Initial revision
authorJeff Hobbs <hobbs@users.sourceforge.net>
Tue, 19 Sep 2000 18:24:43 +0000 (18:24 +0000)
committerJeff Hobbs <hobbs@users.sourceforge.net>
Tue, 19 Sep 2000 18:24:43 +0000 (18:24 +0000)
21 files changed:
README.txt [new file with mode: 0644]
docs/bindings.html [new file with mode: 0755]
docs/changes.txt [new file with mode: 0755]
docs/demopic.gif [new file with mode: 0755]
docs/dump.html [new file with mode: 0755]
docs/idebug.html [new file with mode: 0755]
docs/index.html [new file with mode: 0755]
docs/license.terms [new file with mode: 0755]
docs/limits.html [new file with mode: 0755]
docs/nontcl.html [new file with mode: 0755]
docs/observe.html [new file with mode: 0755]
docs/perl.txt [new file with mode: 0755]
docs/plugin.html [new file with mode: 0755]
docs/procs.html [new file with mode: 0755]
docs/purpose.html [new file with mode: 0755]
docs/start.html [new file with mode: 0755]
docs/tkcon.html [new file with mode: 0755]
docs/todo.html [new file with mode: 0755]
extra/console1_1.tcl [new file with mode: 0644]
extra/stripped.tcl [new file with mode: 0755]
tkcon.tcl [new file with mode: 0755]

diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..7f076ee
--- /dev/null
@@ -0,0 +1,42 @@
+WHAT:   Enhanced Tk Console for all Tk platforms
+
+WHERE:  http://www.purl.org/net/hobbs/tcl/script/tkcon/
+       http://www.hobbs.wservice.com/tcl/script/tkcon/
+       http://www.neosoft.com/tcl/ (somewhere in the devel area)
+
+REQUIREMENTS: Tcl 7.6 / Tk 4.2 (as least the stable versions)
+       Tested through Tcl/Tk8.4.
+        TkCon is all Tcl/Tk code, no compiling required
+
+TkCon is a replacement for the standard console that comes with Tk (on
+Windows/Mac, but also works on Unix).  TkCon provides many more features
+than the standard console and works on all platforms where Tcl/Tk is
+available.  It is meant primarily to aid one when working with the little
+details inside tcl and tk and to give Unix users the GUI console provided
+by default in the Mac and Windows Tk.
+
+FEATURES:
+    Command history
+    Path (Unix style) / Proc / Variable name expansion
+    Multiple consoles, each with its own state (via multiple interpreters)
+    Captures stdout and stderr to console window (puts overridden)
+    Hot errors (click on error result to see stack trace)
+    Electric character matching (a la emacs)
+    Electric proc highlighting
+    Enhanced history searching
+    Configurable
+    Cut / Copy / Paste between windows (interoperates with native platform)
+    Communication between consoles and other Tk interpreters
+        (including non-tcl ones)
+    Works on all Tk platforms
+
+CONTACT: Jeffrey Hobbs, jeff.hobbs at acm.org
+
+GETTING STARTED:
+
+TkCon is a single drop-in file.  On Windows, I place this on the desktop
+and double-click on it instead of wish/tclsh.  On Unix, I place it in a
+known bin directory and run this instead of wish.  I don't have a Mac...
+
+Documentation can be reading by starting with index.html in the docs/
+subdirectory.  Happying Tcl'ing!
diff --git a/docs/bindings.html b/docs/bindings.html
new file mode 100755 (executable)
index 0000000..9f168b0
--- /dev/null
@@ -0,0 +1,130 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Special Bindings</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Special Bindings</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD BGCOLOR=#CCFF99><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+Most of the bindings are the same as for the Text widget.  Some have been
+modified to make sure that the integrity of the console is maintained.
+Others have been added to enhance the usefulness of the console.  Only
+the modified or new bindings are listed here.
+ <P>
+
+<DL compact>
+<DT> <B>Control-x</B> or <B>Cut</B> (on Sparc5 keyboards)
+<DD> Cut
+<DT> <B>Control-c</B> or <B>Copy</B> (on Sparc5 keyboards)
+<DD> Copy
+<DT> <B>Control-v</B> or <B>Paste</B> (on Sparc5 keyboards)
+<DD> Paste
+<DT> <B>Insert</B>
+<DD> Insert (duh).
+ <P>
+<DT> <B>Up</B>
+<DD> Goes up one level in the commands line history when cursor is on the
+prompt line, otherwise it moves through the buffer
+<DT> <B>Down</B>
+<DD> Goes down one level in the commands line history when cursor is on the
+last line of the buffer, otherwise it moves through the buffer
+<DT> <B>Control-p</B>
+<DD> Goes up one level in the commands line history
+<DT> <B>Control-n</B>
+<DD> Goes down one level in the commands line history
+ <P>
+<DT> <B>Tab</B>
+<DD> Tries to expand file path names, then variable names, then proc names.
+<DT> <B>Escape</B>
+<DD> Tries to expand file path names.
+<DT> <B>Control-P</B>
+<DD> Tries to expand procedure names.  The procedure names will be those
+that are actually in the attached interpreter (unless nontcl is specified,
+in which case it always does the lookup in the default slave interpreter).
+<DT> <B>Control-V</B>
+<DD> Tries to expand variable names (those returned by [info vars]).
+It's search behavior is like that for procedure names.
+ <P>
+<DT> <B>Return</B> or <B>Enter</B>
+<DD> Evaluates the current command line if it is a complete command,
+otherwise it just goes to a new line
+<DT> <B>Control-a</B>
+<DD> Go to the beginning of the current command line
+<DT> <B>Control-l</B>
+<DD> Clear the entire console buffer
+<DT> <B>Control-r</B>
+<DD> Searches backwards in the history for a command starting with the
+current command line.  Repeatable to search farther back.
+<DT> <B>Control-s</B>
+<DD> As above, but searches forward (only useful if you searched too far back).
+<DT> <B>Control-t</B>
+<DD> Transposes characters
+<DT> <B>Control-u</B>
+<DD> Clear the current command line
+<DT> <B>Control-z</B>
+<DD> Saves current command line in a buffer that can be retrieved with 
+another <B>Control-z</B>.  If the current command line is empty, then any
+saved command is retrieved without being overwritten, otherwise the
+current contents get swapped with what's in the saved command buffer.
+ <P>
+<DT> <B>Control-Key-1</B>
+<DD> Attaches console to the console's slave interpreter
+<DT> <B>Control-Key-2</B>
+<DD> Attaches console to the console's master interpreter
+<DT> <B>Control-Key-3</B>
+<DD> Attaches console to main TkCon interpreter
+<DT> <B>Control-A</B>
+<DD> Pops up the "About" dialog
+<DT> <B>Control-N</B>
+<DD> Creates a new console.  Each console has separate state, including
+it's own widget hierarchy (it's a slave interpreter).
+<DT> <B>Control-q</B>
+<DD> Close the current console OR Quit the program (depends on the value
+of TKCON(slaveexit)).
+<DT> <B>Control-w</B>
+<DD> Closes the current console.  Closing the main console will exit the
+program (something has to control all the slaves...)
+</DL>
+
+TkCon also has <B>electric bracing</B> (similar to that in emacs).  It will
+highlight matching pairs of {}'s, []'s, ()'s and ""'s.  For the first three,
+if there is no matching left element for the right, then it blinks the
+entire current command line.  For the double quote, if there is no proper
+match then it just blinks the current double quote character.  It does
+properly recognize most escaping (except escaped escapes), but does not look
+for commenting (why would you interactively put comments in?).
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/changes.txt b/docs/changes.txt
new file mode 100755 (executable)
index 0000000..d1f96ab
--- /dev/null
@@ -0,0 +1,811 @@
+ENHANCED TK CONSOLE changes
+-------------------------------------------------------------------------
+Changes file begun Tue May  7 19:09:51 PDT 1996
+Newest changes at top of file.  Release dates between '----'s.
+Changes for a particular version are BELOW the release date line.
+
+Attribution for code is specified after change, a preceding slash
+indicates an idea/bug report attribution fixed by myself.  Where
+no attribution is made, assume (Hobbs).
+-------------------------------------------------------------------------
+
+---- March 31 1999 v1.6 ----
+
+Changed tkConInsert to not use catch (avoids any error generation).
+
+Changed if check on auto_load in tcl_unknown to an llength on the
+args (from [info tclversion]) as 8.0p0 also used just one arg.
+
+Added -exec command line arg, so that users could do the -exec ""
+trick (causes tkcon to skip multi-interpreter model) and makes it
+easier to drop tkcon as a console on extended wish executables.
+
+Changed handling of fixed font for all tkcon text widgets, adding
+new -font option, TKCON(font) var, and redoing 'tkcon font'.
+
+Added color,(disabled|cursor|bg) variables as per Becker's
+recommendations, allowing for old defaults.
+
+Changed multiple instances of string comparisons with llength,
+where appropriate.
+
+Changed dump proc to not try and auto_load a proc arg and improved
+recognition of procs in namespaces.
+
+Added new 'what' proc to environment that tells you what a string
+is recognized as.  Now used in various other procs.
+
+Improved hot errors to not pop up edit dialog when the mouse moved.
+
+---- March 5 1999 v1.5 ----
+
+Expanded tkConSave to support use in 'edit'.
+
+Added tkConGarbageCollect proc for periodic cleanup tasks
+(currently, cleaning up error tags in the console widget),
+with new gc-delay TKCON var.
+
+Revised error handling (errors are now hot in the console).
+
+Changed tkConExpandPathname to recognise that NT for 8.1+ is
+case-sensitive, and to not change case for other Windows configs
+when no further expansion was made.
+
+Made changes to tkConEvalOther and the aliasing of tkConEvalAttached
+for "Main" for more accurate evaluation.
+
+Changed the conditional 'update' in tkcon_puts (that overrides the
+core puts) to 'update idletasks'.  This prevents problems with
+using puts in fileevent triggers and such.
+
+Added check to prevent lower-casing during pathname expansion when
+no further expansion can be made on a string.
+
+New auto-buffer (default 512 lines, set in TKCON(buffer)) for the
+console widget.  Set this ridiculously high if you liked the
+text widget holding all that data.  New tkcon buffer method to
+go with it.
+
+Rewrote edit command.  Previous version was mostly bogus when used
+outside the original slave.
+
+Change tkcon error to use updated 'edit' command.
+
+Massaged tkConEvalOther & tkConInterpEval.
+
+Fixed problem with Show Last Error where a TkCon generated error
+was always appearing (from Package Submenu) and moved it above
+the packages submenu.
+
+Removed auto_execok from the slaveprocs list.
+
+Removed slaveappalias as it didn't work correctly.  Made 'edit'
+a slavealias, with tkConAttach used to determine where it was
+called from
+
+Changed some regexps around to pass tclCheck's mistaken warnings
+(tclCheck's bad matching, not bad regexps).
+
+Changed dump to not try widgets before commands, as otherwise
+it won't automatically complain.
+
+Fixed pathname completion to only beep when trying to expand on a
+non-existent subdirectory (instead of throwing no-directory error).
+
+Fixed a few notes that TclPro's checker picked up (only one actual
+bug in the all switch of 'edit', otherwise it was mostly blowing
+wind...).  (lvirden)
+
+---- February 17 1999 v1.4 ----
+
+Changed "changes" file to "changes.txt".
+
+Added edit/more/less proc that allows for the viewing/editing
+and returning back to the slave of vars/procs or files.
+
+Modified history to not got below 0.
+
+lremove extended with -pattern arg.
+
+Added code in tcl_unknown to ask about loading Tk when someone tries
+a Tk command without Tk being loaded.
+
+Had to change regexps because \E in Tcl8.1a2 was removed in 8.1b1 (arg!).
+
+Added "Make Xauth Secure" button for Unix. (heiko.federhenn@stest.ch)
+
+Fixed tkConInitInterp (used by "Send TkCon Commands") to reattach to
+the named namespace when appropriate.
+
+Fixed bug in popup-menu for Tk8 (bound to wrong toplevel).
+
+Fixed bug in tcl_unknown confusing auto_load between 8.0 and 7.x.
+
+Made Interp->Package menu more dynamic, so it recognizes changes in
+auto_path and updates itself when Interp is torn-off.
+
+Removed list from $new in exec redirect for tcl_unknown. (found by Imai)
+
+Changed package menu to handle multiple package versions.
+
+Added bogus package require statement to master and slaves to ensure
+that pkgIndex.tcl files were properly loaded into interps.
+
+If "Main" is passed to tkConAttachNamespace, it is interpreted as "::".
+
+Changed "Attach Namespace" menu to provide a listbox popup when
+more than $TKCON(maxmenu) namespaces are present.
+
+---- June 1998 v1.3 ----
+
+fixed long-standing expr bug (missing '$') in tkConSafeBind - found
+by TclPro!
+
+took out the use of tkcon_gets because it only worked for global vars.
+
+---- March 1998 v1.2 unreleased ----
+
+updated regexps in some places to support 8.1 regexps.
+
+dump now outputs only non-default options for widgets. (ridgway)
+
+Sorted output list for multiple tab matched items.
+
+Several minor changes for the plugin (user should see no difference).
+
+Known problems with dump command understanding namespaces have been
+fixed, but only for the 8.0 only version.
+
+Changed tkConTagProc to recognize ';' as not part of a proc name.
+
+Changed tkConNew to reuse slave numbers.
+
+Fixed problem with TKCON(exec) == {} (needed uplevel #0 instead of eval).
+
+On Mac, tries to source itself using -rsrc (8.0). (nijtmans)
+
+Changed to use 8.0 menu scheme if possible. (nijtmans)
+
+Changed tkConInitSlave and tkConNew to only set argv0 in new slave if it
+exists (it won't in the plugin).  (demailly)
+
+Changed tkConInit to only checkpoint state once if the slave interp
+and main interp are the same (TKCON(exec) == {}).
+
+---- 08 October 1997 v1.1 ----
+
+For Tk8, made TkCon use a fixed font {Courier, size 10} if the current
+font is not of fixed type.
+
+Startup errors should now be found in the TkCon last error function.
+
+Changed the Triple-1 binding to not include last newline.
+
+Added fix to make sure that double-evaluation of the command line
+didn't occur (might occur for commands that used vwait or something).
+
+TKCON(errorInfo) is now set with all the errors that occur during start-up,
+so that you don't lose stack trace information.
+
+---- July 03 1997 v1.03 ----
+
+Updated namespace eval stuff for Tk8.0b2.
+
+rewrote tkConSepCmd.
+
+ls is now "dir -full" by default.
+
+changed the puts renaming from tcl_puts to tkcon_tcl_puts (so that it
+specifies what renamed it).
+
+added variable highlighting to command highlighting as a background (so
+that a command and var can be seen for the same word).
+
+increased default history size to 48.
+
+Fixed problem where aliased exit couldn't take extra args.
+
+replaced old [tkcon gets] with a new UI version to be used with the new
+tkcon_gets that, like tkcon_puts, replaces the Tcl gets with a version that
+doesn't rely on stdin being present.  [tkcon gets] now accepts no args.
+       **** POTENTIAL INCOMPATIBILITY ****
+
+---- June 10 1997 v1.02 ----
+
+Changed calculator mode commands to be put in the history (but the
+output still looks like an error).
+
+Fixed bug where "source" was assumed to work for primary interp,
+causing failure to load in Tk plugin.
+
+Fixed problem with the id'ing of the primary TkCon interpreter that would
+affect attaching to like named interps.
+
+---- June 8 1997 v1.01 ----
+
+minor streamlining in tkConEvalCmd.
+
+added file menu and separated some items from console menu.
+
+added support for connecting directly to a namespace (itcl or Tcl8).
+
+Fixed several potential problems where args to tkConEvalAttached where
+not properly protected from eval.
+
+added slaveexit variable to allow for exit in slaves to be non-destructive,
+which is the new default.
+
+enhanced Tab binding, made Escape the default pathname-only expansion.
+
+enhanced dump and which commands.
+
+Removed auto_execok redefinition for Tcl7.5-.  TkCon is now intended to
+only run in Tcl7.6+ interpreters (though attaching to 7.5- is still OK).
+
+Added Load/Save menus and expanded Save functionality.
+
+---- June 1 1997 v1.00 ----
+
+TkCon now use virtual events for bindings (REQUIRES TK4.2+) and changed
+Console to TkConsole (to not conflict with new Console megawidget).
+
+Updated tcl_unknown to match Tcl8's unknown.
+
+Changed handling of preferences directory for macintosh.
+       **** POTENTIAL INCOMPATIBILITY ****
+
+Changed tkCon global var to TKCON.
+       **** POTENTIAL INCOMPATIBILITY ****
+
+Changed colors to use absolute #RRGGBB format for color-name disadvantaged
+systems.
+
+Removed use of tkCon(font) variable.
+       **** POTENTIAL INCOMPATIBILITY ****
+
+Fixed procname expansion to work on/in namespaces.
+
+Fixed pathname expansion to expand on a directory.
+
+Fixed all if's to use {}s (better for Tcl8).
+
+Fixed potential paste problems, it now tries to get the general selection
+first, then the CLIPBOARD selection.
+
+Fixed problem with 'puts' being renamed too early.
+
+Added calcmode variable to allow typing expr commands write at the tkCon
+command line without always saying expr (handled in tkConEvalCmd).
+
+---- no official release v0.72 ----
+
+Changed tkConAbout to use text widget so info could be selected.
+
+Fixed problem with pathname expansion on windows due to case insensitivity.
+(how can anyone work with such an insensitive OS?)
+
+Fixed off-by-one error in history substitution reported by
+<s-imai@lsi.tmg.nec.co.jp>.
+
+Fixed error in the handling of packages with a space in the name.
+
+Removed general return of output from rcfile, now only errors are returned.
+
+New tkConEvent proc to handle event movement, fixed search event problem
+where cached event would become incorrect.
+
+new blinkrange variable to change electric bracing style.
+
+---- December 20th 1996 v0.71 ----
+
+changed to not use upvar for nested arrays (bad for Tcl8).
+
+catch package require statement for detecting loadable libraries.
+
+---- November 15th 1996 v0.70 ----
+
+Fixed problem with virtual event C/C/P bindings. (reported by
+robin@jessikat.demon.co.uk)
+
+---- November 15th 1996 v0.69 ----
+
+Added auto_execok to tkCon(slaveprocs), fixes "unknown" command bug.
+
+Fix for 'event' to work with plugin.  (nijtmans)
+
+Added '--' and '-filter' options to 'dump'.
+
+---- November 13th 1996 v0.68 ----
+
+Added $tk_library to auto_path for safe slaves loading Tk. (nijtmans)
+
+Made "r" the default mode for tkConSafeOpen. (nijtmans)
+
+Changed global delcarations in tkConInit to avoid conflicts with
+Nijtmans' plus patch.
+
+---- November 11th 1996 v0.67 ----
+
+Fixed weird backslashing in tkConSafeWindow
+
+---- November 8th 1996 v0.66 ----
+
+Further changes for Tk plugin compatibility. (nijtmans)
+
+---- November 7th 1996 v0.65 ----
+
+Started to add to plugin compatible code.  (nijtmans)
+
+Reworked tkConFind* to accept optional args.
+
+Added History menu which display last ten commands in history.
+
+Removed 'auto_execpath' and changed for new version of 'auto_execok' (in
+'which' and 'unknown'), which will be redefined when TkCon is run in Tcl7.5.
+
+The attached environment is now checkpointed at startup (by default
+this is the slave).
+
+Fixed 'dump var' to use list when printing out nested array elements
+
+Added 'update' to puts, as well as better error reporting for tcl_puts.
+(nijtmans)
+
+Improved bracing around elseif statements.
+
+Removed 'warn' alias from distribution.  Seemed superfluous.
+
+Added support for requiring Tk in Tcl8+.
+
+Made TkCon use tkCon(cols) and tkCon(rows) for startup text size.
+
+---- September 30th 1996 v0.64 ----
+
+Changed the way 'idebug' integrates with TkCon.
+
+Changed to require Tk of version [expr $tcl_version-3.4].
+
+Fixed bug in observe_var (upvar shouldn't have had the \#0).
+
+Made Interp->Inspect menu disappear if TkConInspect package was not present.
+
+Made package handling only enabled for Tcl7.5+ interps and reworked
+how packages were recognized.
+
+! Removed virtual events from Console bindings so that they don't screw
+! up the Console bindings (temporary fix).
+
+Changed how initially loaded packages were detected. (nijtmans)
+
+Made all globals visible in tkConInit. (/nijtmans)
+
+---- September 23rd 1996 v0.63 ----
+
+Changed 'tkConFindBox' to not screw up search string.
+
+---- September 20th 1996 v0.62 ----
+
+Added option for automagically ignoring dead interpreter problems. (wart)
+
+Fixed bug for reattaching to default slave via menu. (wart)
+
+Changed how 'observe' spit out trace info for commands.
+
+Modified 'idebug' internals.
+
+Made 'idebug' create its own tkCon(exec) slave for maintaining history.
+
+Fixed long-standing bug in 'lremove' for -all switch.
+
+Made tkCon(SCRIPT) follow links to the true source script.
+
+Added 'idebug puts' and 'idebug echo' methods.
+
+Fixed 'idebug break' to not work at level 0.
+
+Removed line that could improperly set $name and placed a 'catch'
+around the 'interp alias' for 'ls' in tkConInitInterp.
+
+tkConInit(Slave|Interp) now just 'catch'es the renaming of puts.
+
+Added 'tkcon set' and 'tkcon upvar' methods. (nijtmans)
+
+---- September 17th 1996 v0.61 ----
+
+Added 'idebug' interactive debugging proc based off Stephen Uhler's all-Tcl
+debugger (Oct'95 _Linux_Journal_).  Should work w/ or w/o TkCon.
+
+Added back accidental removal of 'ls' alias in slaves.
+
+---- September 15th 1996 v0.60 ----
+
+Added 'tkcon find str' method and find box to TkCon.
+
+Added 'observe{_var}' command for simple tracing of vars/cmds with
+output in the TkCon console window.
+
+Reworked tkConFillAppsMenu to be more efficient and correct.
+
+Added 'echo' as an internal proc and included it in tkCon(slaveprocs).
+
+Removed tkCon(prompt2).
+
+Changed tkCon(lightcmd) default to 1 from 0.
+
+Improved 'tkcon error' to allow it to check the errorInfo of other apps.
+
+'dump var' now outputs nested array values. (loverso)
+
+Changed tkCon(Load|Save) to use the new Tk4.2 dialogs if available.
+
+Fixed tkConPrompt problem where marks were set incorrectly sometimes
+when it was called by an event (such as <Control-1>).
+
+Added bgerror to slaves and 'tkcon bgerror' method. (nijtmans)
+
+Added tcl_unknown along with other minor mods to get TkCon to work better
+with IncrTcl. (nijtmans)
+
+Made <Triple-1> binding not include the prompt.
+
+Add null Console bindings for the tkCon(root) bindings to avoid them
+getting generated spuriously. (Hobbs / Wart)
+
+Added -argv/-- command line option.  This has very limited use, but is very
+good for wrapping TkCon around an existing application which has it's own
+command line args.  It resets $argv in the main interpreter to what remains
+on the command line and TkCon ignores argv.  This carries over to any "New
+Consoles".
+
+Reintroduced state procedures, placed them in Interp menu.  These should
+only be used if you really understand what they do.
+
+Added 'dump command' method.  Usefulness over 'dump proc' is minimal.
+
+Tightened up the command line args, dropped several optional switches.
+
+Placed all the Console bindings into tkConBindings, which is called
+in tkConInitUI.
+
+Added 'tkConInitInterp' which places the tkCon shell commands (already
+available in any tkCon slave) in the interpreter.  It also rewires
+puts to send the result back to tkCon.
+
+Fixed dead attachment problem where attaching to another interp after
+being connected to a dead interp would munge the new interp's name. (H / Wart)
+
+Added 'tkConEvalOther' which evals in the named interpreter.
+
+Removed 'tkConCheckPackages'.  Package handling is now separated into the
+autoloading part in tkConInit and into tkConInterpMenu which determines
+available static libraries and packages for an interpreter.  Menus redesigned.
+
+Changed 'tkcon eval' to 'tkcon master' since eval gave the wrong connotation.
+
+Made '-nontcl' option take a TCL_BOOLEAN argument.
+
+Made 'which' return unknown commands as an error.
+
+Added button into the help window to send the help URL to netscape.
+
+Made history substitution spit out a correctly translated command if
+evaluation doesn't return an error.
+
+Changed history search to use the same event id as regular command line
+history.
+
+Added tkCon(meta) variable which varies the Meta definition based on the
+platform (Unix == Meta; Win == Alt; Mac == Command)
+
+Added 'dump widget' method.  Spits out current widget state as returned
+by '.widget configure'.
+
+Changed 'dump proc' and 'which' to try and auto_load an unknown procedure.
+
+Added 'tkcon history' command to return a source'able history stack.
+
+Fixed off-by-one error in tkConExpand (caused expansion to not work unless
+you were expanding the last thing on the line and also not if a special
+char was the first on the line).
+
+Fixed TkCon package handling to work properly for IncrTcl. (nijtmans)
+
+---- July 31 1996 v0.52 ----
+
+Reversed changes file to have newest at top.
+
+Added 'tkcon version' command.
+
+Fixed scoping problem when attaching to the master interpreter of a
+particular console.
+
+Rewrote the expansion routines to handle spaces in names better (no longer
+requires the user to use grouping as it puts in '\ ' for spaces).
+
+Fixed off-by-one bug in tkConExpandBestMatch(2).
+
+Rewired attachments so that when 'send' is used to attach to an app and an
+error occurs, TkCon determines whether the app still exists to prevent
+multiple errors from arising due to a dead attachment.  If this occurs, it
+prompts the user on whether to return to the primary slave or to check
+periodically for the attached interpreter to come back.  tkConEvalSend was
+added to facilitate this.
+
+Command highlighting is now only attempted when a non-empty character is
+inserted into the command line (%A != {}).
+
+Added Ctrl-2 accelerator to get attach to master interpreter of a console
+and Ctrl-3 to get to attach to the Main interpreter.
+
+Made the attachment to Main set the tkCon(app) to Main (to get around the
+menu -value {} bug) and also set tkConEvalAttached alias to 'tkConMain eval'.
+
+Rewrote tkConPrompt to accept "pre" and "post" args to place before and
+after the prompt is printed.  pre is tagged stdout, post is tagged stdin.
+
+Rewrote 'dump var' to recognize nested arrays, but not output them
+(it's too complicated to do that in source'able form), as well as
+recognize empty arrays.
+
+Rewrote tkConEvalCmd to keep track of errorInfo when errors occur.
+
+Added 'tkcon error' to display the last errorInfo.
+
+Changed dumpproc and dumpvar to dump (proc|var) ...
+
+Added -root argument to set the tkCon(root) variable explicitly.
+
+Changed the -(slave)eval args to append to rather than set their vars
+so that they can be specified multiple times on the command line.
+
+Added a limit argument to tkConMatch{Quote,Pair}.
+
+Rewrote dumpvar to recognize a single array value name (ie: a(b)).
+
+Renamed default non-Unix resource filename from from tkcon.bat to tkcon.cfg.
+
+No longer 'catch' the renaming of puts in a slave, because we'd want to
+know if that threw an error, although it never should...
+
+---- July 14 1996 v0.51 ----
+
+Removed tkConUsage since it was never called.
+
+Changed tkCon(Load|Save) to use tkFileSelect, if it exists.
+
+Added -load and -pkg equivalents for -package.
+
+Added Ctrl-Key-1 binding to reattach to primary slave.
+
+TkCon now will create itself in a different toplevel if there are already
+children of . when tkConInit is called.
+
+Changed tkConInitSlave not to overwrite tcl_puts in a slave if it exists.
+
+Created tkCon(slaveprocs) to identify what procs get dumped into a
+slave each time and tkCon(slavealias) to identify what will be
+aliased back into the main interpreter.
+
+---- July 4 1996 v0.50 ----
+
+Number of history events to keep now set by tkCon(history).
+
+'unknown' reworked (yet again) to properly handle itself in either the slave
+or another interpreter.  History substition was moved into tkConEvalCmd and
+made an option (via tkCon(subhistory)).
+
+Inlined _dir into dir/ls.  It doesn't save any cycles, but it removes
+the need to manage _dir.
+
+Fixed 'dir/ls -f' to denote executable files with a *.
+
+Fixed dir/ls to not die on 'dir -f <pattern>'. (Thanks to steven@indra.com)
+
+Changed tkConExpand to stop at $ as well.
+
+Changed tkConTagProc binding from Console <KeyRelease> to PostCon <KeyPress>.
+It seems to miss a lot less now.
+
+---- July 3 1996 v0.49 ----
+
+Slight mod to <BackSpace>.
+
+Fixed <Delete> binding to not allow deletions of pre-Prompt text when a
+selection is made.
+
+Fixed tkConEvalCmd to properly send commands to foreign interpreters even
+if $tkCon(nontcl) was set.
+
+Made tkConEvalAttached be some type of alias at all times.
+
+Changed 'slavescript' to 'slaveeval' and added an 'eval' option.
+
+---- June 25 1996 v0.48 ----
+
+Fixed 'alias' problem with multiple args.
+
+Updated binding system to automatically set Console bindings to equivalent
+Text bindings, then redefine what we want.
+
+Updated tkConTagProc to eval in attached slaves.  This can make it
+really slow when attached to foreign interpreters.
+
+---- June 25 1996 v0.47 ----
+
+Fixed tkConExpandBest* to be more accurate ([string first] is only valid
+for us when it returns 0).
+
+Updated tkConExpandPathname to work better for attached interpreters.
+
+Renamed tkExpand* to tkConExpand* (they'd become too TkCon oriented).
+
+Changed tkConEvalCmd to 'list' instead of 'concat' command for attached
+interpreters, and to ignore the whole thing if [string match {} $cmd].
+
+Removed many bindings that were exactly duplicated by "Text" binding.
+
+Added tkCon(blinktime) option to allow user to specify blink duration.
+Value must be at least 100 (millisecs).
+
+Removed tkConUpDownLine.  It never varied from tkTextUpDownLine.
+
+Improved package loading to handle bad pkgIndex.tcl entries.
+
+---- June 21 1996 v0.46 ----
+
+Improved package loading to be correct.
+
+Made 'dir' more Mac/Windows friendly (I hope).
+
+---- June 21 1996 v0.45 (skipped v0.44) ----
+
+Added "Non-Tcl Attachments" preference to disallow sends to interpreters
+which may not understand Tcl (ie - SchemeTk, PerlTk).
+
+Rewrote tkConCheckPackages to allow calling it without a widget reference.
+
+Updated tkConEvalCmd.
+
+Added tkConEvalAttached to evaluate more things in the right place.
+
+Rewrote tkConAttach to allow for attaching directly to slave interpreters
+(no send required).  "Attach Console" menu now lists all slave interpreters
+by slave path (with Tk interp name in ()s), separate from foreign interps.
+
+Add tkConInitSlave to create a TkCon slave.
+
+Renamed tkExpand* to tclExpand*.
+
+Updated 'dir' for better output.
+
+Added command line argument support, rearranged tkConInit to support it.
+
+---- June 18 1996 v0.43 ----
+
+Fixed 'unknown' to work in both slave and master interpreter.
+
+Modified 'dir' to be dumpproc'ed into slave.
+
+Rewrote 'clear' to be dumpproc'ed as well.
+
+Fixed 'puts' bug for slaves.
+
+---- June 17 1996 v0.42 ----
+
+Added extra loop to tkConCheckPackages to account for packages that may
+auto-load Tk itself (like Tix or Tksteal).
+
+---- June 15 1996 v0.41 ----
+
+Added 'warn' as an alias back into the main interpreter.
+
+Fixed documentation leftovers (and updated upgrade.html) to include the
+move of the 'main' and 'slave' commands into 'tkcon'.
+
+Fixed problem in 'clear' command
+
+---- June 14 1996 v0.40 Released ----
+
+OK, I need to add some MAJOR changes here...
+
+Added package handling.
+
+Moved to two-level interpreter model (master control/slave execution).
+
+---- June 13 1996 v0.38 ----
+
+Fixed auto_execpath to work on windows
+
+---- June 11 1996 v0.37 ----
+
+Improved 'tkConResource' to get the right script name on all platforms
+under all manner of circumstances
+
+Improved sourcing of tkCon resource file to not throw bogus errors
+
+---- Jun 10 1996 v0.36 ----
+
+Fixed <Control-n> bug (incr $tkCon(event) --> incr tkCon(event))
+
+---- June 8 1996 v0.35 ----
+
+Removed "Resource" from 'Edit' menu
+
+Rewrote 'clear' to accept percentage level
+
+Fixed <Control-s> forward history search bug
+
+---- June 6 1996 v0.34 ----
+
+Added 'clean' alias to revert a slave to its "pristine" state
+
+Added tkConState* procs to monitor state and be able to revert it
+
+Enhanced 'which' and added an 'auto_execpath' proc.
+
+Removed all known global uses of 'tmp*' variables.
+
+Fixed problem in tkExpandPathname that munged pathnames with spaces.
+
+Fixed problem in many places where spaces in directories and command names
+might get things confused.
+
+Fixed problem with non-interactive slaves.
+
+Commented out binding that recreates a deleted console window.
+
+Add tclindex command.
+
+Added support for -full to ls/dir.
+
+Added command buffer save and command buffer search bindings.
+
+Added Prefs menu.
+
+Changed File menu name to Console.
+
+Removed 'Load/Save File' command from File menu (to easy to source) and
+added 'save' command.
+
+Changed dumpvar to use "array set ..." when outputting array values.
+
+Changed tkCon to use tkcon.rc on non-unix machines.
+
+Revamped tkConInit and source file to make sure nothing specific to tkCon
+was set until an Init proc was called.
+
+---- May 10 1996 Made 0.27 Available to the public ----
+
+---- May 8 1996 Released 0.26 Third semi-public release ----
+
+tkConNew now returns the name of the newly created interpreter.
+
+Added 'main' and 'slave' inter-console communication commands.  Also,
+all slave interpreters become commands in all slave consoles (make sure
+not to name procs "slave#") when created.  tkConOtherInterp proc added
+to handle the communication.
+
+Moved tkConDestroy and tkConNew into new proc tkConMainInit to prevent
+resourcing problems with slave interpreters
+
+Fixed 'puts' bug by removing all 'uplevel subst ...' and placing an
+'eval ...' at the beginning.
+
+---- May 7 1996 Released 0.25 Second semi-public release ----
+
+Discovered bug in puts/output sequence - still searching
+
+Added unalias command, fixed alias command to not unalias commands if
+not enough args were passed
+
+Updated 'unknown' to mirror current tcl7.5 'unknown'
+
+Changed var names inside some procs
+
+Added comments to most procs
+
+Fixed off-by-one bug in tkExpandPathname
+
+---- May 4 1996 Released 0.24 First semi-public release ----
+
+Changes file begun Tue May  7 19:09:51 PDT 1996
diff --git a/docs/demopic.gif b/docs/demopic.gif
new file mode 100755 (executable)
index 0000000..83a9e3a
Binary files /dev/null and b/docs/demopic.gif differ
diff --git a/docs/dump.html b/docs/dump.html
new file mode 100755 (executable)
index 0000000..696a0f1
--- /dev/null
@@ -0,0 +1,77 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: dump procedure</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: <CODE>dump</CODE> procedure</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD BGCOLOR=#CCFF99><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+The <CODE>dump</CODE> command provides a way for the user to spit out
+state information about the interpreter in a Tcl readable (and human
+readable) form.  It takes the general form:
+
+<BLOCKQUOTE>
+<code>dump</code> <b>method</b> <i>?-nocomplain? ?-filter pattern? ?--?
+pattern ?pattern ...?</i>
+</BLOCKQUOTE>
+
+The patterns represent glob-style patterns (as in <code>string match pattern
+$str</code>).  <i>-nocomplain</i> will prevent <code>dump</code> from
+throwing an error if no items matched the pattern.  <i>-filter</i> is
+interpreted as appropriate for the method.  The various methods are:
+
+<DL>
+
+<DT> dump <b>command</b> <i>args</i>
+<DD> Outputs one or more commands.
+
+<DT> dump <b>procedure</b> <i>args</i>
+<DD> Outputs one or more procs in sourceable form.
+
+<DT> dump <b>variable</b> <i>args</i>
+<DD> Outputs the values of variables in sourceable form.  Recognizes nested
+arrays.  The <i>-filter</i> pattern is used as to filter array element
+names and is interepreted as a glob pattern (defaults to {*}).
+It is passed down for nested arrays.
+
+<DT> dump <b>widget</b> <i>args</i>
+<DD> Outputs one or more widgets by giving their configuration options.
+The <i>-filter</i> pattern is used as to filter the config options and
+is interpreted as a case insensitive regexp pattern (defaults to {.*})
+
+</DL>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/idebug.html b/docs/idebug.html
new file mode 100755 (executable)
index 0000000..e557910
--- /dev/null
@@ -0,0 +1,99 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: idebug procedure</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: <CODE>idebug</CODE> procedure</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD BGCOLOR=#CCFF99><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+The <B>idebug</B> command provides an interactive debugging environment for
+procedures via TkCon.  You can place <code>idebug break</code> commands
+into your procedure to create breakpoints.  It will pop up the TkCon
+console and put you into a "debugging" mode.  The <code>body, show &amp;
+trace</code> methods are intended for internal use only.
+ <P>
+
+This procedure is experimental (to say the least).  Comments are encouraged.
+
+<DL>
+
+<DT> <CODE>idebug body</CODE> <I>?level?</I>
+<DD> Prints out the body of the command (if it is a procedure) at the
+specified level.  <i>level</i> defaults to the current level.
+
+<DT> <CODE>idebug break</CODE> <I>?id?</I>
+<DD> Creates a breakpoint within a procedure.  This will only trigger if
+idebug is on and the id matches the pattern.  If so, TkCon will pop to the
+front with the prompt changed to an idebug prompt.  You are given the basic
+ability to observe the call stack an query/set variables or execute Tcl
+commands at any level.  A separate history is maintained in debugging mode.
+
+<DT> <CODE>idebug {echo ?id?}</CODE> <I>?args?</I>
+<DD> Behaves just like <code>echo</code>, but only triggers when idebug is
+on.  You can specify an optional id to further restrict triggering.  If no
+id is specified, it defaults to the name of the command in which the call
+was made.
+
+<DT> <CODE>idebug id</CODE> <I>?id?</I>
+<DD> Query or set the idebug id.  This id is used by other idebug methods
+to determine if they should trigger or not.  The idebug id can be a glob
+pattern and defaults to *.
+
+<DT> <CODE>idebug off</CODE>
+<DD> Turns idebug off.
+
+<DT> <CODE>idebug on</CODE> <I>?id?</I>
+<DD> Turns idebug on.  If <i>id</i> is specified, it sets the id to it.
+
+<DT> <CODE>idebug {puts ?id?}</CODE> <I>args</I>
+<DD> Behaves just like <code>puts</code>, but only triggers when idebug is
+on.  You can specify an optional id to further restrict triggering.  If no
+id is specified, it defaults to the name of the command in which the call
+was made.
+
+<DT> <CODE>idebug show</CODE> <I>type ?level? ?VERBOSE?</I>
+<DD> <i>type</i> must be one of vars, locals or globals.  This method
+will output the variables/locals/globals present in a particular level.
+If VERBOSE is added, then it actually 'dump's out the values as well.
+<i>level</i> defaults to the level in which this method was called.
+
+<DT> <CODE>idebug trace</CODE> <I>?level?</I>
+<DD> Prints out the stack trace from the specified level up to the top
+level.  <i>level</i> defaults to the current level.
+
+</DL>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/index.html b/docs/index.html
new file mode 100755 (executable)
index 0000000..9c9fca8
--- /dev/null
@@ -0,0 +1,53 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Documentation</TITLE>
+
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Documentation (March 1999)</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<H4><A HREF="http://www.purl.org/net/hobbs/tcl/script/tkcon/tkcon.tar.gz">newest tkcon release</A> (tar,gzip'ed)</H4>
+
+<H4><A HREF="demopic.gif">Screenshot</A> (tar,gzip'ed)</H4>
+
+Please <B>read the following pages carefully</B> to fully understand the
+features AND limitations of TkCon.  I'm always open to suggestions for
+improvement.  Send them to my 
+<A HREF="mailto:jeff.hobbs@acm.org">suggestion box</A>.
+ <P>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started:</A></B><BR>
+<SMALL>TkCon resource file and command line options</SMALL></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">New Procedures in TkCon</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE> procedure</A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE> procedure</A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE> procedure</A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE> procedure</A></B></TD>
+</TR>
+</TABLE>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/license.terms b/docs/license.terms
new file mode 100755 (executable)
index 0000000..6928ccb
--- /dev/null
@@ -0,0 +1,40 @@
+                  * COPYRIGHT AND LICENSE TERMS *
+
+(This file blatantly stolen from Tcl/Tk license and adapted - thus assume
+it falls under similar license terms).
+
+This software is copyrighted by Jeffrey Hobbs <jeff.hobbs@acm.org>.  The
+following terms apply to all files associated with the software unless
+explicitly disclaimed in individual files.
+
+The authors hereby grant permission to use, copy, modify, distribute, and
+license this software and its documentation for any purpose, provided that
+existing copyright notices are retained in all copies and that this notice
+is included verbatim in any distributions.  No written agreement, license,
+or royalty fee is required for any of the authorized uses.
+
+IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
+DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
+EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS
+PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO
+OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+MODIFICATIONS.
+
+RESTRICTED RIGHTS: Use, duplication or disclosure by the U.S. government
+is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
+of the Rights in Technical Data and Computer Software Clause as DFARS
+252.227-7013 and FAR 52.227-19.
+
+SPECIAL NOTES:
+
+This software is also falls under the bourbon_ware clause:
+
+ Should you find this software useful in your daily work, you should feel
+ obliged to take the author out for a drink if the opportunity presents
+ itself.  The user may feel exempt from this clause if they are below
+ drinking age or think the author has already partaken of too many drinks.
diff --git a/docs/limits.html b/docs/limits.html
new file mode 100755 (executable)
index 0000000..8c53468
--- /dev/null
@@ -0,0 +1,55 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Limitations</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Limitations</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD BGCOLOR=#FFFF33><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<H3>Limitations:</H3>
+
+TkCon requires Tk4.2+.  Since TkCon is meant to behave like the original Tk
+console, it does not separate itself from the environment (it does not use
+send to function, except when attached to foreign Tk interpreters).  This
+means that it can be can be altered or destroyed by any sourced
+applications, and it will respond to an application's 'exit' call by
+exiting (by default, slave consoles will only close themselves instead of
+exiting the entire TkCon environment).  However, the widget tree of TkCon
+is hidden from the user environment.
+ <P>
+
+Since TkCon is built for cross-platform capability, <font color=#FF0000>in
+Unix/Windows environments it does not have tty/shell behavior</font>.  This
+means programs like <CODE>vi</CODE> and <CODE>less</CODE> (those that rely
+on tty/shell settings) will not function appropriately (currently they may
+hang TkCon).  Programs like <CODE>ls</CODE> and <CODE>more</CODE> will just
+spit output to the TkCon screen without any special control or formatting
+(note that <CODE>ls</CODE> has been rewritten for TkCon).  You also do not
+get any job (process) control outside of what tcl normally can provide.
+Currently there is no way to handle <CODE>stdin</CODE> input.
+ <P>
+
+When connecting to non-Tcl Tk interpreters (ie - PerlTk, SchemeTk, ...),
+you must use the syntax of the target environment.  See my
+<A HREF="nontcl.html">notes on using other Tk-embedded languages</A> for
+more info.
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/nontcl.html b/docs/nontcl.html
new file mode 100755 (executable)
index 0000000..47b3e11
--- /dev/null
@@ -0,0 +1,54 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon for Non-Tcl Users</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon for Non-Tcl Users</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2 BGCOLOR=#FFFF33><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<I>This document is for those users who are trying to use TkCon with a
+non-Tcl based Tk language (ie - SchemeTk, PerlTk, PythonTk...).</I>
+ <P>
+
+TkCon requires <A HREF="http://www.scriptics.com/">Tcl 7.6 / Tk 4.2</A> to
+run (better with 8.0+).  However, it can attach to any language with Tk4+
+embedded into it with the use of the Tk 'send' command.  I have been able
+to succesfully talk to SchemeTk-3.0 and Perl/Tk.  When using TkCon attached
+to these interpreters, you must remember to talk to the connected
+interpreter in its language.
+ <P>
+I welcome further comments from users of Tk-embedded languages on their
+experiences or ideas.  Of course, you can always try to port TkCon in full
+to your language.  I'd like to see the results from any such efforts.
+ <P>
+
+<H3>Special Language Notes:</H3>
+
+<H4>Perl Tk</H4>
+
+Read the man page on Perl/Tk's send command.  You have to define Tk::Receive
+before it will work.
+<A HREF="mailto:lusol@turkey.cc.lehigh.edu">Stephen Lidie
+(lusol@Turkey.CC.Lehigh.EDU)</A> contributed
+a <A HREF="perl.txt">companion Perl/Tk program</A> that does the trick with
+some extras.
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/observe.html b/docs/observe.html
new file mode 100755 (executable)
index 0000000..09defbc
--- /dev/null
@@ -0,0 +1,80 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: observe procedure</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: <CODE>observe</CODE> procedure</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD BGCOLOR=#CCFF99><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+This command provides runtime debugging output for variables and commands
+without the need to edit your code.  For variables, the underlying mechanism
+uses <code>trace</code> and <code>dump var</code>.  For commands, it renames
+the observed procedure and uses a special wrapper procedure.  <b><font
+color="#FF0000">WARNING:</font></b> using this procedure after checkpointing
+state will result in major problems if you clean state because the renamed
+(true) commands will be lost.
+ <P>
+
+This procedure is experimental.  Comments are encouraged.
+
+<DL>
+
+<DT> <CODE>observe command</CODE> <I>cmdname ?maxlevel?</I>
+<DD> This will create a wrapper command which prints out (using
+<code>dump</code>) the call stack to the console.  <i>maxlevel</i>
+represents the maximum number of levels of the call stack which will be
+printed (defaults to 4).
+
+<DT> <CODE>observe cdelete</CODE> <I>cmdname</I>
+<DD> Removes the wrapper around an observed command.
+
+<DT> <CODE>observe cinfo</CODE> <I>cmdname</I>
+<DD> Prints out useless info.
+
+<DT> <CODE>observe variable</CODE> <I>varname operation ?args?</I>
+<DD> Currently a wrapper around trace that uses <code>dump</code> to
+print out the value of the named variable whenever the specified operation
+on that variable occurs (must be read, write or unset).
+
+<DT> <CODE>observe vdelete</CODE> <I>varname operation</I>
+<DD> Deletes the trace wrapper around the named variable.
+
+<DT> <CODE>observe vinfo</CODE> <I>varname</I>
+<DD> Prints out trace info about the named variable.
+
+</DL>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/perl.txt b/docs/perl.txt
new file mode 100755 (executable)
index 0000000..37463b5
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/local/bin/perl -w
+# tkcon.pl - a Perl/Tk "shell" companion for tkcon.tcl.
+#
+# Variable $MW is an object reference to the main window, from which you can
+# create and manipulate child widgets. Variable names beginning with an
+# underscore are reserved for this application.
+#
+# Stephen O. Lidie, 96/08/25
+require 5.002;
+use English;
+use Tk;
+use Tk::Pretty qw(Pretty);
+use Tk::Dialog;
+use strict;
+use subs qw(doit tkcon);
+my($MW, $_TKCON, $_VERSION, $_HELP, $_SHELL, $_TAB, $_PARA, @_ERRORS, $_MES);
+tkcon;                         # main
+sub doit {
+    # Eval some code without use strict constraints.
+    my($code) = @ARG;
+    {
+       no strict;
+       if ($_MES) {
+           $_MES->packForget;
+           $_MES->destroy;
+           $_MES = 0;
+       }
+       @_ERRORS = ();
+       $SIG{'__WARN__'} = sub {push @_ERRORS, @ARG};
+       my $_res = eval $code;
+       push @_ERRORS, $EVAL_ERROR if $EVAL_ERROR;
+       push @_ERRORS, $_res;
+    }
+} # end doit
+sub tkcon {
+    # Nothing fancy here, just create the main window and the help dialog
+    # object, and display a pointer to the help.
+    $_TKCON = 'tkcon.pl';
+    $_VERSION = '0.2';
+    $_SHELL = '/bin/sh';
+    $_SHELL = $ENV{'SHELL'} if $ENV{'SHELL'};
+    $_TAB = 0;
+    $_PARA = '';
+    $MW = MainWindow->new;
+    $MW->title($_TKCON);
+    $MW->iconname($_TKCON);
+    $_HELP = $MW->Dialog(
+       -title      => "$_TKCON Help",
+       -font       => 'fixed',
+       -wraplength => '6i',
+       -justify    => 'left',
+       -text       =>
+           "?    - this text.\n" .
+           "|    - pass arguments to your shell (default /bin/sh).\n" .
+           "p    - use Tk::Pretty to \"pretty-print\" arguments.\n" .
+           "+    - a tab starts/stops multiline input mode.\n" .
+           "exit - quit $_TKCON.\n" .
+           "\nOther input is assumed to be a Perl/Tk command.\n" .
+           "\n\$MW is the MainWindow.\n",
+                        );
+    $_HELP->configure(-foreground => 'blue');
+    $_MES = $MW->Label(-text => "\nEnter ? for help.\n")->pack;
+    MainLoop;
+} # end tkcon
+sub Tk::Receive {
+    shift();
+    $ARG = shift();
+    if (/^\?(.*)/) {           # help
+       $_HELP->Show;
+    } elsif (/^\|(.*)/) {      # bang
+       @_ERRORS = ();
+       push @_ERRORS, `$_SHELL -c $1 2>&1`;
+    } elsif (/^\+$/) {
+       $_TAB++;
+       if ($_TAB % 2) {
+           @_ERRORS = ();
+           $_PARA = '';
+           push @_ERRORS, '+';
+       } else {
+           doit $_PARA;
+       }
+    } else {                   # Perl/Tk command
+       $ARG = "Pretty($1)" if (/^p\s(.*)$/);
+       if ($_TAB % 2) {
+           $_PARA .= $ARG;
+           push @_ERRORS, '+';
+       } else {
+           doit $ARG;
+       }
+    } # ifend
+    return @_ERRORS;
+} # end Tk::Receive
diff --git a/docs/plugin.html b/docs/plugin.html
new file mode 100755 (executable)
index 0000000..253a66e
--- /dev/null
@@ -0,0 +1,66 @@
+<HTML>
+<HEAD>
+<TITLE>Tcl Plugin Stripped TkCon Demo</TITLE>
+</HEAD>
+
+<BODY>
+<H1>Tcl Plugin Stripped TkCon Demo</H1>
+<HR>
+
+<A HREF="/tcl/script/tkcon/">Full TkCon Distribution</A>
+ <P>
+
+This is the full TkCon script when run inside the plugin.  It feels like a
+stripped down version of TkCon, but the only limitations are those
+established by the plugin.  You can test the basic console features and get
+a feel for the mutli-color output.  Below the demo are some ideas to try
+out.  v2 of the plugin is distributed with a megawidget version of TkCon for
+debugging tclets.
+
+<P>
+<embed src="/tcl/script/tkcon/tkcon.tcl" width=600 height=350>
+</P>
+
+Have a look at some of the features: (culled from the
+<A HREF="/tcl/script/tkcon/docs/">full TkCon documentation</A>)
+<UL>
+<LI> <B>Variable / Path / Procedure Name Expansion.</B>  Type in
+<CODE>set tc</CODE> at the prompt.  Hit <I>&lt;Control-Shift-V&gt;</I>.
+<CODE>set tcl_</CODE> should now be visible.
+Hit <I>&lt;Control-Shift-V&gt;</I> again.  You should see the rest of
+the completions printed out for you.  Works the same for procedures
+and files paths (file access restricted from plugin).  Works properly
+when spaces or other funny characters are including in the name.
+
+<LI> <B>Command Highlighting.</B> Note that <CODE>set</CODE> should be in
+green, denoting it is a recognized command in that interpreter.
+
+<LI> <B>Electric Character Matching.</B>  Watch while you type the
+following: <CODE>proc foo { a b } { puts [list $a $b] }</CODE>.  Did you
+notice the blink matching of the braces?  Yes, it's smart.
+
+<LI> <B>Command History.</B>  Use the Up/Down arrows or
+<I>&lt;Control-p&gt;</I>/<I>&lt;Control-n&gt;</I> to peruse the command
+history.  <I>&lt;Control-r&gt;</I>/<I>&lt;Control-s&gt;</I> Actually
+does command history matching (like tcsh or other advanced Unix shells).
+
+<LI> <B>Useful Colorization.</B> Having defined <CODE>foo</CODE> above, type
+in <CODE>foo hey</CODE>.  Note that the error comes back in red.  Go up one
+in the command history and add <CODE> you</CODE> and see that regular
+stdout output comes through in blue (the colors are configurable).
+
+<LI> <B>Cut/Copy/Paste.</B>  You should be able to do that between outside
+windows and TkCon.  The default keys are
+<I>&lt;Control-x&gt;</I>/<I>&lt;Control-c&gt;</I>/<I>&lt;Control-v&gt;</I>.
+
+</UL>
+
+<HR>
+
+<ADDRESS>
+Contact <A HREF="mailto:jeff.hobbs@acm.org">jeff.hobbs@acm.org</A>
+with questions or updated info.
+</ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/procs.html b/docs/procs.html
new file mode 100755 (executable)
index 0000000..2a85eb1
--- /dev/null
@@ -0,0 +1,143 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Procedures</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Procedures</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD BGCOLOR=#CCFF99><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+There are several new procedures introduced in TkCon to improve
+productivity and/or account for lost functionality in the Tcl environment
+that users are used to in native environments.  There are also some
+redefined procedures.  Here is a non-comprehensive list:
+
+<DL COMPACT>
+
+<DT> <B>alias</B> <I>?sourceCmd targetCmd ?arg arg ...??</I>
+<DD> Simple alias mechanism.  It will overwrite existing commands.
+When called without args, it returns current aliases.  Note that TkCon
+makes some aliases for you (in slaves).
+<font color=#FF0000>Don't delete those</font>.
+
+<DT> <B>clear</B> <I>?percentage?</I>
+<DD> Clears the text widget.  Same as the &lt;Control-l&gt; binding, except
+this will accept a percentage of the buffer to clear (1-100, 100 default).
+
+<DT> <B>dir</B> <i>?-all? ?-full? ?-long? ?pattern pattern ...?</i>
+<DD> Cheap way to get directory listings.  Uses glob style pattern matching.
+
+<DT> <B>dump</B> <I>type ?-nocomplain? ?-filter pattern? ?--?
+pattern ?pattern ...?</I>
+<DD> The <CODE>dump</CODE> command provides a way for the user to spit out
+state information about the interpreter in a Tcl readable (and human
+readable) form.
+See <a href="dump.html">further <B>dump</B> docs</a> for details.
+
+<DT> <B>echo</B> <I>?arg arg ...?</I>
+<DD> Concatenates the args and spits the result to the console (stdout).
+
+<DT> <B>edit</B> <I>?-type type? ?-find str? ?-attach interp?</I> arg
+<font size=-1 color=#990033>NEW in v1.4, still under construction</font>
+<DD> Opens an editor with the data from <I>arg</I>.  The optional <I>type</I>
+argument can be one of: <I>proc</I>, <I>var</I> or <I>file</I>.  For
+proc or var, the <I>arg</I> may be a pattern.
+
+<DT> <B>idebug</B> <I>command ?args?</I>
+<DD> Interactive debugging command.
+See <a href="idebug.html">further <B>idebug</B> docs</a> for details.
+
+<DT> <B>lremove</B> <I>?-all? ?-regexp -glob? list items</I>
+<DD> Removes one or more items from a list and returns the new list.  If
+<I>-all</I> is specified, it removes all instances of each item in the
+list.  If <I>-regexp</I> or <I>-glob</I> is specified, it interprets each
+item in the items list as a regexp or glob pattern to match against.
+
+<DT> <B>less</B>
+<DD> Aliased to <B>edit</B>.
+
+<DT> <B>ls</B>
+<DD> Aliased to <B>dir -full</B>.
+
+<DT> <B>more</B>
+<DD> Aliased to <B>edit</B>.
+
+<DT> <B>observe</B> <I>type ?args?</I>
+<DD> This command provides passive runtime debugging output for variables
+and commands.
+See <a href="observe.html">further <B>observe</B> docs</a> for details.
+
+<DT> <B>puts</B> (same options as always)
+<DD> Redefined to put the output into TkCon
+
+<DT> <B>tkcon</B> <I>method ?args?</I>
+<DD> Multi-purpose command.
+See <a href="tkcon.html">further <B>tkcon</B> docs</a> for details.
+
+<DT> <B>tclindex</B> <I>?-extensions patternlist? ?-index TCL_BOOLEAN?
+?-package TCL_BOOLEAN? ?dir1 dir2 ...?</I>
+<DD> Convenience proc to update the tclIndex (controlled by -index switch)
+and/or pkgIndex.tcl (controlled by -package switch) file in the named
+directories based on the given pattern for files.  It defaults to creating
+the tclIndex but not the pkgIndex.tcl file, with the directory defaulting
+to [pwd].  The extension defaults to *.tcl, with *.[info sharelibextension]
+added when -package is true.
+
+<DT> <B>unalias</B> <I>cmd</I>
+<DD> unaliases command
+
+<DT> <B>what</B> <i>string</i>
+<DD> The <CODE>what</CODE> command will identify the word given in
+<i>string</i> in the Tcl environment and return a list of types that
+it was recognized as.  Possible types are: alias, procedure, command,
+variable, directory, file, widget, and executable.  Used by procedures
+<CODE>dump</CODE> and <CODE>which</CODE>.
+
+<DT> <B>which</B> <i>command</i>
+<DD> Like the 'which' command of Unix shells, this will tell you if a
+particular command is known, and if so, whether it is internal or external
+to the interpreter.  If it is an internal command and there is a slot in
+auto_index for it, it tells you the file that auto_index would load.  This
+does not necessarily mean that that is where the file came from, but if it
+were not in the interpreter previously, then that is where the command was
+found.
+
+</DL>
+
+There are several procedures that I use as helpers that some may find
+helpful in there coding (ie - expanding pathnames).  Feel free to lift
+them from the code (but do assign proper attribution).
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/purpose.html b/docs/purpose.html
new file mode 100755 (executable)
index 0000000..a2b0c6c
--- /dev/null
@@ -0,0 +1,63 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Purpose & Features</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Purpose &amp; Features</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD BGCOLOR=#FFFF33><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<H3>Purpose:</H3>
+
+TkCon is a replacement for the standard console that comes with Tk (on
+Windows/Mac, but also works on Unix).  The console itself provides
+<i>many</i> more features than the standard console.  TkCon works on all
+platforms where Tcl/Tk is available.  It is meant primarily to aid one when
+working with the little details inside tcl and tk, giving Unix users the GUI
+console provided by default in the Mac and Windows Tk.  It's also not a bad
+replacement for the default MS-DOS shell (although it needs lots of fine
+tuning).
+ <P>
+See <A HREF="limits.html">Limitations</A> for a good idea of what
+TkCon <B>can't</B> do for you.
+
+<H3>Features:</H3>
+
+Just in case you don't run across them while playing, here are some of the
+extras in TkCon:
+<UL>
+<LI> Command history
+<LI> Path (Unix style) / Proc / Variable name expansion
+<LI> Multiple consoles, each with its own state (via multiple interpreters)
+<LI> Captures <CODE>stdout</CODE> and <CODE>stderr</CODE> to console window
+<LI> Electric character matching (a la emacs)
+<LI> Electric proc highlighting
+<LI> Enhanced history searching
+<LI> Configurable
+<LI> Cut / Copy / Paste between windows
+<LI> Communication between consoles and other Tk interpreters (including
+non-tcl ones)
+<LI> Works on all Tk platforms
+</UL>
+
+Read the <A HREF="index.html">documentation</A> for how to take advantage
+of these features.
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/start.html b/docs/start.html
new file mode 100755 (executable)
index 0000000..957a85e
--- /dev/null
@@ -0,0 +1,313 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: Getting Started</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: Getting Started</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#CCFF99><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+<H3>Resource File:</H3>
+
+TkCon will search for a resource file in "<CODE>$env(HOME)/.tkconrc</CODE>"
+(Unix), "<CODE>$env(HOME)/tkcon.cfg</CODE>" (Windows) or
+"<CODE>$env(PREF_FOLDER)/tkcon.cfg</CODE>" (Macintosh).  On DOS machines,
+"<CODE>$env(HOME)</CODE>" usually refers to "<CODE>C:\</CODE>".  TkCon
+never sources the "<CODE>~/.wishrc</CODE>" file.  The resource file is
+sourced by each new instance of the console.  An example resource file is
+provided below.
+
+<H3>Command Line Arguments</H3>
+
+Except for <CODE>-rcfile</CODE>, command line arguments are handled after
+the TkCon resource file is sourced, but before the slave interpreter or the
+TkCon user interface is initialized.  <CODE>-rcfile</CODE> is handled right
+before it would be sourced, allowing you to specify any alternate file.
+Command line arguments are passed to each new console and will be evaluated
+by each.  To prevent this from happening, you have to say
+<CODE>tkcon main set argv {}; tkcon main set argc 0</CODE>.
+ <P>
+For these options, any unique substring is allowed.
+
+<DL>
+
+<DT> <CODE>-argv</CODE> (also <CODE>--</CODE>)
+<DD> Causes TkCon to stop evaluating arguments and set the remaining args to
+be argv/argc (with <CODE>--</CODE> prepended).  This carries over for any
+further consoles.  This is meant only for wrapping TkCon around programs
+that require their own arguments.
+
+<DT> <CODE>-color,*</CODE> <I>color</I>
+<DD> Sets the requested color type to the specified color for tkcon.
+See the <B>Variables</B> section for the various color,* types.
+
+<DT> <CODE>-eval</CODE> (also <CODE>-main</CODE> or <CODE>-e</CODE>)
+<DD> A tcl script to eval in each main interpreter.  This is evaluated
+after the resource file is loaded and the slave interpreter is created.
+Multiple <CODE>-eval</CODE> switches will be recognized (in order).
+
+<DT> <CODE>-exec</CODE> <I>slavename</I>
+<DD> Sets the named slave that tkcon operates in.  In general, this is only
+useful to set to "" (empty), indicating to tkcon to avoid the
+multi-interpreter model and operate in the main environment.  When this is
+empty, any further arguments will be only used in the first tkcon console
+and not passed onto further new consoles.  This is useful when using tkcon
+as a console for extended wish executables that don't load there commands
+into slave interpreters.
+
+<DT> <CODE>-font</CODE> <I>font</I>
+<DD> Sets the font that tkcon uses for its text windows.  If this isn't
+a fixed width font, tkcon will override it.
+
+<DT> <CODE>-nontcl</CODE> <I>TCL_BOOLEAN</I>
+<DD> Sets <CODE>TKCON(nontcl)</CODE> to <I>TCL_BOOLEAN</I>.  Needed when
+attaching to non-Tcl interpreters.
+
+<DT> <CODE>-package</CODE> <I>package_name</I> (also <CODE>-load</CODE>)
+<DD> Packages to automatically load into the slave interpreters (ie - "Tk").
+
+<DT> <CODE>-rcfile</CODE> <I>filename</I>
+<DD> Specify an alternate tkcon resource file name.
+
+<DT> <CODE>-root</CODE> <I>widgetname</I>
+<DD> Makes the named widget the root name of all consoles (ie - .tkcon).
+
+<DT> <CODE>-slave</CODE> <I>tcl_script</I>
+<DD> A tcl script to eval in each slave interpreter.  This will append
+the one specified in the tkcon resource file, if any.
+
+</DL>
+
+Some examples of tkcon command line startup situations:
+<DL>
+
+<DT> <CODE>megawish tkcon.tcl -exec "" -root .tkcon mainfile.tcl</CODE>
+<DD> Use tkcon as a console for your megawish application.  You can avoid
+starting the line with <CODE>megawish</CODE> if that is the default wish
+that tkcon would use.  The <CODE>-root</CODE> ensures that tkcon will not
+conflict with the 
+
+<DT> <CODE>tkcon.tcl -font "Courier 12" -load Tk</CODE>
+<DD> Use the courier font for tkcon and always load Tk in slave
+interpreters at startup.
+
+<DT> <CODE>tkcon.tcl -rcfile ~/.wishrc -color,bg white</CODE>
+<DD> Use the <CODE>~/.wishrc</CODE> file as the resource file, and
+a white background for tkcon's text widgets.
+
+</DL>
+
+<H3>Variables:</H3>
+
+Certain variables in TkCon can be modified to suit your needs.  It's easiest
+to do this in the resource file, but you can do it when time the program is
+running (and some can be changed via the Prefs menu).  All these are part of
+the master interpreter's global array variable <CODE>TKCON</CODE>.  You can
+'<CODE>tkcon set TKCON</CODE>' when the program is running to check its
+state.  Here is an explanation of certain variables you might change or use:
+
+<DL>
+
+<DT> <CODE>color,bg</CODE>
+<DD> The background color for tkcon text widgets.
+Defaults to the operating system default (determined at startup).
+
+<DT> <CODE>color,blink</CODE>
+<DD> The background color of the electric brace highlighting, if on.
+Defaults to <font color=#FFFF00>yellow</font>.
+
+<DT> <CODE>color,cursor</CODE>
+<DD> The background color for the insertion cursor in tkcon.
+Defaults to <font color=#000000>black</font>.
+
+<DT> <CODE>color,disabled</CODE>
+<DD> The foreground color for disabled menu items.
+Defaults to <font color=#4D4D4D>dark grey</font>.
+
+<DT> <CODE>color,proc</CODE>
+<DD> The foreground color of a recognized proc, if command highlighting is on.
+Defaults to <font color=#008800>dark green</font>.
+
+<DT> <CODE>color,var</CODE>
+<DD> The background color of a recognized var, if command highlighting is on.
+Defaults to <font color=#FFC0D0>pink</font>.
+
+<DT> <CODE>color,prompt</CODE>
+<DD> The foreground color of the prompt as output in the console.
+Defaults to <font color=#8F4433>brown</font>.
+
+<DT> <CODE>color,stdin</CODE>
+<DD> The foreground color of the stdin for the console.
+Defaults to <font color=#000000>black</font>.
+
+<DT> <CODE>color,stdout</CODE>
+<DD> The foreground color of the stdout as output in the console.
+Defaults to <font color=#0000FF>blue</font>.
+
+<DT> <CODE>color,stderr</CODE>
+<DD> The foreground color of stderr as output in the console.
+Defaults to <font color=#FF0000>red</font>.
+ <P>
+
+<DT> <CODE>autoload</CODE>
+<DD> Packages to automatically load into the slave interpreter (ie - 'Tk').
+This is a list.  Defaults to {} (none).
+
+<DT> <CODE>blinktime</CODE>
+<DD> The amount of time (in millisecs) that braced sections should
+<I>blink</I> for.  Defaults to 500 (.5 secs), must be at least 100.
+
+<DT> <CODE>blinkrange</CODE>
+<DD> Whether to blink the entire range for electric brace matching or to
+just blink the actual matching braces (respectively 1 or 0, defaults to 1).
+
+<DT> <CODE>buffer</CODE>
+<DD> The size of the console scroll buffer (in lines).
+Defaults to 512.
+
+<DT> <CODE>calcmode</CODE>
+<DD> Whether to allow <CODE>expr</CODE> commands to be run at the command
+line without prefixing them with <CODE>expr</CODE> (just a convenience).
+
+<DT> <CODE>cols</CODE>
+<DD> Number of columns for the console to start out with.  Defaults to 80.
+
+<DT> <CODE>dead</CODE>
+<DD> What to do with dead connected interpreters.  If <CODE>dead</CODE>
+is <i>leave</i>, TkCon automatically exits the dead interpreter.  If
+<CODE>dead</CODE> is <i>ignore</i> then it remains attached waiting for
+the interpreter to reappear.  Otherwise TkCon will prompt you.
+
+<DT> <CODE>font</CODE>
+<DD> Font to use for tkcon text widgets (also specified with -font).
+Defaults to the system default, or a fixed width equivalent.
+
+<DT> <CODE>history</CODE>
+<DD> The size of the history list to keep.  Defaults to 48.
+
+<DT> <CODE>hoterrors</CODE>
+<DD> Whether hot errors are enabled or not.  When enabled, errors that
+are returned to the console are marked with a link to the error info
+that will pop up in an minimal editor.  This requires more memory because
+each error that occurs will maintain bindings for this feature, as long
+as the error is in the text widget.  Defaults to on.
+
+<DT> <CODE>library</CODE>
+<DD> The path to any tcl library directories (these are appended to the
+auto_path when the after the resource file is loaded in).
+
+<DT> <CODE>lightbrace</CODE>
+<DD> Whether to use the brace highlighting feature or not
+(respectively 1 or 0, defaults to 1).
+
+<DT> <CODE>lightcmd</CODE>
+<DD> Whether to use the command highlighting feature or not
+(respectively 1 or 0, defaults to 1).
+
+<DT> <CODE>maineval</CODE>
+<DD> A tcl script to execute in the main interpreter after the slave
+interpreter is created and the user interface is initialized.
+
+<DT> <CODE>nontcl</CODE>
+<DD> For those who might be using non-Tcl based Tk attachments, set this
+to 1.  It prevents TkCon from trying to evaluate its own Tcl code in an
+attached interpreter.  Also see my <A HREF="nontcl.html">notes for non-Tcl
+based Tk interpreters</A>.
+
+<DT> <CODE>prompt1</CODE>
+<DD> Like tcl_prompt1, except it doesn't require you use '<CODE>puts</CODE>'.
+No equivalent for tcl_prompt2 is available (it's unnecessary IMHO).
+<BR>Defaults to {([file tail [pwd]]) [history nextid] % }.
+
+<DT> <CODE>rcfile</CODE>
+<DD> Name of the resource file.  <CODE>$env(HOME)</CODE> is prepended to
+this.  Defaults to <CODE>.tkconrc</CODE> on Unix and <CODE>tkcon.cfg</CODE>
+otherwise.
+
+<DT> <CODE>rows</CODE>
+<DD> Number of rows for the console to start out with.  Defaults to 20.
+
+<DT> <CODE>scollypos</CODE>
+<DD> Y scrollbar position.  Valid values are <CODE>left</CODE> or
+<CODE>right</CODE>.  Defaults to <CODE>left</CODE>.
+
+<DT> <CODE>showmenu</CODE>
+<DD> Show the menubar on startup (1 or 0, defaults to 1).
+
+<DT> <CODE>showmultiple</CODE>
+<DD> Show multiple matches for path/proc/var name expansion
+(1 or 0, defaults to 1).
+
+<DT> <CODE>slaveeval</CODE>
+<DD> A tcl script to execute in each slave interpreter right after it's
+created.  This allows the user to have user defined info always available
+in a slave.  Example:
+<PRE>  set TKCON(slaveeval) {
+               proc foo args { puts $args }
+               lappend auto_path .
+       }</PRE>
+
+<DT> <CODE>slaveexit</CODE>
+<DD> Allows the prevention of <CODE>exit</CODE> in slaves from exitting
+the entire application.  If it is equal to <CODE>exit</CODE>, exit will
+exit as usual, otherwise it will just close down that interpreter (and
+any children).  Defaults to <VAR>close</VAR>.
+
+<DT> <CODE>subhistory</CODE>
+<DD> Allow history substitution to occur (0 or 1, defaults to 1).  The
+history list is maintained in a single interpreter per TkCon console
+instance.  Thus you have history which can range over a series of attached
+interpreters.
+</DL>
+
+ <P>
+
+An <b>example TkCon resource file</b> might look like:
+<PRE>######################################################
+## My TkCon Resource File
+# Use 'fixed' as my default font (only valid on unix)
+set TKCON(maineval) {
+    set tkcon font fixed
+}
+# Keep 50 commands in history
+set TKCON(history) 50
+# Use a pink prompt
+set TKCON(color,prompt) pink
+######################################################</PRE>
+
+ <p>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/tkcon.html b/docs/tkcon.html
new file mode 100755 (executable)
index 0000000..1da4e8c
--- /dev/null
@@ -0,0 +1,142 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: tkcon procedure</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: <CODE>tkcon</CODE> procedure</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD BGCOLOR=#FFFF33><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="start.html">Getting Started</A></B></TD>
+<TD><B><A HREF="bindings.html">Special Bindings</A></B></TD>
+<TD><B><A HREF="procs.html">Procedures</A></B></TD>
+</TR>
+<TR>
+<TD><B><A HREF="dump.html"><CODE>dump</CODE></A></B></TD>
+<TD BGCOLOR=#CCFF99><B><A HREF="tkcon.html"><CODE>tkcon</CODE></A></B></TD>
+<TD><B><A HREF="idebug.html"><CODE>idebug</CODE></A></B></TD>
+<TD><B><A HREF="observe.html"><CODE>observe</CODE></A></B></TD>
+</TR>
+</TABLE>
+
+ <P>
+This provides lots of useful control over a console:
+
+<DL>
+
+<DT> <CODE>tkcon attach</CODE> <I>interpreter</I>
+<DD> Attaches TkCon to the named interpreter.  The name must be that
+returned by <CODE>[tk appname]</CODE> or a valid path to a slave
+interpreter.  It's best to use this via the <CODE>Console->Attach
+Console</CODE> menu.
+
+<DT> <CODE>tkcon buffer</CODE> ?<I>size</I>?
+<DD> Sets or queries the allowed size of the console text widget in lines.
+The text widget will automatically delete leading lines once this number
+has been exceeded (read: this is the scroll buffer size).
+
+<DT> <CODE>tkcon bgerror</CODE> ?<I>msg errorInfo</I>?
+<DD> Does bgerror stuff in the TkCon master interpreter.
+
+<DT> <CODE>tkcon close</CODE> or <CODE>tkcon destroy</CODE>
+<DD> Destroys this TkCon widget.
+
+<DT> <CODE>tkcon console</CODE> <I>args</I>
+<DD> Passes the args to the TkCon text widget (the console).
+
+<DT> <CODE>tkcon error</CODE>
+<DD> Pops up a dialog that gives the user a full trace of the last error
+received in the TkCon console.
+
+<DT> <CODE>tkcon find</CODE> <I>string ?-case TCL_BOOLEAN
+-regexp TCL_BOOLEAN?</I>
+<DD> Highlights all instances of <I>string</I> in the console.  If the string
+is empty, it clears any previous highlighting.
+
+<DT> <CODE>tkcon font</CODE> ?<I>fontname</I>?
+<DD> Sets or returns the font used by tkcon text widgets.
+
+<DT> <CODE>tkcon gets</CODE> ?<I>varname</I>?
+<DD> Behaves like the traditional Tcl <code>gets</code>, but uses the
+TkCon console instead of <code>stdin</code>.
+
+<DT> <CODE>tkcon hide</CODE>
+<DD> Withdraw the TkCon display from the screen (make sure you have
+a way to get it back).
+
+<DT> <CODE>tkcon history</CODE> ?<i>-newline</i>?
+<DD> Displays the TkCon history in sourceable form.  If <i>-newline</i> is
+specified, it separates each command by an extra newline.
+
+<DT> <CODE>tkcon iconify</CODE>
+<DD> Iconifies the TkCon display.
+
+<DT> <CODE>tkcon load</CODE> <I>filename</I>
+<DD> Sources named file into the slave interpreter.  If no filename is
+given, it will attempt to call <CODE>tk_getOpenFile</CODE> to pop up the
+file select box.
+
+<DT> <CODE>tkcon main</CODE> ?<I>arg arg ...</I>?
+<DD> Passes the args to the main TkCon interpreter to be evaluated and
+returns the result.
+
+<DT> <CODE>tkcon master</CODE> <I>args</I>
+<DD> Passes the args to the master interpreter to be evaluated and
+returns the result.
+
+<DT> <CODE>tkcon new</CODE>
+<DD> Creates a new TkCon widget.
+
+<DT> <CODE>tkcon save</CODE> ?<I>filename</I> ?<I>type</I>??
+<DD> Saves the console buffer to the given filename.  If no filename is
+given, it will attempt to call <CODE>tk_getSaveFile</CODE> to pop up the
+file select box.  If no type is given, a dialog will ask you to specify
+what portion of the text you want to save.
+
+<DT> <CODE>tkcon set</CODE> <I>var ?value?</I>
+<DD> Queries or sets a master interpreter variable.
+
+<DT> <CODE>tkcon append</CODE> <I>var ?value?</I>
+<DD> Like set, but uses <CODE>append</CODE> on the variable.
+
+<DT> <CODE>tkcon lappend</CODE> <I>var ?value?</I>
+<DD> Like set, but uses <CODE>lappend</CODE> on the variable.
+
+<DT> <CODE>tkcon show</CODE> or <CODE>tkcon deiconify</CODE>
+<DD> Redisplays TkCon on the screen.
+
+<DT> <CODE>tkcon slave</CODE> ?<I>slavename ?arg arg ...?</I>?
+<DD> If called with no args, it returns the name of all the TkCon
+interpreters.  Otherwise given an interp name it passes the args
+to the named interpreter to be evaluated and returns the result.
+If no args are passed, then it returns the <CODE>[tk appname]</CODE>
+of that interpreter.
+
+<DT> <CODE>tkcon title</CODE> ?<I>title</I>?
+<DD> Sets or returns the title for TkCon.
+
+<DT> <CODE>tkcon version</CODE>
+<DD> Returns of version of TkCon.
+
+</DL>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/docs/todo.html b/docs/todo.html
new file mode 100755 (executable)
index 0000000..6415e19
--- /dev/null
@@ -0,0 +1,76 @@
+<HTML>
+<HEAD>
+<TITLE>TkCon: To Do Ideas</TITLE>
+</HEAD>
+
+<BODY BGCOLOR=#FFFFFF>
+<H1>TkCon: To Do Ideas</H1>
+
+<TABLE COLS=4 BORDER=0 CELLPADDING=1 CELLSPACING=3 BGCOLOR=#CCCCCC>
+<TR>
+<TD><B><A HREF="index.html">TkCon Docs</A></B></TD>
+<TD><B><A HREF="purpose.html">Purpose &amp; Features</A></B></TD>
+<TD><B><A HREF="limits.html">Limitations</A></B></TD>
+<TD BGCOLOR=#FFFF33><B><A HREF="todo.html">To&nbsp;Do</A></B></TD>
+</TR>
+<TD><B><A HREF="changes.txt">Changes</A></B></TD>
+<TD><B><A HREF="license.terms">License Terms</A></B></TD>
+<TD COLSPAN=2><B><A HREF="nontcl.html">Using TkCon with other Tk Languages</A></B></TD>
+</TR>
+</TABLE>
+
+<H3>Future Ideas</H3>
+
+<UL>
+<LI> Add encoding auto-conversion to exec commands
+<LI> keep history file, also keep history of sourced files
+<LI> <PRE>set mimetype(extension,au) "audio/u-law"
+set mimetype(extension,wav) "audio/wave"
+set mimetype(extension,mid) "audio/midi"
+/etc/magic
+proc run {file} {
+    global mimetype
+
+    if {[file executable $file]} {
+        exec $file
+        return
+    }
+
+    catch {set mimetype $mimetype(extension,[file extension $file])}
+
+    if {![info exists mimetype]} {
+        set mimetype $mimetype(magic,[exec /bin/file $file])
+    }
+
+    exec $mimetype(application,$mimetype) $file
+}</PRE>
+
+<LI> Add socket level communication model
+<LI> Enhance the true debugging capabilities - I'm looking at
+tcl-debug and into what I can adopt from the tkInspect philosophy.
+<LI> I'm taking ideas...
+</UL>
+
+<H3>Known Bugs/Quirks</H3>
+
+<UL>
+<LI> Command highlighting isn't perfect because I try to make it too
+efficient.
+<LI> All interpreters have the same current working directory.  This is
+a limitation of tcl.
+<LI> You can't 'attach' on machines where <CODE>send</CODE> does not exist.
+<A HREF="http://www.osf.org/~loverso/">John Loverso</A> has a comm.tcl
+replacement.
+In any case, you can still attach to internal interpreters and namespaces.
+<LI> Need to clean up checkpointed states when the associated interp dies.
+Works with slaves, but not foreign interps.
+<LI> Can't identify non-Tcl or pre-Tk4 interpreters automagically...
+<LI> You tell me...
+</UL>
+
+<HR NOSHADE SIZE=1>
+<ADDRESS><FONT SIZE=2>&copy;
+<A HREF="mailto:jeff.hobbs@acm.org">Jeffrey Hobbs</A></FONT></ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/extra/console1_1.tcl b/extra/console1_1.tcl
new file mode 100644 (file)
index 0000000..78975f0
--- /dev/null
@@ -0,0 +1,2209 @@
+##
+## Copyright 1996-1997 Jeffrey Hobbs
+##
+## source standard_disclaimer.tcl
+## source beer_ware.tcl
+##
+## Based off previous work for TkCon
+##
+
+##------------------------------------------------------------------------
+## PROCEDURE
+##     console
+##
+## DESCRIPTION
+##     Implements a console mega-widget
+##
+## ARGUMENTS
+##     console <window pathname> <options>
+##
+## OPTIONS
+##     (Any toplevel widget option may be used in addition to these)
+##
+##  -blinkcolor color                  DEFAULT: yellow
+##     Specifies the background blink color for brace highlighting.
+##     This doubles as the highlight color for the find box.
+##
+##  -blinkrange TCL_BOOLEAN            DEFAULT: 1
+##     When doing electric brace matching, specifies whether to blink
+##     the entire range or just the matching braces.
+##
+##  -proccolor color                   DEFAULT: darkgreen
+##     Specifies the color to highlight recognized procs.
+##
+##  -promptcolor color                 DEFAULT: brown
+##     Specifies the prompt color.
+##
+##  -stdincolor color                  DEFAULT: black
+##     Specifies the color for "stdin".
+##     This doubles as the console foreground color.
+##
+##  -stdoutcolor color                 DEFAULT: blue
+##     Specifies the color for "stdout".
+##
+##  -stderrcolor color                 DEFAULT: red
+##     Specifies the color for "stderr".
+##
+##  -blinktime delay                   DEFAULT: 500
+##     For electric brace matching, specifies the amount of time to
+##     blink the background for.
+##
+##  -cols ##                           DEFAULT: 80
+##     Specifies the startup width of the console.
+##
+##  -grabputs TCL_BOOLEAN              DEFAULT: 1
+##     Whether this console should grab the "puts" default output
+##
+##  -lightbrace TCL_BOOLEAN            DEFAULT: 1
+##     Specifies whether to activate electric brace matching.
+##
+##  -lightcmd TCL_BOOLEAN              DEFAULT: 1
+##     Specifies whether to highlight recognized commands.
+##
+##  -rows ##                           DEFAULT: 20
+##     Specifies the startup height of the console.
+##
+##  -scrollypos left|right             DEFAULT: right
+##     Specified position of the console scrollbar relative to the text.
+##
+##  -showmultiple TCL_BOOLEAN          DEFAULT: 1
+##     For file/proc/var completion, specifies whether to display
+##     completions when multiple choices are possible.
+##
+##  -showmenu TCL_BOOLEAN              DEFAULT: 1
+##     Specifies whether to show the menubar.
+##
+##  -subhistory TCL_BOOLEAN            DEFAULT: 1
+##     Specifies whether to allow substitution in the history.
+##
+## RETURNS: the window pathname
+##
+## BINDINGS (these are the bindings for Console, used in the text widget)
+##
+## <<Console_ExpandFile>>      <Key-Tab>
+## <<Console_ExpandProc>>      <Control-Shift-Key-P>
+## <<Console_ExpandVar>>       <Control-Shift-Key-V>
+## <<Console_Tab>>             <Control-Key-i>
+## <<Console_Eval>>            <Key-Return> <Key-KP_Enter>
+##
+## <<Console_Clear>>           <Control-Key-l>
+## <<Console_KillLine>>                <Control-Key-k>
+## <<Console_Transpose>>       <Control-Key-t>
+## <<Console_ClearLine>>       <Control-Key-u>
+## <<Console_SaveCommand>>     <Control-Key-z>
+##
+## <<Console_Previous>>                <Key-Up>
+## <<Console_Next>>            <Key-Down>
+## <<Console_NextImmediate>>   <Control-Key-n>
+## <<Console_PreviousImmediate>>       <Control-Key-p>
+## <<Console_PreviousSearch>>  <Control-Key-r>
+## <<Console_NextSearch>>      <Control-Key-s>
+##
+## <<Console_Exit>>            <Control-Key-q>
+## <<Console_New>>             <Control-Key-N>
+## <<Console_Close>>           <Control-Key-w>
+## <<Console_About>>           <Control-Key-A>
+## <<Console_Help>>            <Control-Key-H>
+## <<Console_Find>>            <Control-Key-F>
+##
+## METHODS
+##     These are the methods that the console megawidget recognizes.
+##
+## configure ?option? ?value option value ...?
+## cget option
+##     Standard tk widget routines.
+##
+## load ?filename?
+##     Loads the named file into the current interpreter.
+##     If no file is specified, it pops up the file requester.
+##
+## save ?filename?
+##     Saves the console buffer to the named file.
+##     If no file is specified, it pops up the file requester.
+##
+## clear ?percentage?
+##     Clears a percentage of the console buffer (1-100).  If no
+##     percentage is specified, the entire buffer is cleared.
+##
+## error
+##     Displays the last error in the interpreter in a dialog box.
+##
+## hide
+##     Withdraws the console from the screen
+##
+## history ?-newline?
+##     Prints out the history without numbers (basically providing a
+##     list of the commands you've used).
+##
+## show
+##     Deiconifies and raises the console
+##
+## subwidget widget
+##     Returns the true widget path of the specified widget.  Valid
+##     widgets are console, scrolly, menubar.
+##
+## NAMESPACE & STATE
+##     The megawidget creates a global array with the classname, and a
+## global array which is the name of each megawidget created.  The latter
+## array is deleted when the megawidget is destroyed.
+##     The procedure console and those beginning with Console are
+## used.  Also, when a widget is created, commands named .$widgetname
+## and Console$widgetname are created.
+##
+## EXAMPLE USAGE:
+##
+## console .con -rows 24 -showmenu false
+##
+##------------------------------------------------------------------------
+
+package require Tk
+
+proc megawidget {CLASS} {
+  upvar \#0 $CLASS class
+
+  foreach o [array names class -*] {
+    foreach {name cname val} $class($o) {
+      if [string match -* $name] continue
+      option add *$CLASS.$name [uplevel \#0 [list subst $val]] widgetDefault
+    }
+  }
+  set class(class) $CLASS
+
+  bind $CLASS <Destroy> "catch {${CLASS}_destroy %W}"
+
+  ;proc $CLASS:eval {w method args} {
+    upvar \#0 $w data
+    set class [winfo class $w]
+    if [string match {} [set arg [info command ${class}_$method]]] {
+      set arg [info command ${class}_$method*]
+    }
+    set num [llength $arg]
+    if {$num==1} {
+      return [uplevel $arg [list $w] $args]
+    } elseif {$num} {
+      return -code error "ambiguous option \"$method\""
+    } elseif {[catch {uplevel [list $data(cmd) $method] $args} err]} {
+      return -code error $err
+    } else {
+      return $err
+    }
+  }
+
+  ;proc ${CLASS}_destroy w {
+    upvar \#0 $w data
+    catch { [winfo class $w]:destroy $w }
+    catch { rename $w {} }
+    catch { rename $data(cmd) {} }
+    catch { unset data }
+  }
+
+  ;proc ${CLASS}_cget {w args} {
+    if {[llength $args] != 1} {
+      return -code error "wrong \# args: should be \"$w cget option\""
+    }
+    upvar \#0 $w data [winfo class $w] class
+    if {[info exists class($args)] && [string match -* $class($args)]} {
+      set args $class($args)
+    }
+    if [string match {} [set arg [array names data $args]]] {
+      set arg [array names data ${args}*]
+    }
+    set num [llength $arg]
+    if {$num==1} {
+      return $data($arg)
+    } elseif {$num} {
+      return -code error "ambiguous option \"$args\""
+    } elseif {[catch {$data(cmd) cget $args} err]} {
+      return -code error $err
+    } else {
+      return $err
+    }
+  }
+
+  ;proc ${CLASS}_configure {w args} {
+    upvar \#0 $w data [winfo class $w] class
+
+    set num [llength $args]
+    if {$num==1} {
+      if {[info exists class($args)] && [string match -* $class($args)]} {
+       set args $class($args)
+      }
+      if [string match {} [set arg [array names data $args]]] {
+       set arg [array names data ${args}*]
+      }
+      set num [llength $arg]
+      if {$num==1} {
+       return [list $arg $class($arg) $data($arg)]
+      } elseif {$num} {
+       return -code error "ambiguous option \"$args\""
+      } elseif {[catch {$data(cmd) config $args} err]} {
+       return -code error $err
+      } else {
+       return $err
+      }
+    } elseif {$num} {
+      for {set i 0} {$i<$num} {incr i} {
+       set key [lindex $args $i]
+       if {[info exists class($key)] && [string match -* $class($key)]} {
+         set key $class($key)
+       }
+       if [string match {} [set arg [array names data $key]]] {
+         set arg [array names data $key*]
+       }
+       set val [lindex $args [incr i]]
+       set len [llength $arg]
+       if {$len==1} {
+         $class(class):configure $w $arg $val
+       } elseif {$len} {
+         return -code error "ambiguous option \"$args\""
+       } elseif {[catch {$data(cmd) configure $key $val} err]} {
+         return -code error $err
+       }
+      }
+      return
+    } else {
+      set conf [$data(cmd) config]
+      foreach i [array names data -*] {
+       lappend conf "$i $class($i) [list $data($i)]"
+      }
+      return [lsort $conf]
+    }
+  }
+
+  ;proc $CLASS:configure {w key value}  {
+    puts "$w: $key configured to [list $value]"
+  }
+
+  return $CLASS
+}
+
+foreach pkg [info loaded {}] {
+  set file [lindex $pkg 0]
+  set name [lindex $pkg 1]
+  if {![catch {set version [package require $name]}]} {
+    if {[string match {} [package ifneeded $name $version]]} {
+      package ifneeded $name $version "load [list $file $name]"
+    }
+  }
+}
+catch {unset file name version}
+
+set Console(WWW) [info exists embed_args]
+
+array set Console {
+  -blinkcolor  {blinkColor     BlinkColor      yellow}
+  -blinkrange  {blinkRange     BlinkRange      1}
+  -proccolor   {procColor      ProcColor       darkgreen}
+  -promptcolor {promptColor    PromptColor     brown}
+  -stdincolor  {stdinColor     StdinColor      black}
+  -stdoutcolor {stdoutColor    StdoutColor     blue}
+  -stderrcolor {stderrColor    StderrColor     red}
+
+  -blinktime   {blinkTime      BlinkTime       500}
+  -cols                {columns        Columns         80}
+  -grabputs    {grabPuts       GrabPuts        0}
+  -lightbrace  {lightBrace     LightBrace      1}
+  -lightcmd    {lightCmd       LightCmd        1}
+  -rows                {rows           Rows            20}
+  -scrollypos  {scrollYPos     ScrollYPos      right}
+  -showmultiple        {showMultiple   ShowMultiple    1}
+  -showmenu    {showMenu       ShowMenu        1}
+  -subhistory  {subhistory     SubHistory      1}
+
+  active       {}
+  version      1.2
+  release      {February 1997}
+  contact      {jhobbs@cs.uoregon.edu}
+  docs         {http://www.sunlabs.com/tcl/plugin/}
+  slavealias   { console }
+  slaveprocs   { alias dir dump lremove puts echo unknown tcl_unknown which }
+}
+
+if [string compare unix $tcl_platform(platform)] {
+  set Console(-font) {font     Font    {Courier 14}}
+} else {
+  set Console(-font) {font     Font    fixed}
+}
+
+if $Console(WWW) {
+  set Console(-prompt) {prompt Prompt  {\[history nextid\] % }}
+} else {
+  set Console(-prompt) {prompt Prompt  \
+      {(\[file tail \[pwd\]\]) \[history nextid\] % }}
+}
+
+megawidget Console
+
+## console -
+# ARGS:        w       - widget pathname of the Console console
+#      args
+# Calls:       ConsoleInitUI
+# Outputs:     errors found in Console resource file
+##
+proc console {W args} {
+  set CLASS Console
+  upvar \#0 $W data $CLASS class
+  if {[winfo exists $W]} {
+    catch {eval destroy [winfo children $W]}
+  } else {
+    toplevel $W -class $CLASS
+  }
+  wm withdraw $W
+  wm title $W "Console $class(version)"
+
+  ## User definable options
+  foreach o [array names class -*] {
+    if [string match -* $class($o)] continue
+    set data($o) [option get $W [lindex $class($o) 0] $CLASS]
+  }
+
+  global auto_path tcl_pkgPath tcl_interactive
+  set tcl_interactive 1
+
+  ## Private variables
+  array set data {
+    appname {} cmdbuf {} cmdsave {} errorInfo {}
+    event 1 histid 0 find {} find,case 0 find,reg 0
+  }
+  array set data [list class $CLASS cmd $CLASS$W \
+      menubar  $W.bar \
+      console  $W.text \
+      scrolly  $W.sy \
+      ]
+
+  rename $W $data(cmd)
+  if {[string comp {} $args] && \
+      [catch {eval ${CLASS}_configure $W $args} err]} {
+    catch {destroy $W}
+    catch {unset data}
+    return -code error $err
+  }
+  ;proc $W args "eval $CLASS:eval [list $W] \$args"
+
+  if {![info exists tcl_pkgPath]} {
+    set dir [file join [file dirname [info nameofexec]] lib]
+    if [string comp {} [info commands @scope]] {
+      set dir [file join $dir itcl]
+    }
+    catch {source [file join $dir pkgIndex.tcl]}
+  }
+  catch {tclPkgUnknown dummy-name dummy-version}
+
+  ## Menus
+  frame $data(menubar) -relief raised -bd 2
+  set c [text $data(console) -font $data(-font) -wrap char -setgrid 1 \
+      -yscrollcomm [list $W.sy set] -foreground $data(-stdincolor) \
+      -width $data(-cols) -height $data(-rows)]
+  bindtags $W [list $W all]
+  bindtags $c [list $c PreCon Console PostCon $W all]
+  scrollbar $data(scrolly) -takefocus 0 -bd 1 -command "$c yview"
+
+  ConsoleInitMenus $W
+
+  if $data(-showmenu) { pack $data(menubar) -fill x }
+  pack $data(scrolly) -side $data(-scrollypos) -fill y
+  pack $c -fill both -expand 1
+
+  Console:prompt $W "console display active\n"
+
+  foreach col {prompt stdout stderr stdin proc} {
+    $c tag configure $col -foreground $data(-${col}color)
+  }
+  $c tag configure blink -background $data(-blinkcolor)
+  $c tag configure find -background $data(-blinkcolor)
+
+  bind $c <Configure> {
+    set W [winfo toplevel %W]
+    scan [wm geometry $W] "%%dx%%d" $W\(-cols\) $W\(-rows\)
+  }
+  wm deiconify $W
+  focus -force $c
+
+  return $W
+}
+
+;proc Console:configure { W key val } {
+  upvar \#0 $W data
+  global Console
+
+  set truth {^(1|yes|true|on)$}
+  switch -- $key {
+    -blinkcolor                {
+      $data(console) tag config blink -background $val
+      $data(console) tag config find -background $val
+    }
+    -proccolor         { $data(console) tag config proc   -foreground $val }
+    -promptcolor       { $data(console) tag config prompt -foreground $val }
+    -stdincolor                {
+      $data(console) tag config stdin  -foreground $val
+      $data(console) config -foreground $val
+    }
+    -stdoutcolor       { $data(console) tag config stdout -foreground $val }
+    -stderrcolor       { $data(console) tag config stderr -foreground $val }
+
+    -blinktime         {
+      if ![regexp {[0-9]+} $val] {
+       return -code error "$key option requires an integer value"
+      }
+    }
+    -cols              {
+      if [winfo exists $data(console)] { $data(console) config -width $val }
+    }
+    -font              { $data(console) config -font $val }
+    -grabputs          {
+      set val [regexp -nocase $truth $val]
+      if $val {
+       set Console(active) [linsert $Console(active) 0 $W]
+      } else {
+       set Console(active) [lremove -all $Console(active) $W]
+      }
+    }
+    -lightbrace                { set val [regexp -nocase $truth $val] }
+    -lightcmd          { set val [regexp -nocase $truth $val] }
+    -prompt            {
+      if [catch {uplevel \#0 [list subst $val]} err] {
+       return -code error "\"$val\" threw an error:\n$err"
+      }
+    }
+    -rows              {
+      if [winfo exists $data(console)] { $data(console) config -height $val }
+    }
+    -scrollypos                {
+      if [regexp {^(left|right)$} $val junk val] {
+       if [winfo exists $data(scrolly)] {
+         pack config $data(scrolly) -side $val
+       }
+      } else {
+       return -code error "bad option \"$val\": must be left or right"
+      }
+    }
+    -showmultiple      { set val [regexp -nocase $truth $val] }
+    -showmenu          {
+      set val [regexp -nocase $truth $val]
+      if [winfo exists $data(menubar)] {
+       if $val {
+         pack $data(menubar) -fill x -before $data(console) \
+             -before $data(scrolly)
+       } else { pack forget $data(menubar) }
+      }
+    }
+    -subhistory                { set val [regexp -nocase $truth $val] }
+  }
+  set data($key) $val
+}
+
+;proc Console:destroy W {
+  global Console
+  set Console(active) [lremove $Console(active) $W]
+}
+
+## ConsoleEval - evaluates commands input into console window
+## This is the first stage of the evaluating commands in the console.
+## They need to be broken up into consituent commands (by ConsoleCmdSep) in
+## case a multiple commands were pasted in, then each is eval'ed (by
+## ConsoleEvalCmd) in turn.  Any uncompleted command will not be eval'ed.
+# ARGS:        w       - console text widget
+# Calls:       ConsoleCmdGet, ConsoleCmdSep, ConsoleEvalCmd
+## 
+;proc ConsoleEval {w} {
+  ConsoleCmdSep [ConsoleCmdGet $w] cmds cmd
+  $w mark set insert end-1c
+  $w insert end \n
+  if [llength $cmds] {
+    foreach c $cmds {ConsoleEvalCmd $w $c}
+    $w insert insert $cmd {}
+  } elseif {[info complete $cmd] && ![regexp {[^\\]\\$} $cmd]} {
+    ConsoleEvalCmd $w $cmd
+  }
+  $w see insert
+}
+
+## ConsoleEvalCmd - evaluates a single command, adding it to history
+# ARGS:        w       - console text widget
+#      cmd     - the command to evaluate
+# Calls:       Console:prompt
+# Outputs:     result of command to stdout (or stderr if error occured)
+# Returns:     next event number
+## 
+;proc ConsoleEvalCmd {w cmd} {
+  ## HACK to get $W as we need it
+  set W [winfo parent $w]
+  upvar \#0 $W data
+
+  $w mark set output end
+  if [string comp {} $cmd] {
+    set err 0
+    if $data(-subhistory) {
+      set ev [ConsoleEvalSlave history nextid]
+      incr ev -1
+      if {[string match !! $cmd]} {
+       set err [catch {ConsoleEvalSlave history event $ev} cmd]
+       if !$err {$w insert output $cmd\n stdin}
+      } elseif {[regexp {^!(.+)$} $cmd dummy event]} {
+       ## Check last event because history event is broken
+       set err [catch {ConsoleEvalSlave history event $ev} cmd]
+       if {!$err && ![string match ${event}* $cmd]} {
+         set err [catch {ConsoleEvalSlave history event $event} cmd]
+       }
+       if !$err {$w insert output $cmd\n stdin}
+      } elseif {[regexp {^\^([^^]*)\^([^^]*)\^?$} $cmd dummy old new]} {
+       if ![set err [catch {ConsoleEvalSlave history event $ev} cmd]] {
+         regsub -all -- $old $cmd $new cmd
+         $w insert output $cmd\n stdin
+       }
+      }
+    }
+    if $err {
+      $w insert output $cmd\n stderr
+    } else {
+      if [string match {} $data(appname)] {
+       if [catch {ConsoleEvalSlave eval $cmd} res] {
+         set data(errorInfo) [ConsoleEvalSlave set errorInfo]
+         set err 1
+       }
+      } else {
+       if [catch [list ConsoleEvalAttached $cmd] res] {
+         if [catch {ConsoleEvalAttached set errorInfo} err] {
+           set data(errorInfo) {Error attempting to retrieve errorInfo}
+         } else {
+           set data(errorInfo) $err
+         }
+         set err 1
+       }
+      }
+      ConsoleEvalSlave history add $cmd
+      if $err {
+       $w insert output $res\n stderr
+      } elseif {[string comp {} $res]} {
+       $w insert output $res\n stdout
+      }
+    }
+  }
+  Console:prompt $W
+  set data(event) [ConsoleEvalSlave history nextid]
+}
+
+## ConsoleEvalSlave - evaluates the args in the associated slave
+## args should be passed to this procedure like they would be at
+## the command line (not like to 'eval').
+# ARGS:        args    - the command and args to evaluate
+##
+;proc ConsoleEvalSlave {args} {
+  uplevel \#0 $args
+}
+
+## ConsoleEvalAttached
+##
+;proc ConsoleEvalAttached {args} {
+  eval uplevel \#0 $args
+}
+
+## ConsoleCmdGet - gets the current command from the console widget
+# ARGS:        w       - console text widget
+# Returns:     text which compromises current command line
+## 
+;proc ConsoleCmdGet w {
+  if [string match {} [$w tag nextrange prompt limit end]] {
+    $w tag add stdin limit end-1c
+    return [$w get limit end-1c]
+  }
+}
+
+## ConsoleCmdSep - separates multiple commands into a list and remainder
+# ARGS:        cmd     - (possible) multiple command to separate
+#      list    - varname for the list of commands that were separated.
+#      rmd     - varname of any remainder (like an incomplete final command).
+#              If there is only one command, it's placed in this var.
+# Returns:     constituent command info in varnames specified by list & rmd.
+## 
+;proc ConsoleCmdSep {cmd ls rmd} {
+  upvar $ls cmds $rmd tmp
+
+  set tmp {}
+  set cmds {}
+  foreach cmd [split [set cmd] \n] {
+    if [string comp {} $tmp] {
+      append tmp \n$cmd
+    } else {
+      append tmp $cmd
+    }
+    if {[info complete $tmp] && ![regexp {[^\\]\\$} $tmp]} {
+      lappend cmds $tmp
+      set tmp {}
+    }
+  }
+  if {[string comp {} [lindex $cmds end]] && [string match {} $tmp]} {
+    set tmp [lindex $cmds end]
+    set cmds [lreplace $cmds end end]
+  }
+}
+
+## Console:prompt - displays the prompt in the console widget
+# ARGS:        w       - console text widget
+# Outputs:     prompt (specified in data(-prompt)) to console
+## 
+;proc Console:prompt {W {pre {}} {post {}} {prompt {}}} {
+  upvar \#0 $W data
+
+  set w $data(console)
+  if [string comp {} $pre] { $w insert end $pre stdout }
+  set i [$w index end-1c]
+  if [string comp {} $data(appname)] {
+    $w insert end ">$data(appname)< " prompt
+  }
+  if [string comp {} $prompt] {
+    $w insert end $prompt prompt
+  } else {
+    $w insert end [ConsoleEvalSlave subst $data(-prompt)] prompt
+  }
+  $w mark set output $i
+  $w mark set insert end
+  $w mark set limit insert
+  $w mark gravity limit left
+  if [string comp {} $post] { $w insert end $post stdin }
+  $w see end
+}
+
+## ConsoleAbout - gives about info for Console
+## 
+;proc ConsoleAbout W {
+  global Console
+
+  set w $W.about
+  if [winfo exists $w] {
+    wm deiconify $w
+  } else {
+    toplevel $w
+    wm title $w "About Console v$Console(version)"
+    button $w.b -text Dismiss -command [list wm withdraw $w]
+    text $w.text -height 8 -bd 1 -width 60
+    pack $w.b -fill x -side bottom
+    pack $w.text -fill both -side left -expand 1
+    $w.text tag config center -justify center
+    $w.text tag config title -justify center -font {Courier 18 bold}
+    $w.text insert 1.0 "About Console v$Console(version)\n\n" title \
+       "Copyright 1995-1997 Jeffrey Hobbs, $Console(contact)\
+       \nhttp://www.cs.uoregon.edu/~jhobbs/\
+       \nRelease Date: v$Console(version), $Console(release)\
+       \nDocumentation available at:\n$Console(docs)" center
+  }
+}
+
+## ConsoleInitMenus - inits the menubar and popup for the console
+# ARGS:        W       - console
+## 
+;proc ConsoleInitMenus {W} {
+  upvar \#0 $W data
+
+  set w    $data(menubar)
+  set text $data(console)
+
+  if [catch {menu $w.pop -tearoff 0}] {
+    label $w.label -text "Menus not available in plugin mode"
+    pack $w.label
+    return
+  }
+  bind [winfo toplevel $w] <Button-3> "tk_popup $w.pop %X %Y"
+
+  pack [menubutton $w.con  -text "Console"  -un 0 -menu $w.con.m] -side left
+  $w.pop add cascade -label "Console" -un 0 -menu $w.pop.con
+
+  pack [menubutton $w.edit -text "Edit"     -un 0 -menu $w.edit.m] -side left
+  $w.pop add cascade -label "Edit"    -un 0 -menu $w.pop.edit
+
+  pack [menubutton $w.pref -text "Prefs"    -un 0 -menu $w.pref.m] -side left
+  $w.pop add cascade -label "Prefs"   -un 0 -menu $w.pop.pref
+
+  pack [menubutton $w.hist -text "History"  -un 0 -menu $w.hist.m] -side left
+  $w.pop add cascade -label "History"   -un 0 -menu $w.pop.hist
+
+  pack [menubutton $w.help -text "Help"     -un 0 -menu $w.help.m] -side right
+  $w.pop add cascade -label "Help"    -un 0 -menu $w.pop.help
+
+  ## Console Menu
+  ##
+  foreach m [list [menu $w.con.m -disabledfore $data(-promptcolor)] \
+                [menu $w.pop.con -disabledfore $data(-promptcolor)]] {
+    $m add command -label "Console $W" -state disabled
+    $m add command -label "Close Console " -un 0 \
+       -acc [event info <<Console_Close>>] -com [list destroy $W]
+    $m add command -label "Clear Console " -un 1 \
+       -acc [event info <<Console_Clear>>] -com [list Console_clear $W]
+    $m add separator
+    $m add command -label "Quit" -un 0 -acc [event info <<Console_Exit>>] \
+       -command exit
+  }
+
+  ## Edit Menu
+  ##
+  foreach m [list [menu $w.edit.m] [menu $w.pop.edit]] {
+    $m add command -label "Cut"   -un 1 \
+       -acc [lindex [event info <<Cut>>] 0] \
+       -command [list ConsoleCut $text]
+    $m add command -label "Copy"  -un 1 \
+       -acc [lindex [event info <<Copy>>] 0] \
+       -command [list ConsoleCopy $text]
+    $m add command -label "Paste" -un 0 \
+       -acc [lindex [event info <<Paste>>] 0] \
+       -command [list ConsolePaste $text]
+    $m add separator
+    $m add command -label "Find"  -un 0 -acc [event info <<Console_Find>>] \
+       -command [list ConsoleFindBox $W]
+  }
+
+  ## Prefs Menu
+  ##
+  foreach m [list [menu $w.pref.m] [menu $w.pop.pref]] {
+    $m add checkbutton -label "Brace Highlighting"    -var $W\(-lightbrace\)
+    $m add checkbutton -label "Command Highlighting"  -var $W\(-lightcmd\)
+    $m add checkbutton -label "History Substitution"  -var $W\(-subhistory\)
+    $m add checkbutton -label "Show Multiple Matches" -var $W\(-showmultiple\)
+    $m add checkbutton -label "Show Menubar"         -var $W\(-showmenu\) \
+       -command "Console:configure $W -showmenu \[set $W\(-showmenu\)\]"
+    $m add cascade -label Scrollbar -un 0 -menu $m.scroll
+
+    ## Scrollbar Menu
+    ##
+    set m [menu $m.scroll -tearoff 0]
+    $m add radio -label "Left" -var $W\(-scrollypos\) -value left \
+       -command [list Console:configure $W -scrollypos left]
+    $m add radio -label "Right" -var $W\(-scrollypos\) -value right \
+       -command [list Console:configure $W -scrollypos right]
+  }
+
+  ## History Menu
+  ##
+  foreach m [list $w.hist.m $w.pop.hist] {
+    menu $m -disabledfore $data(-promptcolor) \
+       -postcommand [list ConsoleHistoryMenu $W $m]
+  }
+
+  ## Help Menu
+  ##
+  foreach m [list [menu $w.help.m] [menu $w.pop.help]] {
+    $m config -disabledfore $data(-promptcolor)
+    $m add command -label "About " -un 0 -acc [event info <<Console_About>>] \
+       -command [list ConsoleAbout $W]
+  }
+
+  bind $W <<Console_Exit>>     exit
+  #bind $W <<Console_New>>     ConsoleNew
+  bind $W <<Console_Close>>    [list destroy $W]
+  bind $W <<Console_About>>    [list ConsoleAbout $W]
+  bind $W <<Console_Help>>     [list ConsoleHelp $W]
+  bind $W <<Console_Find>>     [list ConsoleFindBox $W]
+
+  ## Menu items need null PostCon bindings to avoid the TagProc
+  ##
+  foreach ev [bind $W] {
+    bind PostCon $ev {
+      # empty
+    }
+  }
+}
+
+## ConsoleHistoryMenu - dynamically build the menu for attached interpreters
+##
+# ARGS:        w       - menu widget
+##
+;proc ConsoleHistoryMenu {W w} {
+  upvar \#0 $W data
+
+  if ![winfo exists $w] return
+  set id [ConsoleEvalSlave history nextid]
+  if {$data(histid)==$id} return
+  set data(histid) $id
+  $w delete 0 end
+  set con $data(console)
+  while {($id>$data(histid)-10) && \
+      ![catch {ConsoleEvalSlave history event [incr id -1]} tmp]} {
+    set lbl [lindex [split $tmp "\n"] 0]
+    if {[string len $lbl]>32} { set lbl [string range $tmp 0 30]... }
+    $w add command -label "$id: $lbl" -command "
+    $con delete limit end
+    $con insert limit [list $tmp]
+    $con see end
+    ConsoleEval $con
+    "
+  }
+}
+
+## ConsoleFindBox - creates minimal dialog interface to ConsoleFind
+# ARGS:        w       - text widget
+#      str     - optional seed string for data(find)
+##
+;proc ConsoleFindBox {W {str {}}} {
+  upvar \#0 $W data
+
+  set t $data(console)
+  set base $W.find
+  if ![winfo exists $base] {
+    toplevel $base
+    wm withdraw $base
+    wm title $base "Console Find"
+
+    pack [frame $base.f] -fill x -expand 1
+    label $base.f.l -text "Find:"
+    entry $base.f.e -textvar $W\(find\)
+    pack [frame $base.opt] -fill x
+    checkbutton $base.opt.c -text "Case Sensitive" -variable $W\(find,case\)
+    checkbutton $base.opt.r -text "Use Regexp" -variable $W\(find,reg\)
+    pack $base.f.l -side left
+    pack $base.f.e $base.opt.c $base.opt.r -side left -fill both -expand 1
+    pack [frame $base.sep -bd 2 -relief sunken -height 4] -fill x
+    pack [frame $base.btn] -fill both
+    button $base.btn.fnd -text "Find" -width 6
+    button $base.btn.clr -text "Clear" -width 6
+    button $base.btn.dis -text "Dismiss" -width 6
+    eval pack [winfo children $base.btn] -padx 4 -pady 2 -side left -fill both
+
+    focus $base.f.e
+
+    bind $base.f.e <Return> [list $base.btn.fnd invoke]
+    bind $base.f.e <Escape> [list $base.btn.dis invoke]
+  }
+  $base.btn.fnd config -command "Console_find $W \$data(find) \
+      -case \$data(find,case) -reg \$data(find,reg)"
+  $base.btn.clr config -command "
+  $t tag remove find 1.0 end
+  set data(find) {}
+  "
+  $base.btn.dis config -command "
+  $t tag remove find 1.0 end
+  wm withdraw $base
+  "
+  if [string comp {} $str] {
+    set data(find) $str
+    $base.btn.fnd invoke
+  }
+
+  if {[string comp normal [wm state $base]]} {
+    wm deiconify $base
+  } else { raise $base }
+  $base.f.e select range 0 end
+}
+
+## Console_find - searches in text widget for $str and highlights it
+## If $str is empty, it just deletes any highlighting
+# ARGS: W      - console widget
+#      str     - string to search for
+#      -case   TCL_BOOLEAN     whether to be case sensitive    DEFAULT: 0
+#      -regexp TCL_BOOLEAN     whether to use $str as pattern  DEFAULT: 0
+##
+;proc ConsoleFind {W str args} {
+  upvar \#0 $W data
+  set t $data(console)
+  $t tag remove find 1.0 end
+  set truth {^(1|yes|true|on)$}
+  set opts  {}
+  foreach {key val} $args {
+    switch -glob -- $key {
+      -c* { if [regexp -nocase $truth $val] { set case 1 } }
+      -r* { if [regexp -nocase $truth $val] { lappend opts -regexp } }
+      default { return -code error "Unknown option $key" }
+    }
+  }
+  if ![info exists case] { lappend opts -nocase }
+  if [string match {} $str] return
+  $t mark set findmark 1.0
+  while {[string comp {} [set ix [eval $t search $opts -count numc -- \
+      [list $str] findmark end]]]} {
+    $t tag add find $ix ${ix}+${numc}c
+    $t mark set findmark ${ix}+1c
+  }
+  catch {$t see find.first}
+  return [expr [llength [$t tag ranges find]]/2]
+}
+
+## Console:savecommand - saves a command in a buffer for later retrieval
+#
+##
+;proc Console:savecommand {w} {
+  upvar \#0 [winfo parent $w] data
+
+  set tmp $data(cmdsave)
+  set data(cmdsave) [ConsoleCmdGet $w]
+  if {[string match {} $data(cmdsave)]} {
+    set data(cmdsave) $tmp
+  } else {
+    $w delete limit end-1c
+  }
+  $w insert limit $tmp
+  $w see end
+}
+
+## Console_load - sources a file into the console
+# ARGS:        fn      - (optional) filename to source in
+# Returns:     selected filename ({} if nothing was selected)
+## 
+;proc Console_load {W {fn {}}} {
+  if {[string match {} $fn] &&
+      ([catch {tk_getOpenFile} fn] || [string match {} $fn])} return
+  ConsoleEvalAttached [list source $fn]
+}
+
+## Console_save - saves the console buffer to a file
+## This does not eval in a slave because it's not necessary
+# ARGS:        w       - console text widget
+#      fn      - (optional) filename to save to
+## 
+;proc Console_save {W {fn {}}} {
+  upvar \#0 $W data
+
+  if {[string match {} $fn] &&
+      ([catch {tk_getSaveFile} fn] || [string match {} $fn])} return
+  if [catch {open $fn w} fid] {
+    return -code error "Save Error: Unable to open '$fn' for writing\n$fid"
+  }
+  puts $fid [$data(console) get 1.0 end-1c]
+  close $fid
+}
+
+## clear - clears the buffer of the console (not the history though)
+## 
+;proc Console_clear {W {pcnt 100}} {
+  upvar \#0 $W data
+
+  set data(tmp) [ConsoleCmdGet $data(console)]
+  if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} {
+    return -code error \
+       "invalid percentage to clear: must be 1-100 (100 default)"
+  } elseif {$pcnt == 100} {
+    $data(console) delete 1.0 end
+  } else {
+    set tmp [expr $pcnt/100.0*[$data(console) index end]]
+    $data(console) delete 1.0 "$tmp linestart"
+  }
+  Console:prompt $W {} $data(tmp)
+}
+
+;proc Console_error {W} {
+  ## Outputs stack caused by last error.
+  upvar \#0 $W data
+  set info $data(errorInfo)
+  if [string match {} $info] { set info {errorInfo empty} }
+  catch {destroy $W.error}
+  set w [toplevel $W.error]
+  wm title $w "Console Last Error"
+  button $w.close -text Dismiss -command [list destroy $w]
+  scrollbar $w.sy -takefocus 0 -bd 1 -command [list $w.text yview]
+  text $w.text -font $data(-font) -yscrollcommand [list $w.sy set]
+  pack $w.close -side bottom -fill x
+  pack $w.sy -side right -fill y
+  pack $w.text -fill both -expand 1
+  $w.text insert 1.0 $info
+  $w.text config -state disabled
+}
+
+## Console_event - searches for history based on a string
+## Search forward (next) if $int>0, otherwise search back (prev)
+# ARGS:        W       - console widget
+##
+;proc Console_event {W int {str {}}} {
+  upvar \#0 $W data
+
+  if !$int return
+  set w $data(console)
+
+  set nextid [ConsoleEvalSlave history nextid]
+  if [string comp {} $str] {
+    ## String is not empty, do an event search
+    set event $data(event)
+    if {$int < 0 && $event == $nextid} { set data(cmdbuf) $str }
+    set len [string len $data(cmdbuf)]
+    incr len -1
+    if {$int > 0} {
+      ## Search history forward
+      while {$event < $nextid} {
+       if {[incr event] == $nextid} {
+         $w delete limit end
+         $w insert limit $data(cmdbuf)
+         break
+       } elseif {![catch {ConsoleEvalSlave history event $event} res] \
+           && ![string comp $data(cmdbuf) [string range $res 0 $len]]} {
+         $w delete limit end
+         $w insert limit $res
+         break
+       }
+      }
+      set data(event) $event
+    } else {
+      ## Search history reverse
+      while {![catch {ConsoleEvalSlave history event [incr event -1]} res]} {
+       if {![string comp $data(cmdbuf) [string range $res 0 $len]]} {
+         $w delete limit end
+         $w insert limit $res
+         set data(event) $event
+         break
+       }
+      }
+    } 
+  } else {
+    ## String is empty, just get next/prev event
+    if {$int > 0} {
+      ## Goto next command in history
+      if {$data(event) < $nextid} {
+       $w delete limit end
+       if {[incr data(event)] == $nextid} {
+         $w insert limit $data(cmdbuf)
+       } else {
+         $w insert limit [ConsoleEvalSlave history event $data(event)]
+       }
+      }
+    } else {
+      ## Goto previous command in history
+      if {$data(event) == $nextid} { set data(cmdbuf) [ConsoleCmdGet $w] }
+      if [catch {ConsoleEvalSlave history event [incr data(event) -1]} res] {
+       incr data(event)
+      } else {
+       $w delete limit end
+       $w insert limit $res
+      }
+    }
+  }
+  $w mark set insert end
+  $w see end
+}
+
+;proc Console_history {W args} {
+  set sub {\2}
+  if [string match -n* $args] { append sub "\n" }
+  set h [ConsoleEvalSlave history]
+  regsub -all "( *\[0-9\]+  |\t)(\[^\n\]*\n?)" $h $sub h
+  return $h
+}
+
+;proc Console_hide {W} {
+  wm withdraw $W
+}
+
+;proc Console_show {W} {
+  wm deiconify $W
+  raise $W
+}
+
+##
+## Some procedures to make up for lack of built-in shell commands
+##
+
+## puts
+## This allows me to capture all stdout/stderr to the console window
+# ARGS:        same as usual   
+# Outputs:     the string with a color-coded text tag
+## 
+if ![catch {rename puts tcl_puts}] {
+  ;proc puts args {
+    global Console
+    set w [lindex $Console(active) 0].text
+    if {[llength $Console(active)] && [winfo exists $w]} {
+      set len [llength $args]
+      if {$len==1} {
+       eval $w insert output $args stdout {\n} stdout
+       $w see output
+      } elseif {$len==2 && \
+         [regexp {(stdout|stderr|-nonewline)} [lindex $args 0] junk tmp]} {
+       if [string comp $tmp -nonewline] {
+         eval $w insert output [lreplace $args 0 0] $tmp {\n} $tmp
+       } else {
+         eval $w insert output [lreplace $args 0 0] stdout
+       }
+       $w see output
+      } elseif {$len==3 && \
+         [regexp {(stdout|stderr)} [lreplace $args 2 2] junk tmp]} {
+       if [string comp [lreplace $args 1 2] -nonewline] {
+         eval $w insert output [lrange $args 1 1] $tmp
+       } else {
+         eval $w insert output [lreplace $args 0 1] $tmp
+       }
+       $w see output
+      } else {
+       global errorCode errorInfo
+       if [catch "tcl_puts $args" msg] {
+         regsub tcl_puts $msg puts msg
+         regsub -all tcl_puts $errorInfo puts errorInfo
+         error $msg
+       }
+       return $msg
+      }
+      if $len update
+    } else {
+      global errorCode errorInfo
+      if [catch "tcl_puts $args" msg] {
+       regsub tcl_puts $msg puts msg
+       regsub -all tcl_puts $errorInfo puts errorInfo
+       error $msg
+      }
+      return $msg
+    }
+  }
+}
+
+## echo
+## Relaxes the one string restriction of 'puts'
+# ARGS:        any number of strings to output to stdout
+##
+proc echo args { puts [concat $args] }
+
+## alias - akin to the csh alias command
+## If called with no args, then it dumps out all current aliases
+## If called with one arg, returns the alias of that arg (or {} if none)
+# ARGS:        newcmd  - (optional) command to bind alias to
+#      args    - command and args being aliased
+## 
+proc alias {{newcmd {}} args} {
+  if [string match {} $newcmd] {
+    set res {}
+    foreach a [interp aliases] {
+      lappend res [list $a -> [interp alias {} $a]]
+    }
+    return [join $res \n]
+  } elseif {[string match {} $args]} {
+    interp alias {} $newcmd
+  } else {
+    eval interp alias [list {} $newcmd {}] $args
+  }
+}
+
+## dump - outputs variables/procedure/widget info in source'able form.
+## Accepts glob style pattern matching for the names
+# ARGS:        type    - type of thing to dump: must be variable, procedure, widget
+# OPTS: -nocomplain
+#              don't complain if no vars match something
+#      -filter pattern
+#              specifies a glob filter pattern to be used by the variable
+#              method as an array filter pattern (it filters down for
+#              nested elements) and in the widget method as a config
+#              option filter pattern
+#      --      forcibly ends options recognition
+# Returns:     the values of the requested items in a 'source'able form
+## 
+proc dump {type args} {
+  set whine 1
+  set code  ok
+  while {[string match -* $args]} {
+    switch -glob -- [lindex $args 0] {
+      -n* { set whine 0; set args [lreplace $args 0 0] }
+      -f* { set fltr [lindex $args 1]; set args [lreplace $args 0 1] }
+      --  { set args [lreplace $args 0 0]; break }
+      default { return -code error "unknown option \"[lindex $args 0]\"" }
+    }
+  }
+  if {$whine && [string match {} $args]} {
+    return -code error "wrong \# args: [lindex [info level 0] 0]\
+       ?-nocomplain? ?-filter pattern? ?--? pattern ?pattern ...?"
+  }
+  set res {}
+  switch -glob -- $type {
+    c* {
+      # command
+      # outpus commands by figuring out, as well as possible, what it is
+      # this does not attempt to auto-load anything
+      foreach arg $args {
+       if [string comp {} [set cmds [info comm $arg]]] {
+         foreach cmd [lsort $cmds] {
+           if {[lsearch -exact [interp aliases] $cmd] > -1} {
+             append res "\#\# ALIAS:   $cmd => [interp alias {} $cmd]\n"
+           } elseif {[string comp {} [info procs $cmd]]} {
+             if {[catch {dump p -- $cmd} msg] && $whine} { set code error }
+             append res $msg\n
+           } else {
+             append res "\#\# COMMAND: $cmd\n"
+           }
+         }
+       } elseif $whine {
+         append res "\#\# No known command $arg\n"
+         set code error
+       }
+      }
+    }
+    v* {
+      # variable
+      # outputs variables value(s), whether array or simple.
+      if ![info exists fltr] { set fltr * }
+      foreach arg $args {
+       if {[string match {} [set vars [uplevel info vars [list $arg]]]]} {
+         if {[uplevel info exists $arg]} {
+           set vars $arg
+         } elseif $whine {
+           append res "\#\# No known variable $arg\n"
+           set code error
+           continue
+         } else continue
+       }
+       foreach var [lsort $vars] {
+         upvar $var v
+         if {[array exists v]} {
+           set nest {}
+           append res "array set $var \{\n"
+           foreach i [lsort [array names v $fltr]] {
+             upvar 0 v\($i\) __ary
+             if {[array exists __ary]} {
+               append nest "\#\# NESTED ARRAY ELEMENT: $i\n"
+               append nest "upvar 0 [list $var\($i\)] __ary;\
+                   [dump v -filter $fltr __ary]\n"
+             } else {
+               append res "    [list $i]\t[list $v($i)]\n"
+             }
+           }
+           append res "\}\n$nest"
+         } else {
+           append res [list set $var $v]\n
+         }
+       }
+      }
+    }
+    p* {
+      # procedure
+      foreach arg $args {
+       if {[string comp {} [set ps [info proc $arg]]] ||
+           ([auto_load $arg] &&
+            [string comp {} [set ps [info proc $arg]]])} {
+         foreach p [lsort $ps] {
+           set as {}
+           foreach a [info args $p] {
+             if {[info default $p $a tmp]} {
+               lappend as [list $a $tmp]
+             } else {
+               lappend as $a
+             }
+           }
+           append res [list proc $p $as [info body $p]]\n
+         }
+       } elseif $whine {
+         append res "\#\# No known proc $arg\n"
+         set code error
+       }
+      }
+    }
+    w* {
+      # widget
+      ## The user should have Tk loaded
+      if [string match {} [info command winfo]] {
+       return -code error "winfo not present, cannot dump widgets"
+      }
+      if ![info exists fltr] { set fltr .* }
+      foreach arg $args {
+       if [string comp {} [set ws [info command $arg]]] {
+         foreach w [lsort $ws] {
+           if [winfo exists $w] {
+             if [catch {$w configure} cfg] {
+               append res "\#\# Widget $w does not support configure method"
+               set code error
+             } else {
+               append res "\#\# [winfo class $w] $w\n$w configure"
+               foreach c $cfg {
+                 if {[llength $c] != 5} continue
+                 if {[regexp -nocase -- $fltr $c]} {
+                   append res " \\\n\t[list [lindex $c 0] [lindex $c 4]]"
+                 }
+               }
+               append res \n
+             }
+           }
+         }
+       } elseif $whine {
+         append res "\#\# No known widget $arg\n"
+         set code error
+       }
+      }
+    }
+    default {
+      return -code error "bad [lindex [info level 0] 0] option\
+       \"$type\":\ must be procedure, variable, widget"
+    }
+  }
+  return -code $code [string trimr $res \n]
+}
+
+## which - tells you where a command is found
+# ARGS:        cmd     - command name
+# Returns:     where command is found (internal / external / unknown)
+## 
+proc which cmd {
+  if {[string comp {} [info commands $cmd]] ||
+      ([auto_load $cmd] && [string comp {} [info commands $cmd]])} {
+    if {[lsearch -exact [interp aliases] $cmd] > -1} {
+      return "$cmd:\taliased to [alias $cmd]"
+    } elseif {[string comp {} [info procs $cmd]]} {
+      return "$cmd:\tinternal proc"
+    } else {
+      return "$cmd:\tinternal command"
+    }
+  } elseif {[string comp {} [auto_execok $cmd]]} {
+    return [auto_execok $cmd]
+  } else {
+    return -code error "$cmd:\tunknown command"
+  }
+}
+
+## dir - directory list
+# ARGS:        args    - names/glob patterns of directories to list
+# OPTS:        -all    - list hidden files as well (Unix dot files)
+#      -long   - list in full format "permissions size date filename"
+#      -full   - displays / after directories and link paths for links
+# Returns:     a directory listing
+## 
+proc dir {args} {
+  array set s {
+    all 0 full 0 long 0
+    0 --- 1 --x 2 -w- 3 -wx 4 r-- 5 r-x 6 rw- 7 rwx
+  }
+  while {[string match \-* [lindex $args 0]]} {
+    set str [lindex $args 0]
+    set args [lreplace $args 0 0]
+    switch -glob -- $str {
+      -a* {set s(all) 1} -f* {set s(full) 1}
+      -l* {set s(long) 1} -- break
+      default {
+       return -code error \
+           "unknown option \"$str\", should be one of: -all, -full, -long"
+      }
+    }
+  }
+  set sep [string trim [file join . .] .]
+  if [string match {} $args] { set args . }
+  foreach arg $args {
+    if {[file isdir $arg]} {
+      set arg [string trimr $arg $sep]$sep
+      if $s(all) {
+       lappend out [list $arg [lsort [glob -nocomplain -- $arg.* $arg*]]]
+      } else {
+       lappend out [list $arg [lsort [glob -nocomplain -- $arg*]]]
+      }
+    } else {
+      lappend out [list [file dirname $arg]$sep \
+                      [lsort [glob -nocomplain -- $arg]]]
+    }
+  }
+  if $s(long) {
+    set old [clock scan {1 year ago}]
+    set fmt "%s%9d %s %s\n"
+    foreach o $out {
+      set d [lindex $o 0]
+      append res $d:\n
+      foreach f [lindex $o 1] {
+       file lstat $f st
+       set f [file tail $f]
+       if $s(full) {
+         switch -glob $st(type) {
+           d* { append f $sep }
+           l* { append f "@ -> [file readlink $d$sep$f]" }
+           default { if [file exec $d$sep$f] { append f * } }
+         }
+       }
+       if [string match file $st(type)] {
+         set mode -
+       } else {
+         set mode [string index $st(type) 0]
+       }
+       foreach j [split [format %o [expr $st(mode)&0777]] {}] {
+         append mode $s($j)
+       }
+       if {$st(mtime)>$old} {
+         set cfmt {%b %d %H:%M}
+       } else {
+         set cfmt {%b %d  %Y}
+       }
+       append res [format $fmt $mode $st(size) \
+                       [clock format $st(mtime) -format $cfmt] $f]
+      }
+      append res \n
+    }
+  } else {
+    foreach o $out {
+      set d [lindex $o 0]
+      append res $d:\n
+      set i 0
+      foreach f [lindex $o 1] {
+       if {[string len [file tail $f]] > $i} {
+         set i [string len [file tail $f]]
+       }
+      }
+      set i [expr $i+2+$s(full)]
+      ## This gets the number of cols in the Console console widget
+      set j [expr 64/$i]
+      set k 0
+      foreach f [lindex $o 1] {
+       set f [file tail $f]
+       if $s(full) {
+         switch -glob [file type $d$sep$f] {
+           d* { append f $sep }
+           l* { append f @ }
+           default { if [file exec $d$sep$f] { append f * } }
+         }
+       }
+       append res [format "%-${i}s" $f]
+       if {[incr k]%$j == 0} {set res [string trimr $res]\n}
+      }
+      append res \n\n
+    }
+  }
+  return [string trimr $res]
+}
+interp alias {} ls {} dir
+
+## lremove - remove items from a list
+# OPTS:        -all    remove all instances of each item
+# ARGS:        l       a list to remove items from
+#      args    items to remove
+##
+proc lremove {args} {
+  set all 0
+  if [string match \-a* [lindex $args 0]] {
+    set all 1
+    set args [lreplace $args 0 0]
+  }
+  set l [lindex $args 0]
+  eval append is [lreplace $args 0 0]
+  foreach i $is {
+    if {[set ix [lsearch -exact $l $i]] == -1} continue
+    set l [lreplace $l $ix $ix]
+    if $all {
+      while {[set ix [lsearch -exact $l $i]] != -1} {
+       set l [lreplace $l $ix $ix]
+      }
+    }
+  }
+  return $l
+}
+
+## Unknown changed to get output into Console window
+# unknown:
+# Invoked automatically whenever an unknown command is encountered.
+# Works through a list of "unknown handlers" that have been registered
+# to deal with unknown commands.  Extensions can integrate their own
+# handlers into the "unknown" facility via "unknown_handle".
+#
+# If a handler exists that recognizes the command, then it will
+# take care of the command action and return a valid result or a
+# Tcl error.  Otherwise, it should return "-code continue" (=2)
+# and responsibility for the command is passed to the next handler.
+#
+# Arguments:
+# args -       A list whose elements are the words of the original
+#              command, including the command name.
+
+proc unknown args {
+    global unknown_handler_order unknown_handlers errorInfo errorCode
+
+    #
+    # Be careful to save error info now, and restore it later
+    # for each handler.  Some handlers generate their own errors
+    # and disrupt handling.
+    #
+    set savedErrorCode $errorCode
+    set savedErrorInfo $errorInfo
+
+    if {![info exists unknown_handler_order] || ![info exists unknown_handlers]} {
+       set unknown_handlers(tcl) tcl_unknown
+       set unknown_handler_order tcl
+    }
+
+    foreach handler $unknown_handler_order {
+        set status [catch {uplevel $unknown_handlers($handler) $args} result]
+
+        if {$status == 1} {
+            #
+            # Strip the last five lines off the error stack (they're
+            # from the "uplevel" command).
+            #
+            set new [split $errorInfo \n]
+            set new [join [lrange $new 0 [expr [llength $new] - 6]] \n]
+            return -code $status -errorcode $errorCode \
+                -errorinfo $new $result
+
+        } elseif {$status != 4} {
+            return -code $status $result
+        }
+
+        set errorCode $savedErrorCode
+        set errorInfo $savedErrorInfo
+    }
+
+    set name [lindex $args 0]
+    return -code error "invalid command name \"$name\""
+}
+
+# tcl_unknown:
+# Invoked when a Tcl command is invoked that doesn't exist in the
+# interpreter:
+#
+#      1. See if the autoload facility can locate the command in a
+#         Tcl script file.  If so, load it and execute it.
+#      2. If the command was invoked interactively at top-level:
+#          (a) see if the command exists as an executable UNIX program.
+#              If so, "exec" the command.
+#          (b) see if the command requests csh-like history substitution
+#              in one of the common forms !!, !<number>, or ^old^new.  If
+#              so, emulate csh's history substitution.
+#          (c) see if the command is a unique abbreviation for another
+#              command.  If so, invoke the command.
+#
+# Arguments:
+# args -       A list whose elements are the words of the original
+#              command, including the command name.
+
+proc tcl_unknown args {
+  global auto_noexec auto_noload env unknown_pending tcl_interactive Console
+  global errorCode errorInfo
+
+  # Save the values of errorCode and errorInfo variables, since they
+  # may get modified if caught errors occur below.  The variables will
+  # be restored just before re-executing the missing command.
+
+  set savedErrorCode $errorCode
+  set savedErrorInfo $errorInfo
+  set name [lindex $args 0]
+  if ![info exists auto_noload] {
+    #
+    # Make sure we're not trying to load the same proc twice.
+    #
+    if [info exists unknown_pending($name)] {
+      unset unknown_pending($name)
+      if {[array size unknown_pending] == 0} {
+       unset unknown_pending
+      }
+      return -code error "self-referential recursion in \"unknown\" for command \"$name\"";
+    }
+    set unknown_pending($name) pending;
+    set ret [catch {auto_load $name} msg]
+    unset unknown_pending($name);
+    if $ret {
+      return -code $ret -errorcode $errorCode \
+         "error while autoloading \"$name\": $msg"
+    }
+    if ![array size unknown_pending] {
+      unset unknown_pending
+    }
+    if $msg {
+      set errorCode $savedErrorCode
+      set errorInfo $savedErrorInfo
+      set code [catch {uplevel $args} msg]
+      if {$code ==  1} {
+       #
+       # Strip the last five lines off the error stack (they're
+       # from the "uplevel" command).
+       #
+
+       set new [split $errorInfo \n]
+       set new [join [lrange $new 0 [expr [llength $new] - 6]] \n]
+       return -code error -errorcode $errorCode \
+           -errorinfo $new $msg
+      } else {
+       return -code $code $msg
+      }
+    }
+  }
+  if {[info level] == 1 && [string match {} [info script]] \
+         && [info exists tcl_interactive] && $tcl_interactive} {
+    if ![info exists auto_noexec] {
+      set new [auto_execok $name]
+      if {$new != ""} {
+       set errorCode $savedErrorCode
+       set errorInfo $savedErrorInfo
+       return [uplevel exec [list $new] [lrange $args 1 end]]
+       #return [uplevel exec >&@stdout <@stdin $new [lrange $args 1 end]]
+      }
+    }
+    set errorCode $savedErrorCode
+    set errorInfo $savedErrorInfo
+    ##
+    ## History substitution moved into ConsoleEvalCmd
+    ##
+    set cmds [info commands $name*]
+    if {[llength $cmds] == 1} {
+      return [uplevel [lreplace $args 0 0 $cmds]]
+    }
+    if {[llength $cmds]} {
+      if {$name == ""} {
+       return -code error "empty command name \"\""
+      } else {
+       return -code error \
+           "ambiguous command name \"$name\": [lsort $cmds]"
+      }
+    }
+  }
+  return -code continue
+}
+
+switch -glob $tcl_platform(platform) {
+  win* { set META Alt }
+  mac* { set META Command }
+  default { set META Meta }
+}
+
+# ConsoleClipboardKeysyms --
+# This procedure is invoked to identify the keys that correspond to
+# the "copy", "cut", and "paste" functions for the clipboard.
+#
+# Arguments:
+# copy -       Name of the key (keysym name plus modifiers, if any,
+#              such as "Meta-y") used for the copy operation.
+# cut -                Name of the key used for the cut operation.
+# paste -      Name of the key used for the paste operation.
+
+;proc ConsoleClipboardKeysyms {copy cut paste} {
+  bind Console <$copy> {ConsoleCopy %W}
+  bind Console <$cut>          {ConsoleCut %W}
+  bind Console <$paste>        {ConsolePaste %W}
+}
+
+;proc ConsoleCut w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {
+      clipboard append -displayof $w [selection get -displayof $w]
+      if [$w compare sel.first >= limit] {$w delete sel.first sel.last}
+    }
+  }
+}
+;proc ConsoleCopy w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {clipboard append -displayof $w [selection get -displayof $w]}
+  }
+}
+
+;proc ConsolePaste w {
+  if ![catch {selection get -displayof $w -selection CLIPBOARD} tmp] {
+    if [$w compare insert < limit] {$w mark set insert end}
+    $w insert insert $tmp
+    $w see insert
+    if [string match *\n* $tmp] {ConsoleEval $w}
+  }
+}
+
+## Get all Text bindings into Console except Unix cut/copy/paste
+## and newline insertion
+foreach ev [lremove [bind Text] {<Control-Key-y> <Control-Key-w> \
+    <Meta-Key-w> <Control-Key-o> <Control-Key-v> <Control-Key-c> \
+    <Control-Key-x>}] {
+  bind Console $ev [bind Text $ev]
+}
+
+foreach {ev key} {
+  <<Console_Previous>>         <Key-Up>
+  <<Console_Next>>             <Key-Down>
+  <<Console_NextImmediate>>    <Control-Key-n>
+  <<Console_PreviousImmediate>>        <Control-Key-p>
+  <<Console_PreviousSearch>>   <Control-Key-r>
+  <<Console_NextSearch>>       <Control-Key-s>
+
+  <<Console_ExpandFile>>       <Key-Tab>
+  <<Console_ExpandProc>>       <Control-Shift-Key-P>
+  <<Console_ExpandVar>>                <Control-Shift-Key-V>
+  <<Console_Tab>>              <Control-Key-i>
+  <<Console_Eval>>             <Key-Return>
+  <<Console_Eval>>             <Key-KP_Enter>
+
+  <<Console_Clear>>            <Control-Key-l>
+  <<Console_KillLine>>         <Control-Key-k>
+  <<Console_Transpose>>                <Control-Key-t>
+  <<Console_ClearLine>>                <Control-Key-u>
+  <<Console_SaveCommand>>      <Control-Key-z>
+
+  <<Console_Exit>>     <Control-Key-q>
+  <<Console_New>>      <Control-Key-N>
+  <<Console_Close>>    <Control-Key-w>
+  <<Console_About>>    <Control-Key-A>
+  <<Console_Help>>     <Control-Key-H>
+  <<Console_Find>>     <Control-Key-F>
+} {
+  event add $ev $key
+  bind Console $key {}
+}
+catch {unset ev key}
+
+## Redefine for Console what we need
+##
+event delete <<Paste>> <Control-V>
+ConsoleClipboardKeysyms <Copy> <Cut> <Paste>
+
+bind Console <Insert> {catch {ConsoleInsert %W [selection get -displayof %W]}}
+
+bind Console <Triple-1> {+
+catch {
+  eval %W tag remove sel [%W tag nextrange prompt sel.first sel.last]
+  %W mark set insert sel.first
+}
+}
+
+bind Console <<Console_ExpandFile>> {
+  if [%W compare insert > limit] {Console:expand %W path}
+  break
+}
+bind Console <<Console_ExpandProc>> {
+  if [%W compare insert > limit] {Console:expand %W proc}
+}
+bind Console <<Console_ExpandVar>> {
+  if [%W compare insert > limit] {Console:expand %W var}
+}
+bind Console <<Console_Tab>> {
+  if [%W compare insert >= limit] {
+    ConsoleInsert %W \t
+  }
+}
+bind Console <<Console_Eval>> {
+  ConsoleEval %W
+}
+bind Console <Delete> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+      && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif {[%W compare insert >= limit]} {
+    %W delete insert
+    %W see insert
+  }
+}
+bind Console <BackSpace> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+      && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif {[%W compare insert != 1.0] && [%W compare insert > limit]} {
+    %W delete insert-1c
+    %W see insert
+  }
+}
+bind Console <Control-h> [bind Console <BackSpace>]
+
+bind Console <KeyPress> {
+  ConsoleInsert %W %A
+}
+
+bind Console <Control-a> {
+  if [%W compare {limit linestart} == {insert linestart}] {
+    tkTextSetCursor %W limit
+  } else {
+    tkTextSetCursor %W {insert linestart}
+  }
+}
+bind Console <Control-d> {
+  if [%W compare insert < limit] break
+  %W delete insert
+}
+bind Console <<Console_KillLine>> {
+  if [%W compare insert < limit] break
+  if [%W compare insert == {insert lineend}] {
+    %W delete insert
+  } else {
+    %W delete insert {insert lineend}
+  }
+}
+bind Console <<Console_Clear>> {
+  Console_clear [winfo parent %W]
+}
+bind Console <<Console_Previous>> {
+  if [%W compare {insert linestart} != {limit linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W -1]
+  } else {
+    Console_event [winfo parent %W] -1
+  }
+}
+bind Console <<Console_Next>> {
+  if [%W compare {insert linestart} != {end-1c linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W 1]
+  } else {
+    Console_event [winfo parent %W] 1
+  }
+}
+bind Console <<Console_NextImmediate>> {
+  Console_event [winfo parent %W] 1
+}
+bind Console <<Console_PreviousImmediate>> {
+  Console_event [winfo parent %W] -1
+}
+bind Console <<Console_PreviousSearch>> {
+  Console_event [winfo parent %W] -1 [ConsoleCmdGet %W]
+}
+bind Console <<Console_NextSearch>> {
+  Console_event [winfo parent %W] 1 [ConsoleCmdGet %W]
+}
+bind Console <<Console_Transpose>> {
+  ## Transpose current and previous chars
+  if [%W compare insert > limit] { tkTextTranspose %W }
+}
+bind Console <<Console_ClearLine>> {
+  ## Clear command line (Unix shell staple)
+  %W delete limit end
+}
+bind Console <<Console_SaveCommand>> {
+  ## Save command buffer (swaps with current command)
+  Console:savecommand %W
+}
+catch {bind Console <Key-Page_Up>   { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Prior>     { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Page_Down> { tkTextScrollPages %W 1 }}
+catch {bind Console <Key-Next>      { tkTextScrollPages %W 1 }}
+bind Console <$META-d> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <$META-BackSpace> {
+  if [%W compare {insert -1c wordstart} >= limit] {
+    %W delete {insert -1c wordstart} insert
+  }
+}
+bind Console <$META-Delete> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <ButtonRelease-2> {
+  if {(!$tkPriv(mouseMoved) || $tk_strictMotif) \
+      && ![catch {selection get -displayof %W} tkPriv(junk)]} {
+    if [%W compare @%x,%y < limit] {
+      %W insert end $tkPriv(junk)
+    } else {
+      %W insert @%x,%y $tkPriv(junk)
+    }
+    if [string match *\n* $tkPriv(junk)] {ConsoleEval %W}
+  }
+}
+
+##
+## End Console bindings
+##
+
+##
+## Bindings for doing special things based on certain keys
+##
+bind PostCon <Key-parenright> {
+  if [string comp \\ [%W get insert-2c]] { ConsoleMatchPair %W \( \) limit }
+}
+bind PostCon <Key-bracketright> {
+  if [string comp \\ [%W get insert-2c]] { ConsoleMatchPair %W \[ \] limit }
+}
+bind PostCon <Key-braceright> {
+  if [string comp \\ [%W get insert-2c]] { ConsoleMatchPair %W \{ \} limit }
+}
+bind PostCon <Key-quotedbl> {
+  if [string comp \\ [%W get insert-2c]] { ConsoleMatchQuote %W limit }
+}
+
+bind PostCon <KeyPress> {
+  if [string comp {} %A] { ConsoleTagProc %W }
+}
+
+
+## ConsoleTagProc - tags a procedure in the console if it's recognized
+## This procedure is not perfect.  However, making it perfect wastes
+## too much CPU time...  Also it should check the existence of a command
+## in whatever is the connected slave, not the master interpreter.
+##
+;proc ConsoleTagProc w {
+  upvar \#0 [winfo parent $w] data
+  if !$data(-lightcmd) return
+  set i [$w index "insert-1c wordstart"]
+  set j [$w index "insert-1c wordend"]
+  if {[string comp {} \
+          [ConsoleEvalAttached info command [list [$w get $i $j]]]]} {
+    $w tag add proc $i $j
+  } else {
+    $w tag remove proc $i $j
+  }
+}
+
+## ConsoleMatchPair - blinks a matching pair of characters
+## c2 is assumed to be at the text index 'insert'.
+## This proc is really loopy and took me an hour to figure out given
+## all possible combinations with escaping except for escaped \'s.
+## It doesn't take into account possible commenting... Oh well.  If
+## anyone has something better, I'd like to see/use it.  This is really
+## only efficient for small contexts.
+# ARGS:        w       - console text widget
+#      c1      - first char of pair
+#      c2      - second char of pair
+# Calls:       Console:blink
+## 
+;proc ConsoleMatchPair {w c1 c2 {lim 1.0}} {
+  upvar \#0 [winfo parent $w] data
+  if {!$data(-lightbrace) || $data(-blinktime)<100} return
+  if [string comp {} [set ix [$w search -back $c1 insert $lim]]] {
+    while {[string match {\\} [$w get $ix-1c]] &&
+          [string comp {} [set ix [$w search -back $c1 $ix-1c $lim]]]} {}
+    set i1 insert-1c
+    while {[string comp {} $ix]} {
+      set i0 $ix
+      set j 0
+      while {[string comp {} [set i0 [$w search $c2 $i0 $i1]]]} {
+       append i0 +1c
+       if {[string match {\\} [$w get $i0-2c]]} continue
+       incr j
+      }
+      if {!$j} break
+      set i1 $ix
+      while {$j && [string comp {} [set ix [$w search -back $c1 $ix $lim]]]} {
+       if {[string match {\\} [$w get $ix-1c]]} continue
+       incr j -1
+      }
+    }
+    if [string match {} $ix] { set ix [$w index $lim] }
+  } else { set ix [$w index $lim] }
+  if $data(-blinkrange) {
+    Console:blink $w $data(-blinktime) $ix [$w index insert]
+  } else {
+    Console:blink $w $data(-blinktime) $ix $ix+1c \
+       [$w index insert-1c] [$w index insert]
+  }
+}
+
+## ConsoleMatchQuote - blinks between matching quotes.
+## Blinks just the quote if it's unmatched, otherwise blinks quoted string
+## The quote to match is assumed to be at the text index 'insert'.
+# ARGS:        w       - console text widget
+# Calls:       Console:blink
+## 
+;proc ConsoleMatchQuote {w {lim 1.0}} {
+  upvar \#0 [winfo parent $w] data
+  if {!$data(-lightbrace) || $data(-blinktime)<100} return
+  set i insert-1c
+  set j 0
+  while {[string comp {} [set i [$w search -back \" $i $lim]]]} {
+    if {[string match {\\} [$w get $i-1c]]} continue
+    if {!$j} {set i0 $i}
+    incr j
+  }
+  if [expr $j%2] {
+    if $data(-blinkrange) {
+      Console:blink $w $data(-blinktime) $i0 [$w index insert]
+    } else {
+      Console:blink $w $data(-blinktime) $i0 $i0+1c \
+         [$w index insert-1c] [$w index insert]
+    }
+  } else {
+    Console:blink $w $data(-blinktime) [$w index insert-1c] [$w index insert]
+  }
+}
+
+## Console:blink - blinks between 2 indices for a specified duration.
+# ARGS:        w       - console text widget
+#      delay   - millisecs to blink for
+#      args    - indices of regions to blink
+# Outputs:     blinks selected characters in $w
+## 
+;proc Console:blink {w delay args} {
+  eval $w tag add blink $args
+  after $delay eval $w tag remove blink $args
+  return
+}
+
+
+## ConsoleInsert
+## Insert a string into a text console at the point of the insertion cursor.
+## If there is a selection in the text, and it covers the point of the
+## insertion cursor, then delete the selection before inserting.
+# ARGS:        w       - text window in which to insert the string
+#      s       - string to insert (usually just a single char)
+# Outputs:     $s to text widget
+## 
+;proc ConsoleInsert {w s} {
+  if {[string match {} $s] || [string match disabled [$w cget -state]]} {
+    return
+  }
+  if [$w comp insert < limit] {
+    $w mark set insert end
+  }
+  catch {
+    if {[$w comp sel.first <= insert] && [$w comp sel.last >= insert]} {
+      $w delete sel.first sel.last
+    }
+  }
+  $w insert insert $s
+  $w see insert
+}
+
+## Console:expand - 
+# ARGS:        w       - text widget in which to expand str
+#      type    - type of expansion (path / proc / variable)
+# Calls:       ConsoleExpand(Pathname|Procname|Variable)
+# Outputs:     The string to match is expanded to the longest possible match.
+#              If data(-showmultiple) is non-zero and the user longest match
+#              equaled the string to expand, then all possible matches are
+#              output to stdout.  Triggers bell if no matches are found.
+# Returns:     number of matches found
+## 
+;proc Console:expand {w type} {
+  set exp "\[^\\]\[ \t\n\r\[\{\"\$]"
+  set tmp [$w search -back -regexp $exp insert-1c limit-1c]
+  if [string compare {} $tmp] {append tmp +2c} else {set tmp limit}
+  if [$w compare $tmp >= insert] return
+  set str [$w get $tmp insert]
+  switch -glob $type {
+    pa* { set res [ConsoleExpandPathname $str] }
+    pr* { set res [ConsoleExpandProcname $str] }
+    v*  { set res [ConsoleExpandVariable $str] }
+    default {set res {}}
+  }
+  set len [llength $res]
+  if $len {
+    $w delete $tmp insert
+    $w insert $tmp [lindex $res 0]
+    if {$len > 1} {
+      upvar \#0 [winfo parent $w] data
+      if {$data(-showmultiple) && ![string comp [lindex $res 0] $str]} {
+       puts stdout [lreplace $res 0 0]
+      }
+    }
+  } else bell
+  return [incr len -1]
+}
+
+## ConsoleExpandPathname - expand a file pathname based on $str
+## This is based on UNIX file name conventions
+# ARGS:        str     - partial file pathname to expand
+# Calls:       ConsoleExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+;proc ConsoleExpandPathname str {
+  set pwd [ConsoleEvalAttached pwd]
+  if [catch {ConsoleEvalAttached [list cd [file dirname $str]]} err] {
+    return -code error $err
+  }
+  if [catch {lsort [ConsoleEvalAttached glob [file tail $str]*]} m] {
+    set match {}
+  } else {
+    if {[llength $m] > 1} {
+      set tmp [ConsoleExpandBestMatch $m [file tail $str]]
+      if [string match ?*/* $str] {
+       set tmp [file dirname $str]/$tmp
+      } elseif {[string match /* $str]} {
+       set tmp /$tmp
+      }
+      regsub -all { } $tmp {\\ } tmp
+      set match [linsert $m 0 $tmp]
+    } else {
+      ## This may look goofy, but it handles spaces in path names
+      eval append match $m
+      if [file isdir $match] {append match /}
+      if [string match ?*/* $str] {
+       set match [file dirname $str]/$match
+      } elseif {[string match /* $str]} {
+       set match /$match
+      }
+      regsub -all { } $match {\\ } match
+      ## Why is this one needed and the ones below aren't!!
+      set match [list $match]
+    }
+  }
+  ConsoleEvalAttached [list cd $pwd]
+  return $match
+}
+
+## ConsoleExpandProcname - expand a tcl proc name based on $str
+# ARGS:        str     - partial proc name to expand
+# Calls:       ConsoleExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+;proc ConsoleExpandProcname str {
+  set match [ConsoleEvalAttached info commands $str*]
+  if {[llength $match] > 1} {
+    regsub -all { } [ConsoleExpandBestMatch $match $str] {\\ } str
+    set match [linsert $match 0 $str]
+  } else {
+    regsub -all { } $match {\\ } match
+  }
+  return $match
+}
+
+## ConsoleExpandVariable - expand a tcl variable name based on $str
+# ARGS:        str     - partial tcl var name to expand
+# Calls:       ConsoleExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+;proc ConsoleExpandVariable str {
+  if [regexp {([^\(]*)\((.*)} $str junk ary str] {
+    ## Looks like they're trying to expand an array.
+    set match [ConsoleEvalAttached array names $ary $str*]
+    if {[llength $match] > 1} {
+      set vars $ary\([ConsoleExpandBestMatch $match $str]
+      foreach var $match {lappend vars $ary\($var\)}
+      return $vars
+    } else {set match $ary\($match\)}
+    ## Space transformation avoided for array names.
+  } else {
+    set match [ConsoleEvalAttached info vars $str*]
+    if {[llength $match] > 1} {
+      regsub -all { } [ConsoleExpandBestMatch $match $str] {\\ } str
+      set match [linsert $match 0 $str]
+    } else {
+      regsub -all { } $match {\\ } match
+    }
+  }
+  return $match
+}
+
+## ConsoleExpandBestMatch2 - finds the best unique match in a list of names
+## Improves upon the speed of the below proc only when $l is small
+## or $e is {}.  $e is extra for compatibility with proc below.
+# ARGS:        l       - list to find best unique match in
+# Returns:     longest unique match in the list
+## 
+;proc ConsoleExpandBestMatch2 {l {e {}}} {
+  set s [lindex $l 0]
+  if {[llength $l]>1} {
+    set i [expr [string length $s]-1]
+    foreach l $l {
+      while {$i>=0 && [string first $s $l]} {
+       set s [string range $s 0 [incr i -1]]
+      }
+    }
+  }
+  return $s
+}
+
+## ConsoleExpandBestMatch - finds the best unique match in a list of names
+## The extra $e in this argument allows us to limit the innermost loop a
+## little further.  This improves speed as $l becomes large or $e becomes long.
+# ARGS:        l       - list to find best unique match in
+#      e       - currently best known unique match
+# Returns:     longest unique match in the list
+## 
+;proc ConsoleExpandBestMatch {l {e {}}} {
+  set ec [lindex $l 0]
+  if {[llength $l]>1} {
+    set e  [string length $e]; incr e -1
+    set ei [string length $ec]; incr ei -1
+    foreach l $l {
+      while {$ei>=$e && [string first $ec $l]} {
+       set ec [string range $ec 0 [incr ei -1]]
+      }
+    }
+  }
+  return $ec
+}
+
+
+## ConsoleResource - re'source's this script into current console
+## Meant primarily for my development of this program.  It follows
+## links until the ultimate source is found.
+## 
+set Console(SCRIPT) [info script]
+if !$Console(WWW) {
+  while {[string match link [file type $Console(SCRIPT)]]} {
+    set link [file readlink $Console(SCRIPT)]
+    if [string match relative [file pathtype $link]] {
+      set Console(SCRIPT) [file join [file dirname $Console(SCRIPT)] $link]
+    } else {
+      set Console(SCRIPT) $link
+    }
+  }
+  catch {unset link}
+  if [string match relative [file pathtype $Console(SCRIPT)]] {
+    set Console(SCRIPT) [file join [pwd] $Console(SCRIPT)]
+  }
+}
+
+;proc Console:resource {} {
+  global Console
+  uplevel \#0 [list source $Console(SCRIPT)]
+}
+
+catch {destroy .c}
+console .c
+wm iconify .c
+wm title .c "Tcl Plugin Console"
+wm geometry .c +10+10
diff --git a/extra/stripped.tcl b/extra/stripped.tcl
new file mode 100755 (executable)
index 0000000..64ef1f5
--- /dev/null
@@ -0,0 +1,1083 @@
+#!/bin/sh
+# \
+exec wish4.1 "$0" ${1+"$@"}
+
+#
+## stripped.tcl
+## Stripped down version of Tk Console Widget, part of the VerTcl system
+## Stripped to work with Netscape Tk Plugin.
+##
+## Copyright (c) 1995,1996 by Jeffrey Hobbs
+## jhobbs@cs.uoregon.edu, http://www.cs.uoregon.edu/~jhobbs/
+## source standard_disclaimer.tcl
+
+if {[info tclversion] < 7.5} {
+  error "TkCon requires at least the stable version of tcl7.5/tk4.1"
+}
+
+## tkConInit - inits tkCon
+# ARGS:        root    - widget pathname of the tkCon console root
+#      title   - title for the console root and main (.) windows
+# Calls:       tkConInitUI
+# Outputs:     errors found in tkCon resource file
+##
+proc tkConInit {{title Main}} {
+  global tkCon tcl_platform env auto_path tcl_interactive
+
+  set tcl_interactive 1
+
+  array set tkCon {
+    color,blink                yellow
+    color,proc         darkgreen
+    color,prompt       brown
+    color,stdin                black
+    color,stdout       blue
+    color,stderr       red
+
+    blinktime          500
+    font               fixed
+    lightbrace         1
+    lightcmd           1
+    prompt1            {[history nextid] % }
+    prompt2            {[history nextid] cont > }
+    showmultiple       1
+    slavescript                {}
+
+    cmd {} cmdbuf {} cmdsave {} event 1 svnt 1 cols 80 rows 24
+
+    version    {0.5x Stripped}
+    base       .console
+  }
+
+  if [string comp $tcl_platform(platform) unix] {
+    array set tkCon {
+      font     {Courier 12 {}}
+    }
+  }
+
+  tkConInitUI $title
+
+  interp alias {} clean {} tkConStateRevert tkCon
+  tkConStateCheckpoint tkCon
+}
+
+## tkConInitUI - inits UI portion (console) of tkCon
+## Creates all elements of the console window and sets up the text tags
+# ARGS:        title   - title for the console root and main (.) windows
+# Calls:       tkConInitMenus, tkConPrompt
+##
+proc tkConInitUI {title} {
+  global tkCon
+
+  set root $tkCon(base)
+  if [string match $root .] { set w {} } else { set w [frame $root] }
+
+  set tkCon(console) [text $w.text -font $tkCon(font) -wrap char \
+      -yscrollcommand "$w.sy set" -setgrid 1 -foreground $tkCon(color,stdin)]
+  bindtags $w.text "$w.text PreCon Console PostCon $root all"
+  set tkCon(scrolly) [scrollbar $w.sy \
+      -command "$w.text yview" -takefocus 0 -bd 1]
+
+  pack $w.sy -side left -fill y
+  set tkCon(scrollypos) left
+  pack $w.text -fill both -expand 1
+
+  $w.text insert insert "$title console display active\n" stdout
+  tkConPrompt $w.text
+
+  foreach col {prompt stdout stderr stdin proc} {
+    $w.text tag configure $col -foreground $tkCon(color,$col)
+  }
+  $w.text tag configure blink -background $tkCon(color,blink)
+
+  pack $root -fill both -expand 1
+  focus $w.text
+}
+
+## tkConEval - evaluates commands input into console window
+## This is the first stage of the evaluating commands in the console.
+## They need to be broken up into consituent commands (by tkConCmdSep) in
+## case a multiple commands were pasted in, then each is eval'ed (by
+## tkConEvalCmd) in turn.  Any uncompleted command will not be eval'ed.
+# ARGS:        w       - console text widget
+# Calls:       tkConCmdGet, tkConCmdSep, tkConEvalCmd
+## 
+proc tkConEval {w} {
+  global tkCon
+  tkConCmdSep [tkConCmdGet $w] cmds tkCon(cmd)
+  $w mark set insert end-1c
+  $w insert end \n
+  if [llength $cmds] {
+    foreach cmd $cmds {tkConEvalCmd $w $cmd}
+    $w insert insert $tkCon(cmd) {}
+  } elseif {[info complete $tkCon(cmd)] && ![regexp {[^\\]\\$} $tkCon(cmd)]} {
+    tkConEvalCmd $w $tkCon(cmd)
+  }
+  $w see insert
+}
+
+## tkConEvalCmd - evaluates a single command, adding it to history
+# ARGS:        w       - console text widget
+#      cmd     - the command to evaluate
+# Calls:       tkConPrompt
+# Outputs:     result of command to stdout (or stderr if error occured)
+# Returns:     next event number
+## 
+proc tkConEvalCmd {w cmd} {
+  global tkCon
+  $w mark set output end
+  if [catch {uplevel \#0 history add [list $cmd] exec} result] {
+    $w insert output $result\n stderr
+  } elseif [string comp {} $result] {
+    $w insert output $result\n stdout
+  }
+  tkConPrompt $w
+  set tkCon(svnt) [set tkCon(event) [history nextid]]
+}
+
+## tkConCmdGet - gets the current command from the console widget
+# ARGS:        w       - console text widget
+# Returns:     text which compromises current command line
+## 
+proc tkConCmdGet w {
+  if [string match {} [set ix [$w tag nextrange prompt limit end]]] {
+    $w tag add stdin limit end-1c
+    return [$w get limit end-1c]
+  }
+}
+
+## tkConCmdSep - separates multiple commands into a list and remainder
+# ARGS:        cmd     - (possible) multiple command to separate
+#      list    - varname for the list of commands that were separated.
+#      rmd     - varname of any remainder (like an incomplete final command).
+#              If there is only one command, it's placed in this var.
+# Returns:     constituent command info in varnames specified by list & rmd.
+## 
+proc tkConCmdSep {cmd ls rmd} {
+  upvar $ls cmds $rmd tmp
+  set tmp {}
+  set cmds {}
+  foreach cmd [split [set cmd] \n] {
+    if [string comp {} $tmp] {
+      append tmp \n$cmd
+    } else {
+      append tmp $cmd
+    }
+    if {[info complete $tmp] && ![regexp {[^\\]\\$} $tmp]} {
+      lappend cmds $tmp
+      set tmp {}
+    }
+  }
+  if {[string comp {} [lindex $cmds end]] && [string match {} $tmp]} {
+    set tmp [lindex $cmds end]
+    set cmds [lreplace $cmds end end]
+  }
+}
+
+## tkConPrompt - displays the prompt in the console widget
+# ARGS:        w       - console text widget
+# Outputs:     prompt (specified in tkCon(prompt1)) to console
+## 
+proc tkConPrompt w {
+  global tkCon env
+  set i [$w index end-1c]
+  $w insert end [subst $tkCon(prompt1)] prompt
+  $w mark set output $i
+  $w mark set limit insert
+  $w mark gravity limit left
+}
+
+## tkConStateCheckpoint - checkpoints the current state of the system
+## This allows you to return to this state with tkConStateRevert
+# ARGS:        ary     an array into which several elements are stored:
+#                      commands  - the currently defined commands
+#                      variables - the current global vars
+#              This is the array you would pass to tkConRevertState
+##
+proc tkConStateCheckpoint {ary} {
+  global tkCon
+  upvar $ary a
+  set a(commands)  [uplevel \#0 info commands *]
+  set a(variables) [uplevel \#0 info vars *]
+  return
+}
+
+## tkConStateCompare - compare two states and output difference
+# ARGS:        ary1    an array with checkpointed state
+#      ary2    a second array with checkpointed state
+# Outputs:
+##
+proc tkConStateCompare {ary1 ary2} {
+  upvar $ary1 a1 $ary2 a2
+  puts "Commands unique to $ary1:\n[lremove $a1(commands) $a2(commands)]"
+  puts "Commands unique to $ary2:\n[lremove $a2(commands) $a1(commands)]"
+  puts "Variables unique to $ary1:\n[lremove $a1(variables) $a2(variables)]"
+  puts "Variables unique to $ary2:\n[lremove $a2(variables) $a1(variables)]"
+}
+
+## tkConStateRevert - reverts interpreter to a previous state
+# ARGS:        ary     an array with checkpointed state
+##
+proc tkConStateRevert {ary} {
+  upvar $ary a
+  tkConStateCheckpoint tmp
+  foreach i [lremove $tmp(commands) $a(commands)] { catch "rename $i {}" }
+  foreach i [lremove $tmp(variables) $a(variables)] { uplevel \#0 unset $i }
+}
+
+##
+## Some procedures to make up for lack of built-in shell commands
+##
+
+## puts
+## This allows me to capture all stdout/stderr to the console window
+# ARGS:        same as usual   
+# Outputs:     the string with a color-coded text tag
+## 
+catch {rename puts tcl_puts}
+proc puts args {
+  set len [llength $args]
+  if {$len==1} {
+    eval tkcon console insert output $args stdout {\n} stdout
+    tkcon console see output
+  } elseif {$len==2 &&
+    [regexp {(stdout|stderr|-nonewline)} [lindex $args 0] junk tmp]} {
+    if [string comp $tmp -nonewline] {
+      eval tkcon console insert output [lreplace $args 0 0] $tmp {\n} $tmp
+    } else {
+      eval tkcon console insert output [lreplace $args 0 0] stdout
+    }
+    tkcon console see output
+  } elseif {$len==3 &&
+    [regexp {(stdout|stderr)} [lreplace $args 2 2] junk tmp]} {
+    if [string comp [lreplace $args 1 2] -nonewline] {
+      eval tkcon console insert output [lrange $args 1 1] $tmp
+    } else {
+      eval tkcon console insert output [lreplace $args 0 1] $tmp
+    }
+    tkcon console see output
+  } else {
+    eval tcl_puts $args
+  }
+}
+
+## alias - akin to the csh alias command
+## If called with no args, then it prints out all current aliases
+## If called with one arg, returns the alias of that arg (or {} if none)
+# ARGS:        newcmd  - (optional) command to bind alias to
+#      args    - command and args being aliased
+## 
+proc alias {{newcmd {}} args} {
+  if [string match $newcmd {}] {
+    set res {}
+    foreach a [interp aliases] {
+      lappend res [list $a: [interp alias {} $a]]
+    }
+    return [join $res \n]
+  } elseif {[string match {} $args]} {
+    interp alias {} $newcmd
+  } else {
+    eval interp alias {{}} $newcmd {{}} $args
+  }
+}
+
+## unalias - unaliases an alias'ed command
+# ARGS:        cmd     - command to unbind as an alias
+## 
+proc unalias {cmd} {
+  interp alias {} $cmd {}
+}
+
+## tkcon - command that allows control over the console
+# ARGS:        totally variable, see internal comments
+## 
+proc tkcon {args} {
+  global tkCon
+  switch -- [lindex $args 0] {
+    clean {
+      ## 'cleans' the interpreter - reverting to original tkCon state
+      tkConStateRevert tkCon
+    }
+    console {
+      ## Passes the args to the text widget of the console.
+      eval $tkCon(console) [lreplace $args 0 0]
+    }
+    font {
+      ## "tkcon font ?fontname?".  Sets the font of the console
+      if [string comp {} [lindex $args 1]] {
+       return [$tkCon(console) config -font [lindex $args 1]]
+      } else {
+       return [$tkCon(console) config -font]
+      }
+    }
+    version {
+      return $tkCon(version)
+    }
+    default {
+      ## tries to determine if the command exists, otherwise throws error
+      set cmd [lindex $args 0]
+      set cmd tkCon[string toup [string index $cmd 0]][string range $cmd 1 end]
+      if [string match $cmd [info command $cmd]] {
+       eval $cmd [lreplace $args 0 0]
+      } else {
+       error "bad option \"[lindex $args 0]\": must be attach,\
+               clean, console, font"
+      }
+    }
+  }
+}
+
+## clear - clears the buffer of the console (not the history though)
+## This is executed in the parent interpreter
+## 
+proc clear {{pcnt 100}} {
+  if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} {
+    error "invalid percentage to clear: must be 1-100 (100 default)"
+  } elseif {$pcnt == 100} {
+    tkcon console delete 1.0 end
+  } else {
+    set tmp [expr $pcnt/100.0*[tkcon console index end]]
+    tkcon console delete 1.0 "$tmp linestart"
+  }
+}
+
+## dump - outputs variables/procedure/widget info in source'able form.
+## Accepts glob style pattern matching for the names
+# ARGS:        type    - type of thing to dump: must be variable, procedure, widget
+# OPTS: -nocomplain    don't complain if no vars match something
+# Returns:     the values of the variables in a 'source'able form
+## 
+proc dump {type args} {
+  set whine 1
+  set code ok
+  if [string match \-n* [lindex $args 0]] {
+    set whine 0
+    set args [lreplace $args 0 0]
+  }
+  if {$whine && [string match {} $args]} {
+    error "wrong \# args: [lindex [info level 0] 0] ?-nocomplain? pattern ?pattern ...?"
+  }
+  set res {}
+  switch -glob -- $type {
+    v* {
+      # variable
+      # outputs variables value(s), whether array or simple.
+      foreach arg $args {
+       if {[string match {} [set vars [uplevel info vars [list $arg]]]]} {
+         if {[uplevel info exists $arg]} {
+           set vars $arg
+         } elseif $whine {
+           append res "\#\# No known variable $arg\n"
+           set code error
+           continue
+         } else continue
+       }
+       foreach var [lsort $vars] {
+         upvar $var v
+         if {[array exists v]} {
+           append res "array set $var \{\n"
+           foreach i [lsort [array names v]] {
+             upvar 0 v\($i\) w
+             if {[array exists w]} {
+               append res "    [list $i {NESTED VAR ERROR}]\n"
+               if $whine { set code error }
+             } else {
+               append res "    [list $i $v($i)]\n"
+             }
+           }
+           append res "\}\n"
+         } else {
+           append res [list set $var $v]\n
+         }
+       }
+      }
+    }
+    p* {
+      # procedure
+      foreach arg $args {
+       if {[string comp {} [set ps [info proc $arg]]]} {
+         foreach p [lsort $ps] {
+           set as {}
+           foreach a [info args $p] {
+             if {[info default $p $a tmp]} {
+               lappend as [list $a $tmp]
+             } else {
+               lappend as $a
+             }
+           }
+           append res [list proc $p $as [info body $p]]\n
+         }
+       } elseif $whine {
+         append res "\#\# No known proc $arg\n"
+       }
+      }
+    }
+    w* {
+      # widget
+    }
+    default {
+      return -code error "bad [lindex [info level 0] 0] option\
+       \"[lindex $args 0]\":\ must be procedure, variable, widget"
+    }
+  }
+  return -code $code [string trimr $res \n]
+}
+
+## which - tells you where a command is found
+# ARGS:        cmd     - command name
+# Returns:     where command is found (internal / external / unknown)
+## 
+proc which cmd {
+  if [string comp {} [info commands $cmd]] {
+    if {[lsearch -exact [interp aliases] $cmd] > -1} {
+      return "$cmd:\taliased to [alias $cmd]"
+    } elseif [string comp {} [info procs $cmd]] {
+      return "$cmd:\tinternal proc"
+    } else {
+      return "$cmd:\tinternal command"
+    }
+  } else {
+    return "$cmd:\tunknown command"
+  }
+}
+
+## lremove - remove items from a list
+# OPTS:        -all    remove all instances of each item
+# ARGS:        l       a list to remove items from
+#      is      a list of items to remove
+##
+proc lremove {args} {
+  set all 0
+  if [string match \-a* [lindex $args 0]] {
+    set all 1
+    set args [lreplace $args 0 0]
+  }
+  set l [lindex $args 0]
+  eval append is [lreplace $args 0 0]
+  foreach i $is {
+    if {[set ix [lsearch -exact $l $i]] == -1} continue
+    set l [lreplace $l $ix $ix]
+    if $all {
+      while {[set ix [lsearch -exact $l $i]] != -1} {
+       set l [lreplace $l $i $i]
+      }
+    }
+  }
+  return $l
+}
+
+
+## Unknown changed to get output into tkCon window
+## See $tcl_library/init.tcl for an explanation
+##
+proc unknown args {
+  global auto_noexec auto_noload env unknown_pending tcl_interactive tkCon
+  global errorCode errorInfo
+
+  # Save the values of errorCode and errorInfo variables, since they
+  # may get modified if caught errors occur below.  The variables will
+  # be restored just before re-executing the missing command.
+
+  set savedErrorCode $errorCode
+  set savedErrorInfo $errorInfo
+  set name [lindex $args 0]
+  if ![info exists auto_noload] {
+    #
+    # Make sure we're not trying to load the same proc twice.
+    #
+    if [info exists unknown_pending($name)] {
+      unset unknown_pending($name)
+      if {[array size unknown_pending] == 0} {
+       unset unknown_pending
+      }
+      return -code error "self-referential recursion in \"unknown\" for command \"$name\"";
+    }
+    set unknown_pending($name) pending;
+    set ret [catch {auto_load $name} msg]
+    unset unknown_pending($name);
+    if {$ret != 0} {
+      return -code $ret -errorcode $errorCode \
+         "error while autoloading \"$name\": $msg"
+    }
+    if ![array size unknown_pending] {
+      unset unknown_pending
+    }
+    if $msg {
+      set errorCode $savedErrorCode
+      set errorInfo $savedErrorInfo
+      set code [catch {uplevel $args} msg]
+      if {$code ==  1} {
+       #
+       # Strip the last five lines off the error stack (they're
+       # from the "uplevel" command).
+       #
+
+       set new [split $errorInfo \n]
+       set new [join [lrange $new 0 [expr [llength $new] - 6]] \n]
+       return -code error -errorcode $errorCode \
+           -errorinfo $new $msg
+      } else {
+       return -code $code $msg
+      }
+    }
+  }
+  if {[info level] == 1 && [string match {} [info script]] \
+         && [info exists tcl_interactive] && $tcl_interactive} {
+    if ![info exists auto_noexec] {
+      if [auto_execok $name] {
+       set errorCode $savedErrorCode
+       set errorInfo $savedErrorInfo
+       return [uplevel exec $args]
+       #return [uplevel exec >&@stdout <@stdin $args]
+      }
+    }
+    set errorCode $savedErrorCode
+    set errorInfo $savedErrorInfo
+    if {[string match $name !!]} {
+      catch {set tkCon(cmd) [history event]}
+      return [uplevel {history redo}]
+    } elseif [regexp {^!(.+)$} $name dummy event] {
+      catch {set tkCon(cmd) [history event $event]}
+      return [uplevel [list history redo $event]]
+    } elseif [regexp {^\^([^^]*)\^([^^]*)\^?$} $name dummy old new] {
+      catch {set tkCon(cmd) [history substitute $old $new]}
+      return [uplevel [list history substitute $old $new]]
+    }
+    set cmds [info commands $name*]
+    if {[llength $cmds] == 1} {
+      return [uplevel [lreplace $args 0 0 $cmds]]
+    } elseif {[llength $cmds]} {
+      if {$name == ""} {
+       return -code error "empty command name \"\""
+      } else {
+       return -code error \
+           "ambiguous command name \"$name\": [lsort $cmds]"
+      }
+    }
+  }
+  return -code error "invalid command name \"$name\""
+}
+
+
+# tkConClipboardKeysyms --
+# This procedure is invoked to identify the keys that correspond to
+# the "copy", "cut", and "paste" functions for the clipboard.
+#
+# Arguments:
+# copy -       Name of the key (keysym name plus modifiers, if any,
+#              such as "Meta-y") used for the copy operation.
+# cut -                Name of the key used for the cut operation.
+# paste -      Name of the key used for the paste operation.
+
+proc tkConCut w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {
+      clipboard append -displayof $w [selection get -displayof $w]
+      if [$w compare sel.first >= limit] {$w delete sel.first sel.last}
+    }
+  }
+}
+proc tkConCopy w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {clipboard append -displayof $w [selection get -displayof $w]}
+  }
+}
+
+proc tkConPaste w {
+  if ![catch {selection get -displayof $w -selection CLIPBOARD} tmp] {
+    if [$w compare insert < limit] {$w mark set insert end}
+    $w insert insert $tmp
+    $w see insert
+    if [string match *\n* $tmp] {tkConEval $w}
+  }
+}
+
+proc tkConClipboardKeysyms {copy cut paste} {
+  bind Console <$copy> {tkConCopy %W}
+  bind Console <$cut>  {tkConCut %W}
+  bind Console <$paste>        {tkConPaste %W}
+}
+
+## Get all Text bindings into Console
+##
+foreach ev [lremove [bind Text] {<Control-Key-y> <Control-Key-w> \
+                                    <Meta-Key-w> <Control-Key-o>}] {
+  bind Console $ev [bind Text $ev]
+}
+unset ev
+
+## Redefine for Console what we need
+##
+tkConClipboardKeysyms F16 F20 F18
+tkConClipboardKeysyms Control-c Control-x Control-v
+
+bind Console <Insert> {catch {tkConInsert %W [selection get -displayof %W]}}
+
+bind Console <Up> {
+  if [%W compare {insert linestart} != {limit linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W -1]
+  } else {
+    if {$tkCon(event) == [history nextid]} {
+      set tkCon(cmdbuf) [tkConCmdGet %W]
+    }
+    if [catch {history event [incr tkCon(event) -1]} tkCon(tmp)] {
+      incr tkCon(event)
+    } else {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      %W see end
+    }
+  }
+}
+bind Console <Down> {
+  if [%W compare {insert linestart} != {end-1c linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W 1]
+  } else {
+    if {$tkCon(event) < [history nextid]} {
+      %W delete limit end
+      if {[incr tkCon(event)] == [history nextid]} {
+       %W insert limit $tkCon(cmdbuf)
+      } else {
+       %W insert limit [history event $tkCon(event)]
+      }
+      %W see end
+    }
+  }
+}
+bind Console <Control-P> {
+  if [%W compare insert > limit] {tkConExpand %W proc}
+}
+bind Console <Control-V> {
+  if [%W compare insert > limit] {tkConExpand %W var}
+}
+bind Console <Control-i> {
+  if [%W compare insert >= limit] {
+    tkConInsert %W \t
+  }
+}
+bind Console <Return> {
+  tkConEval %W
+}
+bind Console <KP_Enter> [bind Console <Return>]
+bind Console <Delete> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+         && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif [%W compare insert >= limit] {
+    %W delete insert
+    %W see insert
+  }
+}
+bind Console <BackSpace> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+         && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif {[%W compare insert != 1.0] && [%W compare insert-1c >= limit]} {
+    %W delete insert-1c
+    %W see insert
+  }
+}
+bind Console <Control-h> [bind Console <BackSpace>]
+
+bind Console <KeyPress> {
+  tkConInsert %W %A
+}
+
+bind Console <Control-a> {
+  if [%W compare {limit linestart} == {insert linestart}] {
+    tkTextSetCursor %W limit
+  } else {
+    tkTextSetCursor %W {insert linestart}
+  }
+}
+bind Console <Control-d> {
+  if [%W compare insert < limit] break
+  %W delete insert
+}
+bind Console <Control-k> {
+  if [%W compare insert < limit] break
+  if [%W compare insert == {insert lineend}] {
+    %W delete insert
+  } else {
+    %W delete insert {insert lineend}
+  }
+}
+bind Console <Control-l> {
+  ## Clear console buffer, without losing current command line input
+  set tkCon(tmp) [tkConCmdGet %W]
+  clear
+  tkConPrompt
+  tkConInsert %W $tkCon(tmp)
+}
+bind Console <Control-n> {
+  ## Goto next command in history
+  if {$tkCon(event) < [history nextid]} {
+    %W delete limit end
+    if {[incr tkCon(event)] == [history nextid]} {
+      %W insert limit $tkCon(cmdbuf)
+    } else {
+      %W insert limit [history event $tkCon(event)]
+    }
+    %W see end
+  }
+}
+bind Console <Control-p> {
+  ## Goto previous command in history
+  if {$tkCon(event) == [history nextid]} {
+    set tkCon(cmdbuf) [tkConCmdGet %W]
+  }
+  if [catch {history event [incr tkCon(event) -1]} tkCon(tmp)] {
+    incr tkCon(event)
+  } else {
+    %W delete limit end
+    %W insert limit $tkCon(tmp)
+    %W see end
+  }
+}
+bind Console <Control-r> {
+  ## Search history reverse
+  if {$tkCon(svnt) == [history nextid]} {
+    set tkCon(cmdbuf) [tkConCmdGet %W]
+  }
+  set tkCon(tmp1) [string len $tkCon(cmdbuf)]
+  incr tkCon(tmp1) -1
+  while 1 {
+    if {[catch {history event [incr tkCon(svnt) -1]} tkCon(tmp)]} {
+      incr tkCon(svnt)
+      break
+    } elseif {![string comp $tkCon(cmdbuf) \
+       [string range $tkCon(tmp) 0 $tkCon(tmp1)]]} {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      break
+    }
+  }
+  %W see end
+}
+bind Console <Control-s> {
+  ## Search history forward
+  set tkCon(tmp1) [string len $tkCon(cmdbuf)]
+  incr tkCon(tmp1) -1
+  while {$tkCon(svnt) < [history nextid]} {
+    if {[incr tkCon(svnt)] == [history nextid]} {
+      %W delete limit end
+      %W insert limit $tkCon(cmdbuf)
+      break
+    } elseif {![catch {history event $tkCon(svnt)} tkCon(tmp)]
+             && ![string comp $tkCon(cmdbuf) \
+                      [string range $tkCon(tmp) 0 $tkCon(tmp1)]]} {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      break
+    }
+  }
+  %W see end
+}
+bind Console <Control-t> {
+  ## Transpose current and previous chars
+  if [%W compare insert > limit] {
+    tkTextTranspose %W
+  }
+}
+bind Console <Control-u> {
+  ## Clear command line (Unix shell staple)
+  %W delete limit end
+}
+bind Console <Control-z> {
+  ## Save command buffer
+  set tkCon(tmp) $tkCon(cmdsave)
+  set tkCon(cmdsave) [tkConCmdGet %W]
+  if {[string match {} $tkCon(cmdsave)]} {
+    set tkCon(cmdsave) $tkCon(tmp)
+  } else {
+    %W delete limit end-1c
+  }
+  tkConInsert %W $tkCon(tmp)
+  %W see end
+}
+catch {bind Console <Key-Page_Up>   { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Prior>     { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Page_Down> { tkTextScrollPages %W 1 }}
+catch {bind Console <Key-Next>      { tkTextScrollPages %W 1 }}
+bind Console <Meta-d> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <Meta-BackSpace> {
+  if [%W compare {insert -1c wordstart} >= limit] {
+    %W delete {insert -1c wordstart} insert
+  }
+}
+bind Console <Meta-Delete> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <ButtonRelease-2> {
+  if {(!$tkPriv(mouseMoved) || $tk_strictMotif) \
+         && ![catch {selection get -displayof %W} tkCon(tmp)]} {
+    if [%W compare @%x,%y < limit] {
+      %W insert end $tkCon(tmp)
+    } else {
+      %W insert @%x,%y $tkCon(tmp)
+    }
+    if [string match *\n* $tkCon(tmp)] {tkConEval %W}
+  }
+}
+
+##
+## End weird bindings
+##
+
+##
+## PostCon bindings, for doing special things based on certain keys
+##
+bind PostCon <Key-parenright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \( \)
+  }
+}
+bind PostCon <Key-bracketright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \[ \]
+  }
+}
+bind PostCon <Key-braceright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \{ \}
+  }
+}
+bind PostCon <Key-quotedbl> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchQuote %W
+  }
+}
+
+bind PostCon <KeyPress> {
+  if {$tkCon(lightcmd) && [string comp {} %A]} { tkConTagProc %W }
+}
+
+## tkConTagProc - tags a procedure in the console if it's recognized
+## This procedure is not perfect.  However, making it perfect wastes
+## too much CPU time...  Also it should check the existence of a command
+## in whatever is the connected slave, not the master interpreter.
+##
+proc tkConTagProc w {
+  set i [$w index "insert-1c wordstart"]
+  set j [$w index "insert-1c wordend"]
+  if {[string comp {} [info command [list [$w get $i $j]]]]} {
+    $w tag add proc $i $j
+  } else {
+    $w tag remove proc $i $j
+  }
+}
+
+
+## tkConMatchPair - blinks a matching pair of characters
+## c2 is assumed to be at the text index 'insert'.
+## This proc is really loopy and took me an hour to figure out given
+## all possible combinations with escaping except for escaped \'s.
+## It doesn't take into account possible commenting... Oh well.  If
+## anyone has something better, I'd like to see/use it.  This is really
+## only efficient for small contexts.
+# ARGS:        w       - console text widget
+#      c1      - first char of pair
+#      c2      - second char of pair
+# Calls:       tkConBlink
+## 
+proc tkConMatchPair {w c1 c2} {
+  if [string comp {} [set ix [$w search -back $c1 insert limit]]] {
+    while {[string match {\\} [$w get $ix-1c]] &&
+          [string comp {} [set ix [$w search -back $c1 $ix-1c limit]]]} {}
+    set i1 insert-1c
+    while {[string comp {} $ix]} {
+      set i0 $ix
+      set j 0
+      while {[string comp {} [set i0 [$w search $c2 $i0 $i1]]]} {
+       append i0 +1c
+       if {[string match {\\} [$w get $i0-2c]]} continue
+       incr j
+      }
+      if {!$j} break
+      set i1 $ix
+      while {$j &&
+            [string comp {} [set ix [$w search -back $c1 $ix limit]]]} {
+       if {[string match {\\} [$w get $ix-1c]]} continue
+       incr j -1
+      }
+    }
+    if [string match {} $ix] { set ix [$w index limit] }
+  } else { set ix [$w index limit] }
+  tkConBlink $w $ix [$w index insert]
+}
+
+## tkConMatchQuote - blinks between matching quotes.
+## Blinks just the quote if it's unmatched, otherwise blinks quoted string
+## The quote to match is assumed to be at the text index 'insert'.
+# ARGS:        w       - console text widget
+# Calls:       tkConBlink
+## 
+proc tkConMatchQuote w {
+  set i insert-1c
+  set j 0
+  while {[string comp {} [set i [$w search -back \" $i limit]]]} {
+    if {[string match {\\} [$w get $i-1c]]} continue
+    if {!$j} {set i0 $i}
+    incr j
+  }
+  if [expr $j%2] {
+    tkConBlink $w $i0 [$w index insert]
+  } else {
+    tkConBlink $w [$w index insert-1c] [$w index insert]
+  }
+}
+
+## tkConBlink - blinks between 2 indices for a specified duration.
+# ARGS:        w       - console text widget
+#      i1      - start index to blink region
+#      i2      - end index of blink region
+#      dur     - duration in usecs to blink for
+# Outputs:     blinks selected characters in $w
+## 
+proc tkConBlink {w i1 i2} {
+  global tkCon
+  $w tag add blink $i1 $i2
+  after $tkCon(blinktime) $w tag remove blink $i1 $i2
+  return
+}
+
+
+## tkConInsert
+## Insert a string into a text at the point of the insertion cursor.
+## If there is a selection in the text, and it covers the point of the
+## insertion cursor, then delete the selection before inserting.
+# ARGS:        w       - text window in which to insert the string
+#      s       - string to insert (usually just a single char)
+# Outputs:     $s to text widget
+## 
+proc tkConInsert {w s} {
+  if {[string match {} $s] || [string match disabled [$w cget -state]]} {
+    return
+  }
+  if [$w comp insert < limit] {
+    $w mark set insert end
+  }
+  catch {
+    if {[$w comp sel.first <= insert] && [$w comp sel.last >= insert]} {
+      $w delete sel.first sel.last
+    }
+  }
+  $w insert insert $s
+  $w see insert
+}
+
+## tkConExpand - 
+# ARGS:        w       - text widget in which to expand str
+#      type    - type of expansion (path / proc / variable)
+# Calls:       tkConExpand(Pathname|Procname|Variable)
+# Outputs:     The string to match is expanded to the longest possible match.
+#              If tkCon(showmultiple) is non-zero and the user longest match
+#              equaled the string to expand, then all possible matches are
+#              output to stdout.  Triggers bell if no matches are found.
+# Returns:     number of matches found
+## 
+proc tkConExpand {w type} {
+  set exp "\[^\\]\[ \t\n\r\[\{\"\$]"
+  set tmp [$w search -back -regexp $exp insert-1c limit-1c]
+  if [string compare {} $tmp] {append tmp +2c} else {set tmp limit}
+  if [$w compare $tmp >= insert] return
+  set str [$w get $tmp insert]
+  switch -glob $type {
+    pr* {set res [tkConExpandProcname $str]}
+    v*  {set res [tkConExpandVariable $str]}
+    default {set res {}}
+  }
+  set len [llength $res]
+  if $len {
+    $w delete $tmp insert
+    $w insert $tmp [lindex $res 0]
+    if {$len > 1} {
+      global tkCon
+      if {$tkCon(showmultiple) && [string match [lindex $res 0] $str]} {
+       puts stdout [lreplace $res 0 0]
+      }
+    }
+  }
+  return [incr len -1]
+}
+
+## tkConExpandProcname - expand a tcl proc name based on $str
+# ARGS:        str     - partial proc name to expand
+# Calls:       tkConExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+proc tkConExpandProcname str {
+  set match [info commands $str*]
+  if {[llength $match] > 1} {
+    regsub -all { } [tkConExpandBestMatch $match $str] {\\ } str
+    set match [linsert $match 0 $str]
+  } else {
+    regsub -all { } $match {\\ } match
+  }
+  return $match
+}
+
+## tkConExpandVariable - expand a tcl variable name based on $str
+# ARGS:        str     - partial tcl var name to expand
+# Calls:       tkConExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+proc tkConExpandVariable str {
+  if [regexp {([^\(]*)\((.*)} $str junk ary str] {
+    set match [uplevel \#0 array names $ary $str*]
+    if {[llength $match] > 1} {
+      set vars $ary\([tkConExpandBestMatch $match $str]
+      foreach var $match {lappend vars $ary\($var\)}
+      return $vars
+    } else {set match $ary\($match\)}
+  } else {
+    set match [uplevel \#0 info vars $str*]
+    if {[llength $match] > 1} {
+      regsub -all { } [tkConExpandBestMatch $match $str] {\\ } str
+      set match [linsert $match 0 $str]
+    } else {
+      regsub -all { } $match {\\ } match
+    }
+  }
+  return $match
+}
+
+## tkConExpandBestMatch - finds the best unique match in a list of names
+## The extra $e in this argument allows us to limit the innermost loop a
+## little further.  This improves speed as $l becomes large or $e becomes long.
+# ARGS:        l       - list to find best unique match in
+#      e       - currently best known unique match
+# Returns:     longest unique match in the list
+## 
+proc tkConExpandBestMatch {l {e {}}} {
+  set ec [lindex $l 0]
+  if {[llength $l]>1} {
+    set e  [string length $e]; incr e -1
+    set ei [string length $ec]; incr ei -1
+    foreach l $l {
+      while {$ei>=$e && [string first $ec $l]} {
+       set ec [string range $ec 0 [incr ei -1]]
+      }
+    }
+  }
+  return $ec
+}
+
+
+## Initialize only if we haven't yet
+##
+if [catch {winfo exists $tkCon(base)}] tkConInit
diff --git a/tkcon.tcl b/tkcon.tcl
new file mode 100755 (executable)
index 0000000..53091e7
--- /dev/null
+++ b/tkcon.tcl
@@ -0,0 +1,2141 @@
+#!/bin/sh
+# The wish executable needs to be Tk4.1+ \
+exec wish "$0" ${1+"$@"}
+
+#
+## tkcon.tcl
+## Tk Console Widget, part of the VerTcl system
+##
+## Based (loosely) off Brent Welch's Tcl Shell Widget
+##
+## Thanks especially to the following for bug reports & code ideas:
+## Steven Wahl <steven@indra.com>
+## Jan Nijtmans <nijtmans@nici.kun.nl>
+## Crimmins < @umich.edu somewhere >
+##
+## Copyright 1995,1996 Jeffrey Hobbs.  All rights reserved.
+## Initiated: Thu Aug 17 15:36:47 PDT 1995
+##
+## jhobbs@cs.uoregon.edu, http://www.cs.uoregon.edu/~jhobbs/
+##
+## source standard_disclaimer.tcl
+
+if [catch {package require Tk 4.1}] {
+  error "TkCon requires at least the stable version of tcl7.5/tk4.1"
+}
+package ifneeded Tk $tk_version {load {} Tk}
+
+## warn - little helper proc to pop up a tk_dialog warning message
+# ARGS:        msg     - message you want to display to user
+##
+proc warn { msg } {
+  bell
+  tk_dialog ._warning Warning $msg warning 0 OK
+}
+
+## tkConInit - inits tkCon
+# ARGS:        root    - widget pathname of the tkCon console root
+#      title   - title for the console root and main (.) windows
+# Calls:       tkConInitUI
+# Outputs:     errors found in tkCon resource file
+##
+proc tkConInit {} {
+  global tkCon tcl_interactive tcl_platform env auto_path argv0 argc argv
+
+  set tcl_interactive 1
+
+  if [info exists tkCon(name)] {
+    set title $tkCon(name)
+  } else {
+    tkConMainInit
+    set title Main
+  }
+
+  array set tkCon {
+    color,blink                yellow
+    color,proc         darkgreen
+    color,prompt       brown
+    color,stdin                black
+    color,stdout       blue
+    color,stderr       red
+
+    blinktime          500
+    font               fixed
+    history            32
+    library            {}
+    lightbrace         1
+    lightcmd           0
+    loadTk             0
+    maineval           {}
+    nontcl             0
+    prompt1            {([file tail [pwd]]) [history nextid] % }
+    prompt2            {[history nextid] cont > }
+    rcfile             .tkconrc
+    scrollypos         left
+    showmultiple       1
+    showmenu           1
+    slaveeval          {}
+    subhistory         1
+
+    exec slave app {} appname {} apptype slave cmd {} cmdbuf {} cmdsave {}
+    event 1 svnt 1 cols 80 rows 24 deadapp 0
+    errorInfo          {}
+    slavealias         { tkcon warn }
+    slaveprocs         { alias clear dir dump lremove puts tclindex \
+                             auto_execpath unknown unalias which }
+    version    0.52
+    root       .
+  }
+
+  ## If there appear to be children of '.', then make sure we use
+  ## a disassociated toplevel.
+  if [string compare {} [winfo children .]] {
+    set tkCon(root) .tkcon
+  }
+
+  if [string compare unix $tcl_platform(platform)] {
+    array set tkCon {
+      font     {Courier 12 {}}
+      rcfile   tkcon.cfg
+    }
+  }
+
+  if [info exists env(HOME)] {
+    set tkCon(rcfile) [file join $env(HOME) $tkCon(rcfile)]
+  }
+
+  ## Handle command line arguments before sourcing resource file to
+  ## find if resource file is being specified (let other args pass).
+  for {set i 0} {$i < $argc} {incr i} {
+    if [string match \-rcfile [lindex $argv $i]] {
+      set tkCon(rcfile) [lindex $argv [incr i]]
+    }
+  }
+
+  if [file exists $tkCon(rcfile)] {
+    set code [catch [list uplevel \#0 source $tkCon(rcfile)] err]
+  }
+
+  if [info exists env(TK_CON_LIBRARY)] {
+    eval lappend auto_path $env(TK_CON_LIBRARY)
+  } else {
+    eval lappend auto_path $tkCon(library)
+  }
+
+  set dir [file dir [info nameofexec]]
+  foreach dir [list $dir [file join [file dir $dir] lib]] {
+    if [file exists [file join $dir pkgIndex.tcl]] {
+      if {[lsearch -exact $auto_path $dir] < 0} {
+       lappend auto_path $dir
+      }
+    }
+  }
+
+  foreach dir $auto_path {
+    if [file exists [file join $dir pkgIndex.tcl]] {
+      source [file join $dir pkgIndex.tcl]
+    }
+  }
+
+  ## Handle rest of command line arguments after sourcing resource file
+  ## and slave is created, but before initializing UI or setting packages.
+  set slaveargs {}
+  set slavefiles {}
+  for {set i 0} {$i < $argc} {incr i} {
+    set arg [lindex $argv $i]
+    if [regexp -- {-.+} $arg] {
+      ## Handle arg based options
+      switch -- $arg {
+       -rcfile         { incr i }
+       -maineval - -e -
+       -eval           { append tkCon(maineval) [lindex $argv [incr i]]\n }
+       -slave - -slavescript -
+       -slaveeval      { append tkCon(slaveeval) [lindex $argv [incr i]]\n }
+       -package - -pkg -
+       -load           { set tkCon(load[lindex $argv [incr i]]) 1 }
+       -nontcl         { set tkCon(nontcl) 0 }
+       -root           { set tkCon(root) [lindex $argv [incr i]] }
+       default         { lappend slaveargs $arg }
+      }
+    } elseif {[file isfile $arg]} {
+      lappend slavefiles $arg
+    } else {
+      lappend slaveargs $arg
+    }
+  }
+
+  ## Create slave executable
+  if [string comp {} $tkCon(exec)] {
+    eval tkConInitSlave $tkCon(exec) $slaveargs
+  }
+
+  tkConAttach $tkCon(appname) $tkCon(apptype)
+  tkConInitUI $title
+
+  ## Set up package info for the slave
+  tkConCheckPackages
+
+  ## Evaluate maineval in slave
+  if {[string comp {} $tkCon(maineval)] &&
+      [catch {uplevel \#0 $tkCon(maineval)} merr]} {
+    puts stderr "error in eval:\n$merr"
+  }
+
+  ## Source extra command line argument files into slave executable
+  foreach fn $slavefiles {
+    puts -nonewline "slave sourcing $fn ... "
+    if {[catch {tkConEvalSlave source $fn} fnerr]} {
+      puts stderr "error:\n$fnerr"
+    } else {
+      puts "OK"
+    }
+  }
+
+  interp alias {} ls {} dir
+  #interp alias $tkCon(exec) clean {} tkConStateRevert tkCon
+  #tkConStateCheckpoint tkCon
+
+  ## Evaluate slaveeval in slave
+  if {[string comp {} $tkCon(slaveeval)] &&
+      [catch {interp eval $tkCon(exec) $tkCon(slaveeval)} serr]} {
+    puts stderr "error in slave script:\n$serr"
+  }
+  ## Output any error/output that may have been returned from rcfile
+  if {[info exists code] && [string comp {} $err]} {
+    if $code {
+      puts stderr "error in $tkCon(rcfile):\n$err"
+    } else {
+      puts stdout "returned from $tkCon(rcfile):\n$err"
+    }
+  }
+}
+
+## tkConInitSlave - inits the slave by placing key procs and aliases in it
+## It's arg[cv] are based on passed in options, while argv0 is the same as
+## the master.  tcl_interactive is the same as the master as well.
+# ARGS:        slave   - name of slave to init.  If it does not exist, it is created.
+#      args    - args to pass to a slave as argv/argc
+##
+proc tkConInitSlave {slave args} {
+  global tkCon argv0 tcl_interactive
+  if [string match {} $slave] {
+    error "Don't init the master interpreter, goofball"
+  }
+  if ![interp exists $slave] { interp create $slave }
+  if {[string match {} [$slave eval info command tcl_puts]]} {
+    interp eval $slave rename puts tcl_puts
+  }
+  foreach cmd $tkCon(slaveprocs) { interp eval $slave [dump proc $cmd] }
+  foreach cmd $tkCon(slavealias) { interp alias $slave $cmd {} $cmd }
+  interp alias $slave ls $slave dir
+  interp eval $slave set tcl_interactive $tcl_interactive \; \
+      set argv0 [list $argv0] \; set argc [llength $args] \; \
+      set argv  [list $args] \; history keep $tkCon(history)
+  
+  foreach pkg [lremove [package names] Tcl] {
+    foreach v [package versions $pkg] {
+      interp eval $slave [list package ifneeded $pkg $v \
+                             [package ifneeded $pkg $v]]
+    }
+  }
+}
+
+## tkConInitUI - inits UI portion (console) of tkCon
+## Creates all elements of the console window and sets up the text tags
+# ARGS:        root    - widget pathname of the tkCon console root
+#      title   - title for the console root and main (.) windows
+# Calls:       tkConInitMenus, tkConPrompt
+##
+proc tkConInitUI {title} {
+  global tkCon
+
+  set root $tkCon(root)
+  if [string match . $root] { set w {} } else { set w [toplevel $root] }
+  set tkCon(base) $w
+  wm withdraw $root
+
+  set tkCon(menubar) [frame $w.mbar -relief raised -bd 2]
+  set tkCon(console) [text $w.text -font $tkCon(font) -wrap char \
+      -yscrollcommand "$w.sy set" -setgrid 1 -foreground $tkCon(color,stdin)]
+  bindtags $w.text "$w.text PreCon Console PostCon $root all"
+  set tkCon(scrolly) [scrollbar $w.sy -takefocus 0 -bd 1 \
+                         -command "$w.text yview"]
+
+  tkConInitMenus $tkCon(menubar)
+
+  if $tkCon(showmenu) { pack $tkCon(menubar) -fill x }
+  pack $tkCon(scrolly) -side $tkCon(scrollypos) -fill y
+  pack $tkCon(console) -fill both -expand 1
+
+  tkConPrompt "$title console display active\n"
+
+  foreach col {prompt stdout stderr stdin proc} {
+    $w.text tag configure $col -foreground $tkCon(color,$col)
+  }
+  $w.text tag configure blink -background $tkCon(color,blink)
+
+  bind $w.text <Configure> {
+    scan [wm geometry [winfo toplevel %W]] "%%dx%%d" tkCon(cols) tkCon(rows)
+  }
+
+  wm title $root "tkCon $tkCon(version) $title"
+  wm deiconify $root
+  focus $w.text
+}
+
+## tkConEval - evaluates commands input into console window
+## This is the first stage of the evaluating commands in the console.
+## They need to be broken up into consituent commands (by tkConCmdSep) in
+## case a multiple commands were pasted in, then each is eval'ed (by
+## tkConEvalCmd) in turn.  Any uncompleted command will not be eval'ed.
+# ARGS:        w       - console text widget
+# Calls:       tkConCmdGet, tkConCmdSep, tkConEvalCmd
+## 
+proc tkConEval {w} {
+  global tkCon
+  tkConCmdSep [tkConCmdGet $w] cmds tkCon(cmd)
+  $w mark set insert end-1c
+  $w insert end \n
+  if [llength $cmds] {
+    foreach cmd $cmds {tkConEvalCmd $w $cmd}
+    $w insert insert $tkCon(cmd) {}
+  } elseif {[info complete $tkCon(cmd)] && ![regexp {[^\\]\\$} $tkCon(cmd)]} {
+    tkConEvalCmd $w $tkCon(cmd)
+  }
+  $w see insert
+}
+
+## tkConEvalCmd - evaluates a single command, adding it to history
+# ARGS:        w       - console text widget
+#      cmd     - the command to evaluate
+# Calls:       tkConPrompt
+# Outputs:     result of command to stdout (or stderr if error occured)
+# Returns:     next event number
+## 
+proc tkConEvalCmd {w cmd} {
+  global tkCon
+  $w mark set output end
+  if [string comp {} $cmd] {
+    set err 0
+    if $tkCon(subhistory) {
+      set ev [tkConEvalSlave history nextid]
+      incr ev -1
+      if {[string match !! $cmd]} {
+       set err [catch {tkConEvalSlave history event $ev} cmd]
+      } elseif [regexp {^!(.+)$} $cmd dummy event] {
+       set err [catch {tkConEvalSlave history event $event} cmd]
+      } elseif [regexp {^\^([^^]*)\^([^^]*)\^?$} $cmd dummy old new] {
+       if ![set err [catch {tkConEvalSlave history event $ev} cmd]] {
+         regsub -all -- $old $cmd $new cmd
+       }
+      }
+    }
+    if $err {
+      $w insert output $cmd\n stderr
+    } else {
+      if [string match {} $tkCon(appname)] {
+       if [catch {tkConEvalSlave eval $cmd} res] {
+         set tkCon(errorInfo) [tkConEvalSlave set errorInfo]
+         set err 1
+       }
+      } else {
+       if {$tkCon(nontcl) && [string match interp $tkCon(apptype)]} {
+         if [catch "tkConEvalSend $cmd" res] {
+           set tkCon(errorInfo) {Non-Tcl errorInfo not available}
+           set err 1
+         }
+       } else {
+         if [catch [list tkConEvalAttached $cmd] res] {
+           set tkCon(errorInfo) [tkConEvalAttached set errorInfo]
+           set err 1
+         }
+       }
+      }
+      tkConEvalSlave history add $cmd
+      if $err {
+       $w insert output $res\n stderr
+      } elseif [string comp {} $res] {
+       $w insert output $res\n stdout
+      }
+    }
+  }
+  tkConPrompt
+  set tkCon(svnt) [set tkCon(event) [tkConEvalSlave history nextid]]
+}
+
+## tkConEvalSlave - evaluates the args in the associated slave
+# ARGS:        args    - the command and args to evaluate
+##
+proc tkConEvalSlave args {
+  global tkCon
+  interp eval $tkCon(exec) $args
+}
+
+## tkConEvalSend - sends the args to the attached interpreter
+## Varies from 'send' by determining whether attachment is dead
+## when an error is received
+# ARGS:        args    - the args to send across
+# Returns:     the result of the command
+##
+proc tkConEvalSend args {
+  global tkCon
+  if $tkCon(deadapp) {
+    if {[lsearch -exact [winfo interps] $tkCon(app)]<0} {
+      return
+    } else {
+      set tkCon(appname) [string range $tkCon(appname) 5 end]
+      set tkCon(deadapp) 0
+      tkConPrompt "\n\"$tkCon(app)\" alive\n" [tkConCmdGet $tkCon(console)]
+    }
+  }
+  set code [catch {eval send [list $tkCon(app)] $args} result]
+  if {$code && [lsearch -exact [winfo interps] $tkCon(app)]<0} {
+    ## Interpreter disappeared
+    if [tk_dialog $tkCon(base).dead "Dead Attachment" \
+           "\"$tkCon(app)\" appears to have died.\nReturn to primary slave interpreter?" questhead 0 OK No] {
+      set tkCon(appname) "DEAD:$tkCon(appname)"
+      set tkCon(deadapp) 1
+    } else {
+      set err "Attached Tk interpreter \"$tkCon(app)\" died."
+      tkConAttach {}
+      tkConEvalSlave set errorInfo $err
+    }
+    tkConPrompt \n [tkConCmdGet $tkCon(console)]
+  }
+  return -code $code $result
+}
+
+## tkConCmdGet - gets the current command from the console widget
+# ARGS:        w       - console text widget
+# Returns:     text which compromises current command line
+## 
+proc tkConCmdGet w {
+  if [string match {} [set ix [$w tag nextrange prompt limit end]]] {
+    $w tag add stdin limit end-1c
+    return [$w get limit end-1c]
+  }
+}
+
+## tkConCmdSep - separates multiple commands into a list and remainder
+# ARGS:        cmd     - (possible) multiple command to separate
+#      list    - varname for the list of commands that were separated.
+#      rmd     - varname of any remainder (like an incomplete final command).
+#              If there is only one command, it's placed in this var.
+# Returns:     constituent command info in varnames specified by list & rmd.
+## 
+proc tkConCmdSep {cmd ls rmd} {
+  upvar $ls cmds $rmd tmp
+  set tmp {}
+  set cmds {}
+  foreach cmd [split [set cmd] \n] {
+    if [string comp {} $tmp] {
+      append tmp \n$cmd
+    } else {
+      append tmp $cmd
+    }
+    if {[info complete $tmp] && ![regexp {[^\\]\\$} $tmp]} {
+      lappend cmds $tmp
+      set tmp {}
+    }
+  }
+  if {[string comp {} [lindex $cmds end]] && [string match {} $tmp]} {
+    set tmp [lindex $cmds end]
+    set cmds [lreplace $cmds end end]
+  }
+}
+
+## tkConPrompt - displays the prompt in the console widget
+# ARGS:        w       - console text widget
+# Outputs:     prompt (specified in tkCon(prompt1)) to console
+## 
+proc tkConPrompt {{pre {}} {post {}}} {
+  global tkCon
+  set w $tkCon(console)
+  if [string comp {} $pre] { $w insert end $pre stdout }
+  set i [$w index end-1c]
+  if [string comp {} $tkCon(appname)] {
+    $w insert end ">$tkCon(appname)< " prompt
+  }
+  $w insert end [tkConEvalSlave subst $tkCon(prompt1)] prompt
+  $w mark set output $i
+  $w mark set limit insert
+  $w mark gravity limit left
+  if [string comp {} $post] { $w insert end $post stdin }
+  $w see end
+}
+
+## tkConAbout - gives about info for tkCon
+## 
+proc tkConAbout {} {
+  global tkCon
+  tk_dialog $tkCon(base).about "About TkCon v$tkCon(version)" \
+      "Jeffrey Hobbs, Copyright 1995-96\njhobbs@cs.uoregon.edu\
+       \nhttp://www.cs.uoregon.edu/~jhobbs/" questhead 0 OK
+}
+
+## tkConHelp - gives help info for tkCon
+## 
+proc tkConHelp {} {
+  global tkCon
+  tk_dialog $tkCon(base).help "Help on TkCon v$tkCon(version)" \
+      "Jeffrey Hobbs, jhobbs@cs.uoregon.edu\nHelp available at:\
+      http://www.cs.uoregon.edu/~jhobbs/work/tkcon/" questhead 0 OK
+}
+
+## tkConInitMenus - inits the menus for the console
+# ARGS:        w       - console text widget
+## 
+proc tkConInitMenus w {
+  global tkCon
+
+  pack [menubutton $w.con  -text Console  -un 0 -menu $w.con.m] -side left
+  pack [menubutton $w.edit -text Edit     -un 0 -menu $w.edit.m] -side left
+  #pack [menubutton $w.insp -text Inspect  -un 0 -menu $w.insp.m] -side left
+  pack [menubutton $w.pkgs -text Packages -un 0 -menu $w.pkgs.m] -side left
+  pack [menubutton $w.pref -text Prefs    -un 0 -menu $w.pref.m] -side left
+  pack [menubutton $w.help -text Help     -un 0 -menu $w.help.m] -side right
+
+  menu $w.pop -tearoff 0
+  $w.pop add cascade -label Console  -un 0 -menu $w.pop.con
+  $w.pop add cascade -label Edit     -un 0 -menu $w.pop.edit
+  #$w.pop add cascade -label Inspect  -un 0 -menu $w.pop.insp
+  $w.pop add cascade -label Packages -un 0 -menu $w.pop.pkgs
+  $w.pop add cascade -label Prefs    -un 0 -menu $w.pop.pref
+  $w.pop add cascade -label Help     -un 0 -menu $w.pop.help
+  bind [winfo toplevel $w] <Button-3> "tk_popup $w.pop %X %Y"
+
+  ## Console Menu
+  ##
+  foreach m [list [menu $w.con.m] [menu $w.pop.con]] {
+    $m add command -label "New Console" -un 0 -acc Ctrl-N -com tkConNew
+    $m add command -label "Close Console " -un 0 -acc Ctrl-w -com tkConDestroy
+    $m add separator
+    $m add cascade -label "Attach Console " -un 0 -menu $m.apps
+    $m add separator
+    $m add command -label Quit -un 0 -acc Ctrl-q -command exit
+
+    ## Attach Console Menu
+    ##
+    menu $m.apps -disabledforeground $tkCon(color,prompt) \
+       -postcommand "tkConFillAppsMenu $m.apps"
+  }
+
+  ## Edit Menu
+  ##
+  set text $tkCon(console)
+  foreach m [list [menu $w.edit.m] [menu $w.pop.edit]] {
+    $m add command -label Cut   -un 1 -acc Ctrl-x -command "tkConCut $text"
+    $m add command -label Copy  -un 1 -acc Ctrl-c -command "tkConCopy $text"
+    $m add command -label Paste -un 0 -acc Ctrl-v -command "tkConPaste $text"
+  }
+
+  ## Inspect Menu
+  ## Currently disabled
+  foreach m {} {
+    $m add command -label Procedures       -command "tkConInspect procs"
+    $m add command -label "Global Vars"    -command "tkConInspect vars"
+    $m add command -label Interpreters     -command "tkConInspect interps"
+    $m add command -label Aliases          -command "tkConInspect aliases"
+    $m add command -label Images           -command "tkConInspect images"
+    $m add command -label "All Widgets"    -command "tkConInspect widgets"
+    $m add command -label "Canvas Widgets" -command "tkConInspect canvases"
+    $m add command -label "Menu Widgets"   -command "tkConInspect menus"
+    $m add command -label "Text Widgets"   -command "tkConInspect texts"
+  }
+
+  ## Packages Menu
+  ##
+  menu $w.pkgs.m -disabledforeground $tkCon(color,prompt) \
+      -postcommand "tkConCheckPackages $w.pkgs.m"
+  menu $w.pop.pkgs -disabledforeground $tkCon(color,prompt) \
+      -postcommand "tkConCheckPackages $w.pop.pkgs"
+
+  ## Prefs Menu
+  ##
+  foreach m [list [menu $w.pref.m] [menu $w.pop.pref]] {
+    $m add checkbutton -label "Brace Highlighting"    -var tkCon(lightbrace)
+    $m add checkbutton -label "Command Highlighting"  -var tkCon(lightcmd)
+    $m add checkbutton -label "History Substitution"  -var tkCon(subhistory)
+    $m add checkbutton -label "Non-Tcl Attachments"   -var tkCon(nontcl)
+    $m add checkbutton -label "Show Multiple Matches" -var tkCon(showmultiple)
+    $m add checkbutton -label "Show Menubar"         -var tkCon(showmenu) \
+       -command "if \$tkCon(showmenu) { 
+                       pack $w -fill x -before $tkCon(scrolly)
+                 } else { pack forget $w }"
+    $m add cascade -label Scrollbar -un 0 -menu $m.scroll
+
+    ## Scrollbar Menu
+    ##
+    set m [menu $m.scroll -tearoff 0]
+    $m add radio -label Left -var tkCon(scrollypos) -value left -command {
+      pack config $tkCon(scrolly) -side left
+    }
+    $m add radio -label Right -var tkCon(scrollypos) -value right -command {
+      pack config $tkCon(scrolly) -side right
+    }
+  }
+
+  ## Help Menu
+  ##
+  foreach m [list [menu $w.help.m] [menu $w.pop.help]] {
+    $m add command -label "About " -un 0 -acc Ctrl-A -command tkConAbout
+    $m add separator
+    $m add command -label Help -un 0 -acc Ctrl-H -command tkConHelp
+  }
+
+  ## It's OK to bind to all because it's specific to each interpreter
+  bind all <Control-q> exit
+  bind all <Control-N> tkConNew
+  bind all <Control-w> tkConDestroy
+  bind all <Control-A> tkConAbout
+  bind all <Control-H> tkConHelp
+  bind all <Control-Key-1> {
+    tkConAttach {}
+    tkConPrompt \n [tkConCmdGet $tkCon(console)]
+  }
+  bind all <Control-Key-2> {
+    if [string comp {} $tkCon(name)] {
+      tkConAttach $tkCon(name)
+    } else {
+      tkConAttach Main
+    }
+    tkConPrompt \n [tkConCmdGet $tkCon(console)]
+  }
+  bind all <Control-Key-3> {
+    tkConAttach Main
+    tkConPrompt \n [tkConCmdGet $tkCon(console)]
+  }
+}
+
+## tkConCheckPackages - checks which packages are currently loaded
+## Requires two loops to make sure that packages which auto-load Tk
+## set everything properly.
+# ARGS:        w       - menu name
+##
+proc tkConCheckPackages {{w {}}} {
+  global tkCon
+  foreach pkg [lsort [lremove [package names] Tcl]] {
+    if {![info exists tkCon(load$pkg)]} { set tkCon(load$pkg) 0 }
+    if {$tkCon(load$pkg)==1} {
+      if [catch {tkConEvalSlave package require $pkg}] {
+       bgerror "$pkg cannot be loaded.  Check your pkgIndex.tcl file!!!"
+       set tkCon(load$pkg) -1
+      }
+    }
+  }
+  if [string comp {} [tkConEvalSlave info commands .]] { set tkCon(loadTk) 1 }
+  if ![winfo exists $w] return
+  $w delete 0 end
+  foreach pkg [lsort [lremove [package names] Tcl]] {
+    if {$tkCon(load$pkg)==-1} {
+      $w add command -label "$pkg Load Failed" -state disabled
+    } elseif $tkCon(load$pkg) {
+      $w add command -label "$pkg Loaded" -state disabled
+    } else {
+      $w add checkbutton -label "Load $pkg" -var tkCon(load$pkg) \
+         -command "tkConCheckPackages"
+    }
+  }
+}
+
+## tkConFillAppsMenu - fill in  in the applications sub-menu
+## with a list of all the applications that currently exist.
+##
+proc tkConFillAppsMenu {m} {
+  global tkCon
+
+  set self     [tk appname]
+  set masters  [tkConMain set tkCon(interps)]
+  set masternm [tkConSlave]
+  foreach i $masternm {
+    if [tkConSlave $i set tkCon(loadTk)] {
+      lappend slaves [tkConSlave $i tkConEvalSlave tk appname]
+    } else {
+      lappend slaves "no Tk"
+    }
+  }
+  set path [concat $tkCon(name) $tkCon(exec)]
+  set tmp [tkConInterps]
+  array set interps $tmp
+  array set tknames [concat [lrange $tmp 1 end] [list [lindex $tmp 0]]]
+
+  catch {$m delete 0 last}
+  set cmd {tkConPrompt \n [tkConCmdGet $tkCon(console)]}
+  $m add radio -label {None (use local slave) } -var tkCon(app) -value $path \
+      -command "tkConAttach {}; $cmd" -acc Ctrl-1
+  $m add separator
+  $m add command -label "Foreign Tk Interpreters" -state disabled
+  foreach i [lsort [lremove [winfo interps] \
+                       [concat $masters $slaves [array names tknames]]]] {
+    $m add radio -label $i -var tkCon(app) -value $i \
+       -command "tkConAttach [list $i] interp; $cmd"
+  }
+  $m add separator
+
+  $m add command -label "TkCon Interpreters" -state disabled
+  foreach i [lsort [array names interps]] {
+    if [string match {} $interps($i)] { set interps($i) "no Tk" }
+    if [regexp {^Slave[0-9]+} $i] {
+      if [string comp $tkCon(name) $i] {
+       $m add radio -label "$i ($interps($i))" -var tkCon(app) -value $i \
+           -command "tkConAttach [list $i] slave; $cmd"
+      } else {
+       $m add radio -label "$i ($interps($i))" -var tkCon(app) -value $i \
+           -acc Ctrl-2 \
+           -command "tkConAttach [list $i] slave; $cmd"
+      }
+    } else {
+      set name [concat Main $i]
+      if [string match Main $name] {
+       $m add radio -label "$name ($interps($i))" -var tkCon(app) \
+           -value Main -acc Ctrl-3 \
+           -command "tkConAttach [list $name] slave; $cmd"
+      } else {
+       $m add radio -label "$name ($interps($i))" -var tkCon(app) -value $i \
+            -command "tkConAttach [list $name] slave; $cmd"
+      }
+    }
+  }
+}
+
+## tkConAttach - called to attach tkCon to an interpreter
+# ARGS:        an      - application name to which tkCon sends commands
+#                This is either a slave interperter name or tk appname.
+#      type    - (slave|interp) type of interpreter we're attaching to
+#                slave means it's a TkCon interpreter
+#                interp means we'll need to 'send' to it.
+# Results:     tkConEvalAttached is recreated to evaluate in the
+#              appropriate interpreter
+##
+proc tkConAttach {an {type slave}} {
+  global tkCon
+  set app -
+  set path [concat $tkCon(name) $tkCon(exec)]
+  if [string comp {} $an] {
+    array set interps [tkConInterps]
+    if [string match {[Mm]ain} [lindex $an 0]] { set an [lrange $an 1 end] }
+    if {[string match $path $an]} {
+      set an {}
+      set app $path
+      set type slave
+    } elseif {[info exists interps($an)]} {
+      if [string match {} $an] { set an Main; set app Main }
+      set type slave
+    } elseif {[interp exists $an]} {
+      set an [concat $tkCon(name) $an]
+      set type slave
+    } elseif {[interp exists [concat $tkCon(exec) $an]]} {
+      set an [concat $path $an]
+      set type slave
+    } elseif {[lsearch [winfo interps] $an] > -1} {
+      if {$tkCon(loadTk) && [string match $an [tkConEvalSlave tk appname]]} {
+       set an {}
+       set app $path
+       set type slave
+      } elseif {[set i [lsearch [tkConMain set tkCon(interps)] $an]] > -1} {
+       set an [lindex [tkConMain set tkCon(slaves)] $i]
+       if [string match {[Mm]ain} $an] { set app Main }
+       set type slave
+      } else {
+       set type interp
+      }
+    } else {
+      error "No known interpreter \"$an\""
+    }
+  } else {
+    set app $path
+  }
+  if [string match - $app] { set app $an }
+  set tkCon(app)     $app
+  set tkCon(appname) $an
+  set tkCon(apptype) $type
+
+  ## tkConEvalAttached - evaluates the args in the attached interpreter
+  ## This procedure is dynamic.  It is rewritten by the proc tkConAttach
+  ## to ensure it evals in the right place.
+  # ARGS:      args    - the command and args to evaluate
+  ##
+  switch $type {
+    slave {
+      if [string match {} $an] {
+       interp alias {} tkConEvalAttached {} tkConEvalSlave
+      } elseif [string match Main $tkCon(app)] {
+       interp alias {} tkConEvalAttached {} tkConMain eval
+      } elseif [string match $tkCon(name) $tkCon(app)] {
+       interp alias {} tkConEvalAttached {} uplevel \#0
+      } else {
+       interp alias {} tkConEvalAttached {} tkConMain interp eval $tkCon(app)
+      }
+    }
+    interp {
+      if $tkCon(nontcl) {
+       interp alias {} tkConEvalAttached {} tkConEvalSlave
+      } else {
+       interp alias {} tkConEvalAttached {} tkConEvalSend
+      }
+    }
+    default { error "[lindex [info level 0] 0] did not specify type" }
+  }
+  return
+}
+
+## tkConLoad - sources a file into the console
+# ARGS:        fn      - (optional) filename to source in
+# Returns:     selected filename ({} if nothing was selected)
+## 
+proc tkConLoad {{fn {}}} {
+  global tkCon
+  if {[string match {} $fn] &&
+      ([catch {tkFileSelect} fn] || [string match {} $fn])} return
+  tkConEvalAttached source $fn
+}
+
+## tkConSave - saves the console buffer to a file
+## This does not eval in a slave because it's not necessary
+# ARGS:        w       - console text widget
+#      fn      - (optional) filename to save to
+## 
+proc tkConSave {{fn {}}} {
+  global tkCon
+  if {[string match {} $fn] &&
+      ([catch {tkFileSelect} fn] || [string match {} $fn])} return
+  if [catch {open $fn w} fid] {
+    error "Save Error: Unable to open '$fn' for writing\n$fid"
+  }
+  puts $fid [$tkCon(console) get 1.0 end-1c]
+  close $fid
+}
+
+## tkConResource - re'source's this script into current console
+## Meant primarily for my development of this program.  It's seems loopy
+## due to quirks in Tcl on windows.
+## 
+set tkCon(SCRIPT) [info script]
+if [string match relative [file pathtype [info script]]] {
+  set tkCon(SCRIPT) [file join [pwd] [info script]]
+}
+set tkCon(SCRIPT) [eval file join [file split $tkCon(SCRIPT)]]
+proc tkConResource {} "uplevel \#0 [list source $tkCon(SCRIPT)]; return"
+
+## tkConMainInit
+## This is only called for the main interpreter to include certain procs
+## that we don't want to include (or rather, just alias) in slave interps.
+##
+proc tkConMainInit {} {
+  global tkCon
+
+  if ![info exists tkCon(slaves)] {
+    array set tkCon [list slave 0 slaves Main name {} interps [tk appname]]
+  }
+  interp alias {} tkConMain {} tkConInterpEval Main
+  interp alias {} tkConSlave {} tkConInterpEval
+
+  ## tkConNew - create new console window
+  ## Creates a slave interpreter and sources in this script.
+  ## All other interpreters also get a command to eval function in the
+  ## new interpreter.
+  ## 
+  proc tkConNew {} {
+    global argv0 argc argv tkCon
+    set tmp [interp create Slave[incr tkCon(slave)]]
+    lappend tkCon(slaves) $tmp
+    load {} Tk $tmp
+    lappend tkCon(interps) [$tmp eval [list tk appname "[tk appname] $tmp"]]
+    $tmp eval set argc $argc \; set argv [list $argv] \; \
+       set argv0 [list $argv0]
+    $tmp eval [list set tkCon(name) $tmp]
+    $tmp eval [list source $tkCon(SCRIPT)]
+    $tmp alias tkConDestroy tkConDestroy $tmp
+    $tmp alias tkConNew            tkConNew
+    $tmp alias tkConMain    tkConInterpEval Main
+    $tmp alias tkConSlave   tkConInterpEval
+    $tmp alias tkConInterps tkConInterps
+    return $tmp
+  }
+
+  ## tkConDestroy - destroy console window
+  ## This proc should only be called by the main interpreter.  If it is
+  ## called from there, it will ask before exiting TkCon.  All others
+  ## (slaves) will just have their slave interpreter deleted, closing them.
+  ## 
+  proc tkConDestroy {{slave {}}} {
+    global tkCon
+    if [string match {} $slave] {
+      ## Main interpreter close request
+      if [tk_dialog $tkCon(base).destroyme {Quit TkCon?} \
+             {Closing the Main console will quit TkCon} \
+             warning 0 "Don't Quit" "Quit TkCon"] exit
+    } else {
+      ## Slave interpreter close request
+      set name [tkConInterpEval $slave]
+      set tkCon(interps) [lremove $tkCon(interps) [list $name]]
+      set tkCon(slaves)  [lremove $tkCon(slaves) [list $slave]]
+      interp delete $slave
+    }
+  }
+
+  ## tkConInterpEval - passes evaluation to another named interpreter
+  ## If the interpreter is named, but no args are given, it returns the
+  ## [tk appname] of that interps master (not the associated eval slave).
+  ##
+  proc tkConInterpEval {{slave {}} args} {
+    if [string match {} $slave] {
+      global tkCon
+      return $tkCon(slaves)
+    } elseif [string match {[Mm]ain} $slave] {
+      set slave {}
+    }
+    if [string match {} $args] {
+      return [interp eval $slave tk appname]
+    } else {
+      uplevel \#0 [list interp eval $slave $args]
+    }
+  }
+
+  proc tkConInterps {{ls {}} {interp {}}} {
+    if [string match {} $interp] { lappend ls {} [list [tk appname]] }
+    foreach i [interp slaves $interp] {
+      if [string comp {} $interp] { set i "$interp $i" }
+      if [catch "interp eval [list $i] tk appname" name] {
+       lappend ls $i {}
+      } else {
+       lappend ls $i $name
+      }
+      set ls [tkConInterps $ls $i]
+    }
+    return $ls
+  }
+}
+
+
+## tkConStateCheckpoint - checkpoints the current state of the system
+## This allows you to return to this state with tkConStateRevert
+# ARGS:        ary     - an array into which several elements are stored:
+#                      commands  - the currently defined commands
+#                      variables - the current global vars
+#              This is the array you would pass to tkConRevertState
+##
+proc tkConStateCheckpoint {ary} {
+  global tkCon
+  upvar $ary a
+  set a(commands)  [tkConEvalAttached info commands *]
+  set a(variables) [tkConEvalAttached info vars *]
+  return
+}
+
+## tkConStateCompare - compare two states and output difference
+# ARGS:        ary1    - an array with checkpointed state
+#      ary2    - a second array with checkpointed state
+# Outputs:
+##
+proc tkConStateCompare {ary1 ary2} {
+  upvar $ary1 a1 $ary2 a2
+  puts "Commands unique to $ary1:\n[lremove $a1(commands) $a2(commands)]"
+  puts "Commands unique to $ary2:\n[lremove $a2(commands) $a1(commands)]"
+  puts "Variables unique to $ary1:\n[lremove $a1(variables) $a2(variables)]"
+  puts "Variables unique to $ary2:\n[lremove $a2(variables) $a1(variables)]"
+}
+
+## tkConStateRevert - reverts interpreter to a previous state
+# ARGS:        ary     - an array with checkpointed state
+##
+proc tkConStateRevert {ary} {
+  upvar $ary a
+  foreach i [lremove [tkConEvalAttached info commands *] $a(commands)] {
+    catch "tkConEvalAttached rename $i {}"
+  }
+  foreach i [lremove [tkConEvalAttached info vars *] $a(variables)] {
+    catch "tkConEvalAttached unset $i"
+  }
+}
+
+
+## tkcon - command that allows control over the console
+# ARGS:        totally variable, see internal comments
+## 
+proc tkcon {args} {
+  global tkCon
+  switch -- [lindex $args 0] {
+    close {
+      ## Closes the console
+      tkConDestroy
+    }
+    clean {
+      ## 'cleans' the interpreter - reverting to original tkCon state
+      ## FIX
+      ## tkConStateRevert tkCon
+    }
+    console {
+      ## Passes the args to the text widget of the console.
+      eval $tkCon(console) [lreplace $args 0 0]
+    }
+    error {
+      ## Outputs stack caused by last error.
+      if [string match {} $tkCon(errorInfo)] {
+       set tkCon(errorInfo) {errorInfo empty}
+      }
+      catch {destroy $tkCon(base).error}
+      set w [toplevel $tkCon(base).error]
+      button $w.close -text Dismiss -command "destroy $w"
+      scrollbar $w.sy -takefocus 0 -bd 1 -command "$w.text yview"
+      text $w.text -font $tkCon(font) -yscrollcommand "$w.sy set"
+      pack $w.close -side bottom -fill x
+      pack $w.sy -side right -fill y
+      pack $w.text -fill both -expand 1
+      $w.text insert 1.0 $tkCon(errorInfo)
+      $w.text config -state disabled
+    }
+    eval {
+      ## evals contents in master interpreter
+      eval [lreplace $args 0 0]
+    }
+    font {
+      ## "tkcon font ?fontname?".  Sets the font of the console
+      if [string comp {} [lindex $args 1]] {
+       return [$tkCon(console) config -font [lindex $args 1]]
+      } else {
+       return [$tkCon(console) config -font]
+      }
+    }
+    hide {
+      ## Hides the console with 'withdraw'.
+      wm withdraw $tkCon(root)
+    }
+    iconify {
+      ## Iconifies the console with 'iconify'.
+      wm iconify $tkCon(root)
+    }
+    show - deiconify {
+      ## "tkcon show|deiconify".  Deiconifies the console.
+      wm deiconify $tkCon(root)
+    }
+    title {
+      ## "tkcon title ?title?".  Retitles the console
+      if [string comp {} [lindex $args 1]] {
+       return [wm title $tkCon(root) [lindex $args 1]]
+      } else {
+       return [wm title $tkCon(root)]
+      }
+    }
+    version {
+      return $tkCon(version)
+    }
+    default {
+      ## tries to determine if the command exists, otherwise throws error
+      set cmd [lindex $args 0]
+      set cmd tkCon[string toup [string index $cmd 0]][string range $cmd 1 end]
+      if [string match $cmd [info command $cmd]] {
+       eval $cmd [lreplace $args 0 0]
+      } else {
+       error "bad option \"[lindex $args 0]\": must be attach, close,\
+               console, destroy, eval, font, hide, iconify,\
+               load, main, new, save, show, slave, deiconify, title"
+      }
+    }
+  }
+}
+
+##
+## Some procedures to make up for lack of built-in shell commands
+##
+
+## puts
+## This allows me to capture all stdout/stderr to the console window
+# ARGS:        same as usual   
+# Outputs:     the string with a color-coded text tag
+## 
+catch {rename puts tcl_puts}
+proc puts args {
+  set len [llength $args]
+  if {$len==1} {
+    eval tkcon console insert output $args stdout {\n} stdout
+    tkcon console see output
+  } elseif {$len==2 &&
+    [regexp {(stdout|stderr|-nonewline)} [lindex $args 0] junk tmp]} {
+    if [string comp $tmp -nonewline] {
+      eval tkcon console insert output [lreplace $args 0 0] $tmp {\n} $tmp
+    } else {
+      eval tkcon console insert output [lreplace $args 0 0] stdout
+    }
+    tkcon console see output
+  } elseif {$len==3 &&
+    [regexp {(stdout|stderr)} [lreplace $args 2 2] junk tmp]} {
+    if [string comp [lreplace $args 1 2] -nonewline] {
+      eval tkcon console insert output [lrange $args 1 1] $tmp
+    } else {
+      eval tkcon console insert output [lreplace $args 0 1] $tmp
+    }
+    tkcon console see output
+  } else {
+    eval tcl_puts $args
+  }
+}
+
+## clear - clears the buffer of the console (not the history though)
+## This is executed in the parent interpreter
+## 
+proc clear {{pcnt 100}} {
+  if {![regexp {^[0-9]*$} $pcnt] || $pcnt < 1 || $pcnt > 100} {
+    error "invalid percentage to clear: must be 1-100 (100 default)"
+  } elseif {$pcnt == 100} {
+    tkcon console delete 1.0 end
+  } else {
+    set tmp [expr $pcnt/100.0*[tkcon console index end]]
+    tkcon console delete 1.0 "$tmp linestart"
+  }
+}
+
+## alias - akin to the csh alias command
+## If called with no args, then it dumps out all current aliases
+## If called with one arg, returns the alias of that arg (or {} if none)
+# ARGS:        newcmd  - (optional) command to bind alias to
+#      args    - command and args being aliased
+## 
+proc alias {{newcmd {}} args} {
+  if [string match {} $newcmd] {
+    set res {}
+    foreach a [interp aliases] {
+      lappend res [list $a: [interp alias {} $a]]
+    }
+    return [join $res \n]
+  } elseif {[string match {} $args]} {
+    interp alias {} $newcmd
+  } else {
+    eval interp alias {{}} $newcmd {{}} $args
+  }
+}
+
+## unalias - unaliases an alias'ed command
+# ARGS:        cmd     - command to unbind as an alias
+## 
+proc unalias {cmd} {
+  interp alias {} $cmd {}
+}
+
+## dump - outputs variables/procedure/widget info in source'able form.
+## Accepts glob style pattern matching for the names
+# ARGS:        type    - type of thing to dump: must be variable, procedure, widget
+# OPTS: -nocomplain    don't complain if no vars match something
+# Returns:     the values of the variables in a 'source'able form
+## 
+proc dump {type args} {
+  set whine 1
+  set code ok
+  if [string match \-n* [lindex $args 0]] {
+    set whine 0
+    set args [lreplace $args 0 0]
+  }
+  if {$whine && [string match {} $args]} {
+    error "wrong \# args: [lindex [info level 0] 0] ?-nocomplain? pattern ?pattern ...?"
+  }
+  set res {}
+  switch -glob -- $type {
+    v* {
+      # variable
+      # outputs variables value(s), whether array or simple.
+      foreach arg $args {
+       if {[string match {} [set vars [uplevel info vars [list $arg]]]]} {
+         if {[uplevel info exists $arg]} {
+           set vars $arg
+         } elseif $whine {
+           append res "\#\# No known variable $arg\n"
+           set code error
+           continue
+         } else continue
+       }
+       foreach var [lsort $vars] {
+         upvar $var v
+         if {[array exists v]} {
+           append res "array set $var \{\n"
+           foreach i [lsort [array names v]] {
+             upvar 0 v\($i\) w
+             if {[array exists w]} {
+               append res "    [list $i {NESTED VAR ERROR}]\n"
+               if $whine { set code error }
+             } else {
+               append res "    [list $i $v($i)]\n"
+             }
+           }
+           append res "\}\n"
+         } else {
+           append res [list set $var $v]\n
+         }
+       }
+      }
+    }
+    p* {
+      # procedure
+      foreach arg $args {
+       if {[string comp {} [set ps [info proc $arg]]]} {
+         foreach p [lsort $ps] {
+           set as {}
+           foreach a [info args $p] {
+             if {[info default $p $a tmp]} {
+               lappend as [list $a $tmp]
+             } else {
+               lappend as $a
+             }
+           }
+           append res [list proc $p $as [info body $p]]\n
+         }
+       } elseif $whine {
+         append res "\#\# No known proc $arg\n"
+       }
+      }
+    }
+    w* {
+      # widget
+    }
+    default {
+      return -code error "bad [lindex [info level 0] 0] option\
+       \"[lindex $args 0]\":\ must be procedure, variable, widget"
+    }
+  }
+  return -code $code [string trimr $res \n]
+}
+
+## which - tells you where a command is found
+# ARGS:        cmd     - command name
+# Returns:     where command is found (internal / external / unknown)
+## 
+proc which cmd {
+  if [string comp {} [info commands $cmd]] {
+    if {[lsearch -exact [interp aliases] $cmd] > -1} {
+      return "$cmd:\taliased to [alias $cmd]"
+    } elseif [string comp {} [info procs $cmd]] {
+      return "$cmd:\tinternal proc"
+    } else {
+      return "$cmd:\tinternal command"
+    }
+  } elseif [auto_execok $cmd] {
+    return [auto_execpath $cmd]
+  } else {
+    return "$cmd:\tunknown command"
+  }
+}
+
+## auto_execpath - tells you where an external command is found
+## Only a slight modification from core auto_execok proc
+# ARGS:        cmd     - command name
+# Returns:     where command is found or {} if not found
+## 
+if {[string match windows $tcl_platform(platform)]} {
+  proc auto_execpath name {
+    global auto_execpath tcl_platform env
+
+    if [info exists auto_execpath($name)] {
+      return $auto_execpath($name)
+    }
+    set auto_execpath($name) {}
+    if {[string comp relative [file pathtype $name]]} {
+      foreach ext {{} .exe .bat .cmd} {
+       if {[file exists ${name}${ext}] && \
+           ![file isdirectory ${name}${ext}]} {
+         set auto_execpath($name) $name
+       }
+      }
+      return $auto_execpath($name)
+    }
+    if {[info exists env(PATH)]} {
+      set path $env(PATH)
+    } else {
+      if [info exists env(Path)] { set path $env(Path) } else { return {} }
+    }
+    foreach dir [split $path {;}] {
+      if {[string match {} $dir]} { set dir . }
+      foreach ext {{} .exe .bat .cmd} {
+       set file [file join $dir ${name}${ext}]
+       if {[file exists $file] && ![file isdirectory $file]} {
+         set auto_execpath($name) $file
+         break
+       }
+      }
+    }
+    return $auto_execpath($name)
+  }
+} else {
+  proc auto_execpath name {
+    global auto_execpath env
+
+    if [info exists auto_execpath($name)] {
+      return $auto_execpath($name)
+    }
+    set auto_execpath($name) {}
+    if {[string comp relative [file pathtype $name]]} {
+      if {[file executable $name] && ![file isdirectory $name]} {
+       set auto_execpath($name) $name
+      }
+      return $auto_execpath($name)
+    }
+    foreach dir [split $env(PATH) :] {
+      if {[string match {} $dir]} { set dir . }
+      set file [file join $dir $name]
+      if {[file executable $file] && ![file isdirectory $file]} {
+       set auto_execpath($name) $file
+       break
+      }
+    }
+    return $auto_execpath($name)
+  }
+}
+
+## dir - directory list
+# ARGS:        args    - names/glob patterns of directories to list
+# OPTS:        -all    - list hidden files as well (Unix dot files)
+#      -long   - list in full format "permissions size date filename"
+#      -full   - displays / after directories and link paths for links
+# Returns:     a directory listing
+## 
+proc dir {args} {
+  array set s {
+    all 0 full 0 long 0 0 --- 1 --x 2 -w- 3 -wx 4 r-- 5 r-x 6 rw- 7 rwx
+  }
+  while {[string match \-* [lindex $args 0]]} {
+    set str [lindex $args 0]
+    set args [lreplace $args 0 0]
+    switch -glob -- $str {
+      -a* {set s(all) 1} -f* {set s(full) 1} -l* {set s(long) 1} -- break
+      default {
+       error "Passed unknown arg $str, should be one of: -all, -full, -long"
+      }
+    }
+  }
+  set sep [string trim [file join . .] .]
+  if [string match {} $args] { set args . }
+  foreach arg $args {
+    if {[file isdir $arg]} {
+      set arg [string trimr $arg $sep]$sep
+      if $s(all) {
+       lappend out [list $arg [lsort [glob -nocomplain -- $arg.* $arg*]]]
+      } else {
+       lappend out [list $arg [lsort [glob -nocomplain -- $arg*]]]
+      }
+    } else {
+      lappend out [list [file dirname $arg]$sep \
+                      [lsort [glob -nocomplain -- $arg]]]
+    }
+  }
+  if $s(long) {
+    set old [clock scan {1 year ago}]
+    set fmt "%s%9d %s %s\n"
+    foreach o $out {
+      set d [lindex $o 0]
+      append res $d:\n
+      foreach f [lindex $o 1] {
+       file lstat $f st
+       set f [file tail $f]
+       if $s(full) {
+         switch -glob $st(type) {
+           d* { append f $sep }
+           l* { append f "@ -> [file readlink $d$sep$f]" }
+           default { if [file exec $d$sep$f] { append f * } }
+         }
+       }
+       if [string match file $st(type)] {
+         set mode -
+       } else {
+         set mode [string index $st(type) 0]
+       }
+       foreach j [split [format %o [expr $st(mode)&0777]] {}] {
+         append mode $s($j)
+       }
+       if {$st(mtime)>$old} {
+         set cfmt {%b %d %H:%M}
+       } else {
+         set cfmt {%b %d  %Y}
+       }
+       append res [format $fmt $mode $st(size) \
+                       [clock format $st(mtime) -format $cfmt] $f]
+      }
+      append res \n
+    }
+  } else {
+    foreach o $out {
+      set d [lindex $o 0]
+      append res $d:\n
+      set i 0
+      foreach f [lindex $o 1] {
+       if {[string len [file tail $f]] > $i} {
+         set i [string len [file tail $f]]
+       }
+      }
+      set i [expr $i+2+$s(full)]
+      set j [expr [tkcon eval set tkCon(cols)]/$i]
+      set k 0
+      foreach f [lindex $o 1] {
+       set f [file tail $f]
+       if $s(full) {
+         switch -glob [file type $d$sep$f] {
+           d* { append f $sep }
+           l* { append f @ }
+           default { if [file exec $d$sep$f] { append f * } }
+         }
+       }
+       append res [format "%-${i}s" $f]
+       if {[incr k]%$j == 0} {set res [string trimr $res]\n}
+      }
+      append res \n\n
+    }
+  }
+  return [string trimr $res]
+}
+
+
+## tclindex - creates the tclIndex file
+# OPTS:        -ext    - extensions to auto index (defaults to *.tcl)
+# ARGS:        args    - directories to auto index (defaults to pwd)
+# Outputs:     tclIndex file to each directory
+##
+proc tclindex args {
+  set ext {*.tcl}
+  if [string match \-e* [lindex $args 0]] {
+    set ext  [lindex $args 1]
+    set args [lreplace $args 0 1]
+  }
+  if [string match {} $args] {
+    eval auto_mkindex [list [pwd]] $ext
+  } else {
+    foreach dir $args {
+      if [file isdir $dir] { eval auto_mkindex [list $dir] $ext }
+    }
+  }
+}
+
+## lremove - remove items from a list
+# OPTS:        -all    remove all instances of each item
+# ARGS:        l       a list to remove items from
+#      is      a list of items to remove
+##
+proc lremove {args} {
+  set all 0
+  if [string match \-a* [lindex $args 0]] {
+    set all 1
+    set args [lreplace $args 0 0]
+  }
+  set l [lindex $args 0]
+  eval append is [lreplace $args 0 0]
+  foreach i $is {
+    if {[set ix [lsearch -exact $l $i]] == -1} continue
+    set l [lreplace $l $ix $ix]
+    if $all {
+      while {[set ix [lsearch -exact $l $i]] != -1} {
+       set l [lreplace $l $i $i]
+      }
+    }
+  }
+  return $l
+}
+
+
+## Unknown changed to get output into tkCon window
+# unknown:
+# Invoked when a Tcl command is invoked that doesn't exist in the
+# interpreter:
+#
+#      1. See if the autoload facility can locate the command in a
+#         Tcl script file.  If so, load it and execute it.
+#      2. If the command was invoked interactively at top-level:
+#          (a) see if the command exists as an executable UNIX program.
+#              If so, "exec" the command.
+#          (b) see if the command requests csh-like history substitution
+#              in one of the common forms !!, !<number>, or ^old^new.  If
+#              so, emulate csh's history substitution.
+#          (c) see if the command is a unique abbreviation for another
+#              command.  If so, invoke the command.
+#
+# Arguments:
+# args -       A list whose elements are the words of the original
+#              command, including the command name.
+
+proc unknown args {
+  global auto_noexec auto_noload env unknown_pending tcl_interactive tkCon
+  global errorCode errorInfo
+
+  # Save the values of errorCode and errorInfo variables, since they
+  # may get modified if caught errors occur below.  The variables will
+  # be restored just before re-executing the missing command.
+
+  set savedErrorCode $errorCode
+  set savedErrorInfo $errorInfo
+  set name [lindex $args 0]
+  if ![info exists auto_noload] {
+    #
+    # Make sure we're not trying to load the same proc twice.
+    #
+    if [info exists unknown_pending($name)] {
+      unset unknown_pending($name)
+      if {[array size unknown_pending] == 0} {
+       unset unknown_pending
+      }
+      return -code error "self-referential recursion in \"unknown\" for command \"$name\"";
+    }
+    set unknown_pending($name) pending;
+    set ret [catch {auto_load $name} msg]
+    unset unknown_pending($name);
+    if {$ret != 0} {
+      return -code $ret -errorcode $errorCode \
+         "error while autoloading \"$name\": $msg"
+    }
+    if ![array size unknown_pending] {
+      unset unknown_pending
+    }
+    if $msg {
+      set errorCode $savedErrorCode
+      set errorInfo $savedErrorInfo
+      set code [catch {uplevel $args} msg]
+      if {$code ==  1} {
+       #
+       # Strip the last five lines off the error stack (they're
+       # from the "uplevel" command).
+       #
+
+       set new [split $errorInfo \n]
+       set new [join [lrange $new 0 [expr [llength $new] - 6]] \n]
+       return -code error -errorcode $errorCode \
+           -errorinfo $new $msg
+      } else {
+       return -code $code $msg
+      }
+    }
+  }
+  if {[info level] == 1 && [string match {} [info script]] \
+         && [info exists tcl_interactive] && $tcl_interactive} {
+    if ![info exists auto_noexec] {
+      if [auto_execok $name] {
+       set errorCode $savedErrorCode
+       set errorInfo $savedErrorInfo
+       return [uplevel exec $args]
+       #return [uplevel exec >&@stdout <@stdin $args]
+      }
+    }
+    set errorCode $savedErrorCode
+    set errorInfo $savedErrorInfo
+    ##
+    ## History substitution moved into tkConEvalCmd
+    ##
+    set cmds [info commands $name*]
+    if {[llength $cmds] == 1} {
+      return [uplevel [lreplace $args 0 0 $cmds]]
+    }
+    if {[llength $cmds]} {
+      if {$name == ""} {
+       return -code error "empty command name \"\""
+      } else {
+       return -code error \
+           "ambiguous command name \"$name\": [lsort $cmds]"
+      }
+    }
+  }
+  return -code error "invalid command name \"$name\""
+}
+
+
+#-------------------------------------------------------------------------
+# Elements of tkPriv that are used in this file:
+#
+# char -               Character position on the line;  kept in order
+#                      to allow moving up or down past short lines while
+#                      still remembering the desired position.
+# mouseMoved -         Non-zero means the mouse has moved a significant
+#                      amount since the button went down (so, for example,
+#                      start dragging out a selection).
+# prevPos -            Used when moving up or down lines via the keyboard.
+#                      Keeps track of the previous insert position, so
+#                      we can distinguish a series of ups and downs, all
+#                      in a row, from a new up or down.
+# selectMode -         The style of selection currently underway:
+#                      char, word, or line.
+# x, y -               Last known mouse coordinates for scanning
+#                      and auto-scanning.
+#-------------------------------------------------------------------------
+
+# tkConClipboardKeysyms --
+# This procedure is invoked to identify the keys that correspond to
+# the "copy", "cut", and "paste" functions for the clipboard.
+#
+# Arguments:
+# copy -       Name of the key (keysym name plus modifiers, if any,
+#              such as "Meta-y") used for the copy operation.
+# cut -                Name of the key used for the cut operation.
+# paste -      Name of the key used for the paste operation.
+
+proc tkConClipboardKeysyms {copy cut paste} {
+  bind Console <$copy> {tkConCopy %W}
+  bind Console <$cut>  {tkConCut %W}
+  bind Console <$paste>        {tkConPaste %W}
+}
+
+proc tkConCut w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {
+      clipboard append -displayof $w [selection get -displayof $w]
+      if [$w compare sel.first >= limit] {$w delete sel.first sel.last}
+    }
+  }
+}
+proc tkConCopy w {
+  if [string match $w [selection own -displayof $w]] {
+    clipboard clear -displayof $w
+    catch {clipboard append -displayof $w [selection get -displayof $w]}
+  }
+}
+
+proc tkConPaste w {
+  if ![catch {selection get -displayof $w -selection CLIPBOARD} tmp] {
+    if [$w compare insert < limit] {$w mark set insert end}
+    $w insert insert $tmp
+    $w see insert
+    if [string match *\n* $tmp] {tkConEval $w}
+  }
+}
+
+## Get all Text bindings into Console except Unix cut/copy/paste
+## and newline insertion
+foreach ev [lremove [bind Text] {<Control-Key-y> <Control-Key-w> \
+                                    <Meta-Key-w> <Control-Key-o>}] {
+  bind Console $ev [bind Text $ev]
+}
+unset ev
+
+## Redefine for Console what we need
+##
+tkConClipboardKeysyms F16 F20 F18
+tkConClipboardKeysyms Control-c Control-x Control-v
+
+bind Console <Insert> {catch {tkConInsert %W [selection get -displayof %W]}}
+
+bind Console <Up> {
+  if [%W compare {insert linestart} != {limit linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W -1]
+  } else {
+    if {$tkCon(event) == [tkConEvalSlave history nextid]} {
+      set tkCon(cmdbuf) [tkConCmdGet %W]
+    }
+    if [catch {tkConEvalSlave \
+                  history event [incr tkCon(event) -1]} tkCon(tmp)] {
+      incr tkCon(event)
+    } else {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      %W see end
+    }
+  }
+}
+bind Console <Down> {
+  if [%W compare {insert linestart} != {end-1c linestart}] {
+    tkTextSetCursor %W [tkTextUpDownLine %W 1]
+  } else {
+    if {$tkCon(event) < [tkConEvalSlave history nextid]} {
+      %W delete limit end
+      if {[incr tkCon(event)] == [tkConEvalSlave history nextid]} {
+       %W insert limit $tkCon(cmdbuf)
+      } else {
+       %W insert limit [tkConEvalSlave history event $tkCon(event)]
+      }
+      %W see end
+    }
+  }
+}
+bind Console <Tab> {
+  if [%W compare insert > limit] {tkConExpand %W path}
+}
+bind Console <Control-P> {
+  if [%W compare insert > limit] {tkConExpand %W proc}
+}
+bind Console <Control-V> {
+  if [%W compare insert > limit] {tkConExpand %W var}
+}
+bind Console <Control-i> {
+  if [%W compare insert >= limit] {
+    tkConInsert %W \t
+  }
+}
+bind Console <Return> {
+  tkConEval %W
+}
+bind Console <KP_Enter> [bind Console <Return>]
+bind Console <Delete> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+         && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif [%W compare insert >= limit] {
+    %W delete insert
+    %W see insert
+  }
+}
+bind Console <BackSpace> {
+  if {[string comp {} [%W tag nextrange sel 1.0 end]] \
+         && [%W compare sel.first >= limit]} {
+    %W delete sel.first sel.last
+  } elseif {[%W compare insert != 1.0] && [%W compare insert > limit]} {
+    %W delete insert-1c
+    %W see insert
+  }
+}
+bind Console <Control-h> [bind Console <BackSpace>]
+
+bind Console <KeyPress> {
+  tkConInsert %W %A
+}
+
+bind Console <Control-a> {
+  if [%W compare {limit linestart} == {insert linestart}] {
+    tkTextSetCursor %W limit
+  } else {
+    tkTextSetCursor %W {insert linestart}
+  }
+}
+bind Console <Control-d> {
+  if [%W compare insert < limit] break
+  %W delete insert
+}
+bind Console <Control-k> {
+  if [%W compare insert < limit] break
+  if [%W compare insert == {insert lineend}] {
+    %W delete insert
+  } else {
+    %W delete insert {insert lineend}
+  }
+}
+bind Console <Control-l> {
+  ## Clear console buffer, without losing current command line input
+  set tkCon(tmp) [tkConCmdGet %W]
+  clear
+  tkConPrompt {} $tkCon(tmp)
+}
+bind Console <Control-n> {
+  ## Goto next command in history
+  if {$tkCon(event) < [tkConEvalSlave history nextid]} {
+    %W delete limit end
+    if {[incr tkCon(event)] == [tkConEvalSlave history nextid]} {
+      %W insert limit $tkCon(cmdbuf)
+    } else {
+      %W insert limit [tkConEvalSlave history event $tkCon(event)]
+    }
+    %W see end
+  }
+}
+bind Console <Control-p> {
+  ## Goto previous command in history
+  if {$tkCon(event) == [tkConEvalSlave history nextid]} {
+    set tkCon(cmdbuf) [tkConCmdGet %W]
+  }
+  if [catch {tkConEvalSlave history event [incr tkCon(event) -1]} tkCon(tmp)] {
+    incr tkCon(event)
+  } else {
+    %W delete limit end
+    %W insert limit $tkCon(tmp)
+    %W see end
+  }
+}
+bind Console <Control-r> {
+  ## Search history reverse
+  if {$tkCon(svnt) == [tkConEvalSlave history nextid]} {
+    set tkCon(cmdbuf) [tkConCmdGet %W]
+  }
+  set tkCon(tmp1) [string len $tkCon(cmdbuf)]
+  incr tkCon(tmp1) -1
+  while 1 {
+    if {[catch {tkConEvalSlave \
+       history event [incr tkCon(svnt) -1]} tkCon(tmp)]} {
+      incr tkCon(svnt)
+      break
+    } elseif {![string comp $tkCon(cmdbuf) \
+       [string range $tkCon(tmp) 0 $tkCon(tmp1)]]} {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      break
+    }
+  }
+  %W see end
+}
+bind Console <Control-s> {
+  ## Search history forward
+  set tkCon(tmp1) [string len $tkCon(cmdbuf)]
+  incr tkCon(tmp1) -1
+  while {$tkCon(svnt) < [tkConEvalSlave history nextid]} {
+    if {[incr tkCon(svnt)] == [tkConEvalSlave history nextid]} {
+      %W delete limit end
+      %W insert limit $tkCon(cmdbuf)
+      break
+    } elseif {![catch {tkConEvalSlave history event $tkCon(svnt)} tkCon(tmp)] \
+       && ![string comp $tkCon(cmdbuf) \
+       [string range $tkCon(tmp) 0 $tkCon(tmp1)]]} {
+      %W delete limit end
+      %W insert limit $tkCon(tmp)
+      break
+    }
+  }
+  %W see end
+}
+bind Console <Control-t> {
+  ## Transpose current and previous chars
+  if [%W compare insert > limit] {
+    tkTextTranspose %W
+  }
+}
+bind Console <Control-u> {
+  ## Clear command line (Unix shell staple)
+  %W delete limit end
+}
+bind Console <Control-z> {
+  ## Save command buffer
+  set tkCon(tmp) $tkCon(cmdsave)
+  set tkCon(cmdsave) [tkConCmdGet %W]
+  if {[string match {} $tkCon(cmdsave)]} {
+    set tkCon(cmdsave) $tkCon(tmp)
+  } else {
+    %W delete limit end-1c
+  }
+  tkConInsert %W $tkCon(tmp)
+  %W see end
+}
+catch {bind Console <Key-Page_Up>   { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Prior>     { tkTextScrollPages %W -1 }}
+catch {bind Console <Key-Page_Down> { tkTextScrollPages %W 1 }}
+catch {bind Console <Key-Next>      { tkTextScrollPages %W 1 }}
+bind Console <Meta-d> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <Meta-BackSpace> {
+  if [%W compare {insert -1c wordstart} >= limit] {
+    %W delete {insert -1c wordstart} insert
+  }
+}
+bind Console <Meta-Delete> {
+  if [%W compare insert >= limit] {
+    %W delete insert {insert wordend}
+  }
+}
+bind Console <ButtonRelease-2> {
+  if {(!$tkPriv(mouseMoved) || $tk_strictMotif) \
+         && ![catch {selection get -displayof %W} tkCon(tmp)]} {
+    if [%W compare @%x,%y < limit] {
+      %W insert end $tkCon(tmp)
+    } else {
+      %W insert @%x,%y $tkCon(tmp)
+    }
+    if [string match *\n* $tkCon(tmp)] {tkConEval %W}
+  }
+}
+
+##
+## End weird bindings
+##
+
+##
+## Bindings for doing special things based on certain keys
+##
+bind PostCon <Key-parenright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \( \) limit
+  }
+}
+bind PostCon <Key-bracketright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \[ \] limit
+  }
+}
+bind PostCon <Key-braceright> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchPair %W \{ \} limit
+  }
+}
+bind PostCon <Key-quotedbl> {
+  if {$tkCon(lightbrace) && $tkCon(blinktime)>99 &&
+      [string comp \\ [%W get insert-2c]]} {
+    tkConMatchQuote %W limit
+  }
+}
+
+bind PostCon <KeyPress> {
+  if {$tkCon(lightcmd) && [string comp {} %A]} { tkConTagProc %W }
+}
+
+## tkConTagProc - tags a procedure in the console if it's recognized
+## This procedure is not perfect.  However, making it perfect wastes
+## too much CPU time...  Also it should check the existence of a command
+## in whatever is the connected slave, not the master interpreter.
+##
+proc tkConTagProc w {
+  set i [$w index "insert-1c wordstart"]
+  set j [$w index "insert-1c wordend"]
+  if {[string comp {} \
+          [tkConEvalAttached info command [list [$w get $i $j]]]]} {
+    $w tag add proc $i $j
+  } else {
+    $w tag remove proc $i $j
+  }
+}
+
+## tkConMatchPair - blinks a matching pair of characters
+## c2 is assumed to be at the text index 'insert'.
+## This proc is really loopy and took me an hour to figure out given
+## all possible combinations with escaping except for escaped \'s.
+## It doesn't take into account possible commenting... Oh well.  If
+## anyone has something better, I'd like to see/use it.  This is really
+## only efficient for small contexts.
+# ARGS:        w       - console text widget
+#      c1      - first char of pair
+#      c2      - second char of pair
+# Calls:       tkConBlink
+## 
+proc tkConMatchPair {w c1 c2 {lim 1.0}} {
+  if [string comp {} [set ix [$w search -back $c1 insert $lim]]] {
+    while {[string match {\\} [$w get $ix-1c]] &&
+          [string comp {} [set ix [$w search -back $c1 $ix-1c $lim]]]} {}
+    set i1 insert-1c
+    while {[string comp {} $ix]} {
+      set i0 $ix
+      set j 0
+      while {[string comp {} [set i0 [$w search $c2 $i0 $i1]]]} {
+       append i0 +1c
+       if {[string match {\\} [$w get $i0-2c]]} continue
+       incr j
+      }
+      if {!$j} break
+      set i1 $ix
+      while {$j &&
+            [string comp {} [set ix [$w search -back $c1 $ix $lim]]]} {
+       if {[string match {\\} [$w get $ix-1c]]} continue
+       incr j -1
+      }
+    }
+    if [string match {} $ix] { set ix [$w index $lim] }
+  } else { set ix [$w index $lim] }
+  tkConBlink $w $ix [$w index insert]
+}
+
+## tkConMatchQuote - blinks between matching quotes.
+## Blinks just the quote if it's unmatched, otherwise blinks quoted string
+## The quote to match is assumed to be at the text index 'insert'.
+# ARGS:        w       - console text widget
+# Calls:       tkConBlink
+## 
+proc tkConMatchQuote {w {lim 1.0}} {
+  set i insert-1c
+  set j 0
+  while {[string comp {} [set i [$w search -back \" $i $lim]]]} {
+    if {[string match {\\} [$w get $i-1c]]} continue
+    if {!$j} {set i0 $i}
+    incr j
+  }
+  if [expr $j%2] {
+    tkConBlink $w $i0 [$w index insert]
+  } else {
+    tkConBlink $w [$w index insert-1c] [$w index insert]
+  }
+}
+
+## tkConBlink - blinks between 2 indices for a specified duration.
+# ARGS:        w       - console text widget
+#      i1      - start index to blink region
+#      i2      - end index of blink region
+#      dur     - duration in usecs to blink for
+# Outputs:     blinks selected characters in $w
+## 
+proc tkConBlink {w i1 i2} {
+  global tkCon
+  $w tag add blink $i1 $i2
+  after $tkCon(blinktime) $w tag remove blink $i1 $i2
+  return
+}
+
+
+## tkConInsert
+## Insert a string into a text console at the point of the insertion cursor.
+## If there is a selection in the text, and it covers the point of the
+## insertion cursor, then delete the selection before inserting.
+# ARGS:        w       - text window in which to insert the string
+#      s       - string to insert (usually just a single char)
+# Outputs:     $s to text widget
+## 
+proc tkConInsert {w s} {
+  if {[string match {} $s] || [string match disabled [$w cget -state]]} {
+    return
+  }
+  if [$w comp insert < limit] {
+    $w mark set insert end
+  }
+  catch {
+    if {[$w comp sel.first <= insert] && [$w comp sel.last >= insert]} {
+      $w delete sel.first sel.last
+    }
+  }
+  $w insert insert $s
+  $w see insert
+}
+
+## tkConExpand - 
+# ARGS:        w       - text widget in which to expand str
+#      type    - type of expansion (path / proc / variable)
+# Calls:       tkConExpand(Pathname|Procname|Variable)
+# Outputs:     The string to match is expanded to the longest possible match.
+#              If tkCon(showmultiple) is non-zero and the user longest match
+#              equaled the string to expand, then all possible matches are
+#              output to stdout.  Triggers bell if no matches are found.
+# Returns:     number of matches found
+## 
+proc tkConExpand {w type} {
+  set exp "\[^\\]\[ \t\n\r\[\{\"\$]"
+  set tmp [$w search -back -regexp $exp insert limit]
+  if [string compare {} $tmp] {append tmp +2c} else {set tmp limit}
+  if [$w compare $tmp >= insert] return
+  set str [$w get $tmp insert]
+  switch -glob $type {
+    pa* { set res [tkConExpandPathname $str] }
+    pr* { set res [tkConExpandProcname $str] }
+    v*  { set res [tkConExpandVariable $str] }
+    default {set res {}}
+  }
+  set len [llength $res]
+  if $len {
+    $w delete $tmp insert
+    $w insert $tmp [lindex $res 0]
+    if {$len > 1} {
+      global tkCon
+      if {$tkCon(showmultiple) && [string match [lindex $res 0] $str]} {
+       puts stdout [lreplace $res 0 0]
+      }
+    }
+  } else bell
+  return [incr len -1]
+}
+
+## tkConExpandPathname - expand a file pathname based on $str
+## This is based on UNIX file name conventions
+# ARGS:        str     - partial file pathname to expand
+# Calls:       tkConExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+proc tkConExpandPathname str {
+  set pwd [tkConEvalAttached pwd]
+  if [catch {tkConEvalAttached cd [file dir $str]} err] {
+    return -code error $err
+  }
+  if [catch {lsort [tkConEvalAttached glob [file tail $str]*]} m] {
+    set match {}
+  } else {
+    if {[llength $m] > 1} {
+      set tmp [tkConExpandBestMatch $m [file tail $str]]
+      if [string match ?*/* $str] {
+       set tmp [file dir $str]/$tmp
+      } elseif [string match /* $str] {
+       set tmp /$tmp
+      }
+      regsub -all { } $tmp {\\ } tmp
+      set match [linsert $m 0 $tmp]
+    } else {
+      ## This may look goofy, but it handles spaces in path names
+      eval append match $m
+      if [file isdir $match] {append match /}
+      if [string match ?*/* $str] {
+       set match [file dir $str]/$match
+      } elseif [string match /* $str] {
+       set match /$match
+      }
+      regsub -all { } $match {\\ } match
+      ## Why is this one needed and the ones below aren't!!
+      set match [list $match]
+    }
+  }
+  tkConEvalAttached cd $pwd
+  return $match
+}
+
+## tkConExpandProcname - expand a tcl proc name based on $str
+# ARGS:        str     - partial proc name to expand
+# Calls:       tkConExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+proc tkConExpandProcname str {
+  set match [tkConEvalAttached info commands $str*]
+  if {[llength $match] > 1} {
+    regsub -all { } [tkConExpandBestMatch $match $str] {\\ } str
+    set match [linsert $match 0 $str]
+  } else {
+    regsub -all { } $match {\\ } match
+  }
+  return $match
+}
+
+## tkConExpandVariable - expand a tcl variable name based on $str
+# ARGS:        str     - partial tcl var name to expand
+# Calls:       tkConExpandBestMatch
+# Returns:     list containing longest unique match followed by all the
+#              possible further matches
+## 
+proc tkConExpandVariable str {
+  if [regexp {([^\(]*)\((.*)} $str junk ary str] {
+    ## Looks like they're trying to expand an array.
+    set match [tkConEvalAttached array names $ary $str*]
+    if {[llength $match] > 1} {
+      set vars $ary\([tkConExpandBestMatch $match $str]
+      foreach var $match {lappend vars $ary\($var\)}
+      return $vars
+    } else {set match $ary\($match\)}
+    ## Space transformation avoided for array names.
+  } else {
+    set match [tkConEvalAttached info vars $str*]
+    if {[llength $match] > 1} {
+      regsub -all { } [tkConExpandBestMatch $match $str] {\\ } str
+      set match [linsert $match 0 $str]
+    } else {
+      regsub -all { } $match {\\ } match
+    }
+  }
+  return $match
+}
+
+## tkConExpandBestMatch2 - finds the best unique match in a list of names
+## Improves upon the speed of the below proc only when $l is small
+## or $e is {}.
+# ARGS:        l       - list to find best unique match in
+# Returns:     longest unique match in the list
+## 
+proc tkConExpandBestMatch2 {l {e {}}} {
+  set ec [lindex $l 0]
+  if {[llength $l]>1} {
+    set ei [string length $ec]; incr ei -1
+    foreach l $l {
+      while {$ei>0 && [string first $ec $l]} {
+       set ec [string range $ec 0 [incr ei -1]]
+      }
+    }
+  }
+  return $ec
+}
+
+## tkConExpandBestMatch - finds the best unique match in a list of names
+## The extra $e in this argument allows us to limit the innermost loop a
+## little further.  This improves speed as $l becomes large or $e becomes long.
+# ARGS:        l       - list to find best unique match in
+#      e       - currently best known unique match
+# Returns:     longest unique match in the list
+## 
+proc tkConExpandBestMatch {l {e {}}} {
+  set ec [lindex $l 0]
+  if {[llength $l]>1} {
+    set e  [string length $e]; incr e -1
+    set ei [string length $ec]; incr ei -1
+    foreach l $l {
+      while {$ei>=$e && [string first $ec $l]} {
+       set ec [string range $ec 0 [incr ei -1]]
+      }
+    }
+  }
+  return $ec
+}
+
+
+## Initialize only if we haven't yet
+##
+if [catch {winfo exists $tkCon(root)}] tkConInit