Initial revision
authorRyan C. Gordon <icculus@icculus.org>
Wed, 18 Apr 2001 23:47:38 +0000
changeset 1 d7cb562e4e24
parent 0 7b99cc550f4e
child 2 8b3701d5db49
Initial revision
FILEID.DIZ
LICENSE.TXT
Makefile
README
docs/LICENSE.TXT
docs/changelog.txt
docs/thanks.txt
docs/todo.txt
programs/april.toby
programs/april_modified.toby
programs/boolTest.toby
programs/boxes.toby
programs/colorBlocks.toby
programs/connie.toby
programs/eyes.toby
programs/flowerVines.toby
programs/globTest.toby
programs/gradient.toby
programs/gradient2.toby
programs/greg1.toby
programs/nesting.toby
programs/nicki.toby
programs/psychedelic.toby
programs/psychedelic2.toby
programs/psychedelic3.toby
programs/psychedelic4.toby
programs/rotateTurtle.toby
programs/sabrina.toby
programs/sabrina2.toby
programs/swirls.toby
programs/testArray.toby
programs/testMultiTurtling.toby
programs/testRecursive.toby
programs/testReturn.toby
programs/testStep.toby
programs/testString.toby
programs/testTurtleSpace.toby
programs/testWhile.toby
programs/theLight.toby
programs/triangleWeb.toby
programs/triangleWheel.toby
programs/webBox.toby
programs/wierdBox.toby
programs/wireOrb.toby
splash.jpg
src/exceptions/ExecException.h
src/exceptions/FlowException.h
src/exceptions/HaltException.h
src/exceptions/IOException.h
src/exceptions/ParseException.h
src/exceptions/ReturnException.h
src/exceptions/TobyException.h
src/i18n/example.tobylang
src/i18n/french.tobylang
src/i18n/tobykeywords.tobylang
src/platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.cpp
src/platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.h
src/platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.cpp
src/platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.h
src/platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.cpp
src/platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.h
src/platform/threads/nullthreads/NullMutex.cpp
src/platform/threads/nullthreads/NullMutex.h
src/platform/threads/nullthreads/NullThread.cpp
src/platform/threads/nullthreads/NullThread.h
src/platform/threads/pthreads/PthreadsMutex.cpp
src/platform/threads/pthreads/PthreadsMutex.h
src/platform/threads/pthreads/PthreadsThread.cpp
src/platform/threads/pthreads/PthreadsThread.h
src/platform/threads/sdlthreads/SDLMutex.cpp
src/platform/threads/sdlthreads/SDLMutex.h
src/platform/threads/sdlthreads/SDLThread.cpp
src/platform/threads/sdlthreads/SDLThread.h
src/standalone.cpp
src/turtlespace/Turtle.cpp
src/turtlespace/Turtle.h
src/turtlespace/TurtleSpace.cpp
src/turtlespace/TurtleSpace.h
src/turtlespace/TurtleSpaceRenderer.h
src/util/TobyCollection.cpp
src/util/TobyCollection.h
src/util/TobyGeometry.h
src/util/TobyLanguage.cpp
src/util/TobyLanguage.h
src/util/TobyMutex.h
src/util/TobyObject.h
src/util/TobyStack.cpp
src/util/TobyStack.h
src/util/TobyString.cpp
src/util/TobyString.h
src/util/TobyThread.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FILEID.DIZ	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,10 @@
+
+Toby.
+
+A learning environment inspired by LOGO (TurtleGraphics).
+
+Please read the included README for all the dirty details.
+
+--ryan. (icculus@linuxgames.com)
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.TXT	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+	  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+	 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+    USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,390 @@
+#-----------------------------------------------------------------------------#
+# TOBY -- An abstract interpreter engine and system for learning.
+# Copyright (C) 1999  Ryan C. Gordon.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#-----------------------------------------------------------------------------#
+
+
+#-----------------------------------------------------------------------------#
+# Makefile for building Toby on Unix-like systems. Follow the instructions
+#  for editing this file, then run "make" on the command line.
+#
+#  Written by Ryan C. Gordon (icculus@linuxgames.com)
+#-----------------------------------------------------------------------------#
+
+
+#-----------------------------------------------------------------------------#
+# Set to your liking.
+#-----------------------------------------------------------------------------#
+CC = gcc
+LINKER = gcc
+
+
+#-----------------------------------------------------------------------------#
+# If this makefile fails to detect Cygwin correctly, or you want to force
+#  the build process's behaviour, set it to "true" or "false" (w/o quotes).
+#-----------------------------------------------------------------------------#
+#cygwin := true
+#cygwin := false
+cygwin := autodetect
+
+#-----------------------------------------------------------------------------#
+# Set this to true if you want to create a debug build.
+#-----------------------------------------------------------------------------#
+debugging := false
+#debugging := true
+
+#-----------------------------------------------------------------------------#
+# Set this to what your platform has.
+#   Current option(s): "pthreads", "sdl", "null".
+#-----------------------------------------------------------------------------#
+#platform_threads := pthreads
+platform_threads := sdl
+#platform_threads := null
+
+#-----------------------------------------------------------------------------#
+# Set this to what your platform has.
+#   Current option(s): "sdl", "gtk".
+#-----------------------------------------------------------------------------#
+#platform_video := sdl
+platform_video := gtk
+
+
+#-----------------------------------------------------------------------------#
+# To use a different platform's ASM or portable C, change this.
+#-----------------------------------------------------------------------------#
+#USE_ASM := -DUSE_I386_ASM
+USE_ASM := -DUSE_PORTABLE_C
+
+
+
+#-----------------------------------------------------------------------------#
+# You only need to set SDL_INC_DIR and SDL_LIB_DIR if you are using CygWin
+#  as a compiler and SDL for video.
+#
+#  SDL_INC_DIR is where SDL.h and associated headers can be found, and
+#  SDL_LIB_DIR is where SDL.lib and SDL.dll are located. These may be set as
+#  environment variables, if you'd prefer to not hack the Makefile.
+#
+# Same thing applies for GTK+, if you are using that. Good luck.
+#
+# examples:
+#   SDL_INC_DIR := C:/2/SDL-1.1.8/include
+#   SDL_LIB_DIR := C:/2/SDL-1.1.8/lib
+#-----------------------------------------------------------------------------#
+ifeq ($(strip $(SDL_INC_DIR)),)
+  SDL_INC_DIR := please_set_me_cygwin_users
+endif
+
+ifeq ($(strip $(SDL_LIB_DIR)),)
+  SDL_LIB_DIR := please_set_me_cygwin_users
+endif
+
+ifeq ($(strip $(GTK_INC_DIR)),)
+  GTK_INC_DIR := please_set_me_cygwin_users
+endif
+
+ifeq ($(strip $(GTK_LIB_DIR)),)
+  GTK_LIB_DIR := please_set_me_cygwin_users
+endif
+
+
+
+
+
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+# Everything below this line is probably okay.
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+#-----------------------------------------------------------------------------#
+
+
+#-----------------------------------------------------------------------------#
+# CygWin autodetect.
+#-----------------------------------------------------------------------------#
+
+ifeq ($(strip $(cygwin)),autodetect)
+  ifneq ($(strip $(shell gcc -v 2>&1 |grep "cygwin")),)
+    cygwin := true
+  else
+    cygwin := false
+  endif
+endif
+
+
+#-----------------------------------------------------------------------------#
+# Set up video flags...
+#-----------------------------------------------------------------------------#
+using_sdl_at_all := false
+ifeq ($(strip $(platform_video)),sdl)
+  using_sdl_at_all := true
+endif
+ifeq ($(strip $(platform_threads)),sdl)
+  using_sdl_at_all := true
+endif
+
+ifeq ($(strip $(using_sdl_at_all)),true)
+  ifeq ($(strip $(cygwin)),true)
+    ifeq ($(strip $(SDL_INC_DIR)),please_set_me_cygwin_users)
+      $(error Cygwin users need to set the SDL_INC_DIR envr var.)
+    else
+      CFLAGS += -I$(SDL_INC_DIR)
+    endif
+
+    ifeq ($(strip $(SDL_LIB_DIR)),please_set_me_cygwin_users)
+      $(error Cygwin users need to set the SDL_LIB_DIR envr var.)
+    else
+      LDFLAGS += -L$(SDL_LIB_DIR) -lSDL
+    endif
+  else
+    CFLAGS += $(shell sdl-config --cflags)
+    LDFLAGS += $(shell sdl-config --libs)
+  endif
+endif
+
+ifeq ($(strip $(platform_video)),gtk)
+  ifeq ($(strip $(cygwin)),true)
+    ifeq ($(strip $(GTK_INC_DIR)),please_set_me_cygwin_users)
+      $(error Cygwin users need to set the GTK_INC_DIR envr var.)
+    else
+      CFLAGS += -I$(GTK_INC_DIR)
+    endif
+
+    ifeq ($(strip $(GTK_LIB_DIR)),please_set_me_cygwin_users)
+      $(error Cygwin users need to set the GTK_LIB_DIR envr var.)
+    else
+      LDFLAGS += -L$(GTK_LIB_DIR) -lgtk -lgdk -lglib
+    endif
+  else
+    CFLAGS += $(shell gtk-config --cflags)
+    LDFLAGS += $(shell gtk-config --libs)
+  endif
+endif
+
+#-----------------------------------------------------------------------------#
+# Platform-specific binary stuff.
+#-----------------------------------------------------------------------------#
+
+ifeq ($(strip $(cygwin)),true)
+  ASM = nasmw
+  EXE_EXT = .exe
+  ASMOBJFMT = win32
+  ASMDEFS = -dC_IDENTIFIERS_UNDERSCORED
+  CFLAGS += -DC_IDENTIFIERS_UNDERSCORED
+else
+  ASM = nasm
+  EXE_EXT =
+  ASMOBJFMT = elf
+endif
+
+
+#-----------------------------------------------------------------------------#
+# General compiler, assembler, and linker flags.
+#-----------------------------------------------------------------------------#
+
+BINDIR := bin
+SRCDIR := src
+
+CFLAGS += $(USE_ASM) -I$(SRCDIR) -D_REENTRANT -fsigned-char -DPLATFORM_UNIX
+CFLAGS += -Wall -Werror -fexceptions -frtti
+
+ifeq ($(strip $(debugging)),true)
+  CFLAGS += -DDEBUG -g -fno-omit-frame-pointer
+  LDFLAGS += -g -fno-omit-frame-pointer
+else
+  CFLAGS += -D_NDEBUG -O2 -fomit-frame-pointer
+  LDFLAGS += -O2 -fomit-frame-pointer
+endif
+
+ifneq ($(strip $(USE_ASM)),-DUSE_PORTABLE_C)
+  CFLAGS += -O2 -fasm
+endif
+
+ASMFLAGS := -f $(ASMOBJFMT) $(ASMDEFS)
+
+
+#-----------------------------------------------------------------------------#
+# Source and target names.
+#-----------------------------------------------------------------------------#
+
+MAINEXE := $(BINDIR)/toby$(strip $(EXE_EXT))
+STANDALONEEXE := $(BINDIR)/standalone$(strip $(EXE_EXT))
+
+EXES := $(STANDALONEEXE) #$(MAINEXE)
+
+UTILSRCS := util/TobyCollection.cpp util/TobyStack.cpp util/TobyString.cpp \
+            util/TobyLanguage.cpp
+TURTLESPACESRCS := turtlespace/Turtle.cpp turtlespace/TurtleSpace.cpp
+
+valid_threads_target := false
+ifeq ($(strip $(platform_threads)),pthreads)
+  THREADSRCS := platform/threads/pthreads/PthreadsThread.cpp \
+                platform/threads/pthreads/PthreadsMutex.cpp
+  THREADSDIR := pthreads
+  valid_threads_target := true
+endif
+
+ifeq ($(strip $(platform_threads)),sdl)
+  THREADSRCS := platform/threads/sdlthreads/SDLThread.cpp \
+                platform/threads/sdlthreads/SDLMutex.cpp
+  THREADSDIR := sdlthreads
+  valid_threads_target := true
+endif
+
+ifeq ($(strip $(platform_threads)),null)
+  THREADSRCS := platform/threads/nullthreads/NullThread.cpp \
+                platform/threads/nullthreads/NullMutex.cpp
+  THREADSDIR := nullthreads
+  valid_threads_target := true
+endif
+
+ifneq ($(strip $(valid_threads_target)),true)
+  $(error platform_threads flag in Makefile is not valid.)
+endif
+
+
+valid_video_target := false
+ifeq ($(strip $(platform_video)),sdl)
+  VIDEOSRCS := platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.cpp \
+               platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.cpp
+  VIDEODIR  := sdlrenderer
+  valid_video_target := true
+endif
+
+ifeq ($(strip $(platform_video)),gtk)
+  VIDEOSRCS := platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.cpp
+  VIDEODIR  := gtkrenderer
+  valid_video_target := true
+endif
+
+ifneq ($(strip $(valid_video_target)),true)
+  $(error platform_video flag in Makefile is not valid.)
+endif
+
+
+
+COMMONSRCS := $(UTILSRCS) $(TURTLESPACESRCS) $(THREADSRCS) $(VIDEOSRCS)
+
+# Rule for getting list of objects from source
+COMMONOBJS1 := $(COMMONSRCS:.c=.o)
+COMMONOBJS2 := $(COMMONOBJS1:.cpp=.o)
+COMMONOBJS3 := $(COMMONOBJS2:.asm=.o)
+
+COMMONOBJS := $(foreach f,$(COMMONOBJS3),$(BINDIR)/$(f))
+COMMONSRCS := $(foreach f,$(COMMONOBJS3),$(SRCDIR)/$(f))
+
+
+CLEANUP = $(wildcard *.exe) $(wildcard *.obj) \
+          $(wildcard $(BINDIR)/*.exe) $(wildcard $(BINDIR)/*.obj) \
+          $(wildcard *~) $(wildcard *.err) \
+          $(wildcard .\#*) core
+
+
+#-----------------------------------------------------------------------------#
+# Rules.
+#-----------------------------------------------------------------------------#
+
+# Rules for turning source files into .o files
+$(BINDIR)/%.o: $(SRCDIR)/%.cpp
+	$(CC) -c -o $@ $< $(CFLAGS)
+
+$(BINDIR)/%.o: $(SRCDIR)/%.c
+	$(CC) -c -o $@ $< $(CFLAGS)
+
+$(BINDIR)/%.o: $(SRCDIR)/%.asm
+	$(ASM) $(ASMFLAGS) -o $@ $<
+
+.PHONY: all clean listobjs
+
+all: $(BINDIR) $(EXES)
+
+$(MAINEXE) : $(BINDIR) $(COMMONOBJS) $(BINDIR)/toby.o
+	$(LINKER) -o $(MAINEXE) $(LDFLAGS) $(COMMONOBJS) $(BINDIR)/toby.o
+
+$(STANDALONEEXE) : $(BINDIR) $(COMMONOBJS) $(BINDIR)/standalone.o
+	$(LINKER) -o $(STANDALONEEXE) $(LDFLAGS) $(COMMONOBJS) $(BINDIR)/standalone.o
+
+$(BINDIR):
+	@sh -c 'if [ ! -d $(BINDIR) ]; then mkdir $(BINDIR); fi'
+	@sh -c 'if [ ! -d $(BINDIR)/turtlespace ]; then mkdir $(BINDIR)/turtlespace; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/util ]; then mkdir $(BINDIR)/util; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform ]; then mkdir $(BINDIR)/platform; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform/renderers ]; then mkdir $(BINDIR)/platform/renderers; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform/renderers/fbrenderer ]; then mkdir $(BINDIR)/platform/renderers/fbrenderer; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform/renderers/$(VIDEODIR) ]; then mkdir $(BINDIR)/platform/renderers/$(VIDEODIR); fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform/threads ]; then mkdir $(BINDIR)/platform/threads; fi'
+	@sh -c 'if [ ! -d $(BINDIR)/platform/threads/$(THREADSDIR) ]; then mkdir $(BINDIR)/platform/threads/$(THREADSDIR); fi'
+
+clean:
+	rm -f $(CLEANUP)
+	rm -rf $(BINDIR)
+
+listobjs:
+	@echo OBJECTS:
+	@echo $(COMMONOBJS)
+	@echo
+	@echo EXECUTABLES:
+	@echo $(EXES)
+
+showcfg:
+	@echo "Using CygWin   : $(cygwin)"
+	@echo "Debugging      : $(debugging)"
+	@echo "ASM flag       : $(USE_ASM)"
+	@echo "Video library  : $(platform_video)"
+	@echo "Thread library : $(platform_threads)"
+
+#-----------------------------------------------------------------------------#
+# This section is pretty much just for Ryan's use to make distributions.
+#  You Probably Should Not Touch.
+#-----------------------------------------------------------------------------#
+
+# These are the files needed in a binary distribution, regardless of what
+#  platform is being used.
+BINSCOMMON  = $(MAINEXE) $(STANDALONEEXE)
+BINSCOMMON += LICENSE.TXT
+
+.PHONY: package msbins win32bins nocygwin
+package: clean
+	cd .. ; zip -9rz ./toby-src-$(shell date +%m%d%Y).zip toby -x "*CVS*" < toby/FILEID.DIZ
+
+
+ifeq ($(strip $(cygwin)),true)
+msbins: win32bins
+
+win32bins: clean all
+ifeq ($(strip $(platform_video)),sdl)
+	cp $(SDL_LIB_DIR)/SDL.dll .
+    EXTRAPACKAGELIBS := SDL.dll
+endif
+	echo -e "\r\n\r\n\r\nHEY YOU.\r\n\r\n\r\nTake a look at README-win32bins.txt FIRST.\r\n\r\n\r\n--ryan. (icculus@linuxgames.com)\r\n\r\n" |zip -9rz ../toby-win32bins-$(shell date +%m%d%Y).zip $(EXES) $(EXTRAPACKAGELIBS) README-win32bins.txt
+
+else
+msbins: nocygwin
+win32bins: nocygwin
+endif
+
+nocygwin:
+	@echo This must be done on a Windows box in the Cygwin environment.
+
+#-----------------------------------------------------------------------------#
+# That's all, folks.
+#-----------------------------------------------------------------------------#
+
+# end of Makefile ...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,26 @@
+Documentation is in the docs/ directory. It's meager, but there are plans to
+ greatly enhance the contents of this directory in the near future.
+
+Quick start:
+
+Compile the source into an executable file:
+
+"make"
+
+Run it:
+
+"./toby"
+
+Obviously, this is for Unix environments like Linux.
+
+This program is licensed under the GNU General Public License. Please know
+ your rights and freedoms; the license text can be found in docs/LICENSE.TXT;
+ another copy is also in the root directory of the source tree, so you have
+ ample opportunity to find it.  :)
+
+Enjoy!
+
+--ryan. (icculus@linuxgames.com)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/LICENSE.TXT	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+	  Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+	 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
+    USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/changelog.txt	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,108 @@
+Toby CHANGELOG.
+
+
+Please note that only the most significant changes are noted here. Also,
+things that aren't visually interesting usually aren't mentioned. For
+example, the fact that the keyword tables are now autosorted doesn't get
+noted, but the fact that there's now a splash screen is noted. This is
+meant to be informative, but not authoritative.
+
+
+If you want a byte-for-byte revision history, please use the CVS server:
+    [hhmm...which is not currently available, since XNOT's demise. The
+     repository is intact, and will be made public again sooner or later.]
+
+What's new in Toby alpha6:
+- Added (multidimensional) arrays, a String intrinsic type, and functions for
+  string manipulation to the interpreter and Toby language.
+- Added French translation by Olivier Scalbert. Thanks!
+- Rewrote TurtleSpace...AGAIN. TurtleSpace is now a class (not an interface)
+  which does all the high-level stuff. It talks to a TurtleSpaceRenderer
+  interface, which does the low-level stuff, like getting bits to the screen.
+  the high-level code (turtle management, etc) was moved out of JTurtleSpace
+  and into TurtleSpace. The rest of JTurtleSpace became SwingRenderer.
+  Turtle.java had all the painting and calculation stuff moved out of it and
+  into SwingRenderer. Turtle.java is now just a container of info for a given
+  turtle (angle, size, position, etc.), and is in the main turtlespace
+  package. TriangleTurtle mostly made it's way into SwingRenderer for now, and
+  will eventually move into TurtleSpace. Turtles, I guess, will always be
+  triangles. Abstractness has limits.  :)
+- Added (for my amusement as much as a test of the new TurtleSpace) an
+  SDL-based native code implementation of TurtleSpaceRenderer. It crashes
+  sooner than later, and everything but line-drawing is a no-op, but it runs!
+  This is not to be tried by the weak, but the C and java code is in there.
+- This will be the last Java release by me. The next revision will be a C++
+  rewrite. The Java code will be kept around, and enhancements and fixes will
+  still be accepted, but I will be focusing on the C++ version after alpha6.
+
+What's new in Toby alpha5:
+- Fixes, improvements, and revisions, oh my!
+- Added a thanks.txt file to the docs.
+- Added some basic batch file/scripts for running Toby.
+- The parser and interpreter have been COMPLETELY rewritten. The new system
+  has been termed the TUD engine (for Toby Universal Domination), and it's
+  much, MUCH, faster than the alpha4 interpreter for several reasons.
+  At the same time, it's also much more flexible, which means sooner or later
+  more languages will get plugged into this project. An honest-to-God LOGO
+  implementation comes to mind, but other things like scientific modelling
+  languages and such should not be ruled out, either.
+- TurtleSpace has become an interface, which is implemented by a
+  JComponent-based widget. This abstraction will, eventually, allow us to
+  create a Spotlet (Java UI on the Palm Pilot) version of Toby.
+- A lot of handy code was moved from TobyProcedure.java (most of what wasn't
+  moved out of this class was eventually rewritten) to SaneTokenizer.java.
+  Anything that could be considered abstract was moved out of TobyTokenizer
+  and placed in SaneTokenizer, too. Now TobyTokenizer.java does just what is
+  absolutely specific to the Toby language.
+- The program has been separated into packages under the last.toby.* tree.
+- Lots of things that had wide use, like TobyParseException, have been made
+  more abstract (in this case, renamed to "ParseException").
+- The interpreter is no longer a subclass of TurtleSpace. They are completely
+  separate entities, which makes better sense in the long run.
+- TobyLanguage no longer uses printf()-style format tags, like "%s," "%d,"
+  etc, since this prevents true language abstraction. Now tags are simply
+  "%1," "%2," etc., so they may be in any order in the text and still
+  recieve correct replacement, and we can change the output of "12" to "twelve"
+  in the source base and not have to change the local strings. Furthermore,
+  the English text is the default hardcoded language, but this may be
+  overridden at runtime by a toby.lang file, so new languages may be added
+  without a recompile or modification of the source code.
+- Toby.java is now just an entry to the code. The original Toby.java has
+  become last.toby.gui.TobyFrame ...
+- Fixes to the Swing code.
+- SaneTokenizer now handles pushBack() better.
+- Much, much more.
+
+...basically, this was a almost complete rewrite; every subsystem was looked
+at, and reevaluated. There is still more to be done.
+
+
+What's new in Toby alpha4:
+- Lots of bug fixes and code improvements.
+- Required Java version is now 1.2, Java 1.1 w/ Swing will not be
+  sufficient for much longer, I think.
+- Toby now understands the "==" operator, which works like the Java
+   "==" operator...equivalence checking.
+- Splash screen code is written and incorporated. Need a better graphic.
+- An angle of zero degrees in TurtleSpace used to be due north. This was
+  because LOGO treated angles this way. This has been changed to follow
+  geometric convention; zero degrees is now due east.
+- All literal strings have been moved to TobyLanguage.java ...Code has
+  been added to make dynamic language support a reality. Soon, there will
+  be translations to other languages, and in the next alpha, you won't
+  even need a recompile (or restart) to switch languages.
+- On file open, if the file doesn't exist, we try to open filename.toby,
+  just in case. On save, if .toby extension isn't specified, we add it.
+- Checks for various incompatibilities in virtual machines/class library
+  implementations have been moved to Incompatibilities.java.
+- ...and much, much more.
+
+
+What's new in Toby alpha3:
+- Lots of stuff; this is the first public release, and I wasn't keeping a
+  changelog before this.  :)
+
+--ryan. (icculus@lokigames.com)
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/thanks.txt	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,31 @@
+At this point, TOBY has been entirely written, and maintained by
+ Ryan C. Gordon (icculus@linuxgames.com), but in the spirit of the GNU
+ project, the software is placed under GNU General Public License, and hopes
+ to see more contributors in the future. At such a time, this file will list
+ more names. :)  In the meantime...
+
+...Ryan would like to give a shout out to the following:
+
+- Gregory S. Read, for testing Toby's limits, breaking the ELSEIF statement,
+  and being a bizarre sort of soul mate. Get yer slack on.
+- Sabrina Blanks, April Andrews, and Nicki Publick for being unwitting test
+  subjects for Toby.
+- Loren Osborne, for many hours of debate and discussion of implementation.
+- Michael Roessler, who managed to sleep through the noise of my clicky
+  keyboard on many consecutive nights of hacking.
+- The journal list gang, for listening to Ryan ramble about his life.
+- Robert Spidle, for battling ninjas.
+- The "Dragon book" for parsing concepts. Friggin' trees, man.
+- Mr. Mullen and Mrs. Kelly, for putting me up to the original project.
+- Karie Publick, for the naming the program, in a roundabout way.
+- Mrs. Strohm, for many things I never knew I'd be thanking her for later.
+- YOUcentric, for proof that Java doesn't necessarily suck.
+- Sun Microsystems, for all the effort to disprove YOUcentric.
+- Bernd Kreimeier, for thoughts on efficiency of the instanceof operator.
+- Ani Difranco, Phish, Soul Coughing, Soul Miner's Daughter, Beastie Boys,
+  AMG, Belle and Sebastian, and Tool for providing the Soundtrack for da Hack.
+- The Freshmeat crew, for cutting my appindex entry by about 18 sentences.
+- ...and 'A' through 'F' in the phone book.
+
+--ryan.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/todo.txt	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,237 @@
+// Things still to be done for TOBY...
+//  some are bugfixes, some are enhancements, some are hopes and dreams...
+
+
+(Most of these were written in regards to previous rewrites of the codebase.
+ The C++ version (the current one) is rewrite #4. Much of this is possibly
+ Java-specific.)
+
+ongoing bugfixes/enhancements :
+    Build a table with all available renderers, and let the user pick them
+    at runtime?  Is this worthwhile?
+
+    The FrameBuffer and SDL renderers are inefficient and broken.
+
+    Move the source tree to src/
+
+    GLOBAL REFERENCING IS FUCKED.
+
+    I want an alpha channel in the pen. By default, there's 15 or so colors
+    with setPenColor(). Then there's more advanced drawing with
+    setPenColorRGB. I also want a setPenColorRGBA or something.
+
+    The only pencolor StdFunction should set red, green, blue, and alpha in
+    one call. The weaker versions should be in a Toby-specific package.
+
+    I'd like to be able to have a way to tell TurtleSpace to change it's
+     coordinate system, so it's not pixel-based, but 1-100, or 0.0-1.0 or
+     999 to 1055 or whatever.
+
+    I want TurtleSpace to just be graphic-specific stuff. All the turtle
+    management, etc. should be in a separate class, which makes requests
+    through the interface for drawing lines between two points, text, etc.
+
+    There should be a IntegerIntrinsic and a FloatIntrinsic (which may hold
+    a double), not a NumberIntrinsic. FloatIntrinsics should throw an
+    exeception if you call getIntValue() when it's holding an non-whole number.
+
+    Hhm...might need a CastExpressionLogicContext or something.
+
+    Strange duplicate error if I have a bogus file on the command line.
+
+    A font height stdfunction would be good.
+
+    JTurtleSpace: drawing the turtle is not resetting the GC's color.
+
+    There isn't a "!=" operator in Toby?!
+
+    Typechecking in the Toby parser is either screwed, or nonexistant.
+
+    A screenshot facility might be nice.
+
+    TobyMenuBar.java : Need to not hardcode TobyParser...
+    TobyMenuBar.java : Move execution to separate class.
+
+    LogicContext should not have statics.
+
+    The statics in LogicContext prevent multiple concurrent interpreters.
+
+    swing turtle should be fixed width, not based on screen size.
+
+    Allow JTurtleSpace to load graphics in background.
+
+    stdfunctions should have their names assigned at construction by
+     the caller.
+
+    Keep static references to the stdfunctions logic contexts, and
+     have the parsers install them in the globallogiccontext themselves.
+
+    Add TurtleSpaceException.
+
+    Have a turtle built on startup.
+
+    Are all the linkImpl()s protected? executeImpl?
+
+    use gratuitous verifyEndLine() calls.
+
+    elseif hoses.
+
+    Why are the fields in FlowException public?
+
+    Can I have one java.awt.Graphics object per thread? So I don't need to
+     synchronize graphic functions?
+
+    Sometimes program locks before initial paint. File open problem?
+
+    Remove as many synchronizings from TurtleSpaces as possible.
+
+    Make it so swing turtles don't need to be a square. This code is mostly in
+     place. Nuke private setSize() and the sideLength var and see what breaks...
+
+    JTurtleSpace.getTurtleSpaceWidth() and height must not return different
+     values during interpretation, so must handle component resize events...
+
+    Move VERSION and TITLE from last.toby.Toby to last.toby.util.TobyLanguage?
+
+    Need method in TurtleSpace to determine due north
+     (it's different for Toby and LOGO...)
+
+    not one damned comment is correct anymore.  :)
+
+    (See if getParent()/getValue() vs. public members are much slower...)
+    check all nodetrees freeResourceImpls...
+
+    Make tobylanguage more neutral.
+
+    Make ReturnException.
+    Make GotoException.
+    Make BreakException.
+
+    Change NodeTree to TreeNode. ANnoying.
+
+    We need to remove as many "SYNTAX ERROR" messages as possible. This
+     should be a last-choice message for when the parser is COMPLETELY
+     confused as to the state of the program. It should NEVER be used by
+     the interpreter. This might add a bunch of strings to TobyLanguage.
+
+    incompatibility : Drawing on eastern edge of turtle space leaves
+     graphic artifacts on Win32 Sun JDK ...
+
+    Parser.searchAlphabeticArray() could have a better search
+     algorithm. And alphabetizeArrayElements() is weak. It's just a lame
+     bubble sort right now.
+
+    operator precedence needs to be done on levels (i.e. '*' and '/' are
+     on the same "level"...)
+
+    Have Toby not start at screen size, but something average, and then
+     save the window position/size...?
+
+    Maybe we can move all the file i/o from TobyFrame.java to its own class?
+
+    Better splash graphic. PLEASE.
+
+    Literal strings are all centralized into a static class, which is
+     good. Now, It would be better if TobyLanguage would, at startup,
+     read the literals from disk, so not even a recompile is needed to
+     change the language of the application. If worse comes to worse,
+     we default to the English literals which are static.
+
+    can we pre-JIT specific classes/methods?
+
+    Alt-hotkey should bring up the menus. A lot of the hotkeys aren't making
+     it past the text editor component right now.
+
+    In fact, rip out that cruddy editor widget...
+
+    The ultimate ongoing fix are the "!!!" comments. Any comments containing
+     '!!!' have been placed there to alert me that there is a bug/deficiency
+     in the code that is worth revisiting, but probably isn't crippling. As
+     such, they tend to build up. Feel free to fix any of these and submit
+     patches to rgordon@xnot.com ...
+
+    Make inputarea use sane keys...I don't like the Swing defaults. Therefore
+     someday I'd like to either replace the Swing component with a homegrown
+     prettier/more functional textarea, or make some sort of customizer;
+     config file or whatnot. Mostly, I'd like SHIFT-DELETE and SHIFT-INSERT
+     to cut and paste.  :) Other enhancements welcome.
+
+    Functions can specify a return type and then return nothing. This should
+     be considered a bug. (Java and C consider it a feature, and it is, but
+     it confuses beginning programmers.)
+
+    FIX VARVIEWER. It is BADLY broken. It's never worked right.
+
+    When program is quitting, and you hit cancel on the "save" dialog, the
+     window still closes (although the VM doesn't terminate). This behavior
+     only seems to happen when the window manager tries to close the window
+     (clicking the little 'X' in win95, or whatnot under Linux)...selecting
+     "Quit" from the Toby menu seems to work correctly.
+
+    Maximize window instead of sizing to screen width and height: is there a
+     way to do this in Swing?
+
+    Move parse and execution time report code to more user-friendly output.
+     Right now it just dumps to stdout. I'd like it to go to
+     EditorInformationDisplay or something.
+
+    Make Applet work with JavaScript...so JScript can pass a string of TOBY
+     code (perhaps from a form's textarea...) to the applet to draw.
+
+    (Does the applet even work anymore?)
+
+
+Milestones: NOT ACCURATE ANYMORE.
+
+alpha2 : completed.
+    Convert from AWT 1.1 to Swing.          (COMPLETED)
+    remove dependency on last.* packages.   (COMPLETED)
+    remove glaring bugs.                    (COMPLETED)
+
+alpha3 : completed.
+    Add globals                             (COMPLETED)
+    descending FOR loops and STEPs...       (COMPLETED)
+    WHILEs...                               (COMPLETED)
+    line/column readout in TobyInputArea.   (COMPLETED)
+
+alpha4 : completed.
+    allow assignments in var declaration.   (COMPLETED)
+    more standard functions...              (COMPLETED)
+    Fix as many "!!!" comments as possible. (COMPLETED)
+    Initial dynamic language support.       (COMPLETED)
+    Add splash screen code.                 (COMPLETED)
+
+alpha5 : completed.
+    Fully separate parser and interpreter.  (COMPLETED)
+    Separate interpreter and TurtleSpace.   (COMPLETED)
+    Rewrite interpreter to use parse trees. (COMPLETED)
+    Split this thing up into packages.      (COMPLETED)
+    Abstract TurtleSpace into interface.    (COMPLETED)
+
+alpha6 : in progress.
+    COMMENT EVERYTHING.
+    add arrays?                             (COMPLETED)
+    add String intrinsic?                   (COMPLETED)
+    Printing source code.
+    Printing current TurtleSpace.
+    Undo/redo
+    Make TurtleSpace into a bean.
+    Add status bar to bottom of frame...
+    Implement help system.
+    Rewrite VarViewer to be cooler.
+    Rewrite/replace text editor.
+    German langfile.
+    Spanish langfile.
+    French langfile.                        (COMPLETED)
+    Write Spotlet version of TurtleSpace.
+    Verify the applet works in a
+     Java 1.2 compatible browser (HotJava?)
+
+1.0 : not yet begun.
+    fix bugs reported from betas.
+    Clean up interface problems reported in beta2.
+    fix all outstanding bugs.
+    release.
+
+// end of todo ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/april.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,61 @@
+function main() returns nothing
+	// april kicks ass
+	flower()
+endfunction
+
+
+function flower() returns nothing
+	number i
+	number bob
+	number direction
+
+	direction = 1
+
+	bob = 0
+
+	for i = 100 downto 10 step -5
+		bob = bob + direction
+	
+		if (bob >= 12)
+			bob = 11
+			direction = -1
+		endif
+
+		if (bob <= 0)
+			bob = 0
+			direction = 1
+		endif
+
+		setPenColor(bob)
+
+		webbox(i)
+	endfor
+
+endfunction
+
+
+function webbox(number m) returns nothing
+	number i
+
+	for i = 1 to 360 / 10
+		box(m)
+		turnRight(10)
+
+	endfor
+endfunction
+
+
+function box(number size) returns nothing
+
+	number i
+
+	for i = 1 to 4
+		goForward(size)
+		turnRight(90)
+	endfor
+
+endfunction
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/april_modified.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,63 @@
+function main() returns nothing
+	// april kicks ass
+	flower()
+endfunction
+
+
+function flower() returns nothing
+	number i
+	number bob
+	number direction
+
+	direction = 1
+
+	bob = 0
+
+	for i = 10 to 100 step 5
+		bob = bob + direction
+	
+		if (bob >= 12)
+			bob = 11
+			direction = -1
+		endif
+
+		if (bob <= 0)
+			bob = 0
+			direction = 1
+		endif
+
+		setPenColor(bob)
+		webbox(i)
+	endfor
+
+endfunction
+
+
+function webbox(number m) returns nothing
+	number i
+
+	for i = 1 to 360 / 10
+		box(m)
+		turnRight(10)
+
+	endfor
+endfunction
+
+
+function box(number size) returns nothing
+
+	number i
+
+	for i = 1 to 4
+		goForward(size)
+		turnRight(90)
+	endfor
+
+endfunction
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/boolTest.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,51 @@
+//------------------------------------------------------------
+// boolTest.toby ... Should draw two large circles
+//  of dotted lines, connected in the center of 
+//  TurtleSpace.
+//
+// - Tests IF statement, BOOLEAN intrinsic.
+//
+//   Copyright (c) Lighting and Sound Technologies, 1998.
+//    Written by Ryan C. Gordon.
+//------------------------------------------------------------
+
+function main() returns nothing
+
+    boolean isDrawTime
+	boolean goRight
+    number i
+
+	disableFence()
+
+    isDrawTime = true
+
+    for i = 1 to 720
+        if (isDrawTime == true)
+            setPenDown()
+            isDrawTime = false
+        else
+            setPenUp()
+            isDrawTime = true
+        endif
+
+        goForward(10)
+
+			// this isn't meant to be
+			//  efficient. This is a test.
+        if (i > 360)
+			goRight = true
+		endif
+
+		if (goRight)
+            turnRight(1)
+        else
+            turnLeft(1)
+        endif
+    endfor
+
+endfunction
+
+// end of boolTest.toby ...
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/boxes.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+// boxes.toby : Various cool geometrics with simple boxes.
+
+function box(number size) returns nothing
+//---------------------------------------------------------//
+//  Most functions in this package make use of this        //
+//   function for cool stuff.                              //
+//                                                         //
+//      params : (number) size == size of one side of box. //
+//     returns : void.                                     //
+//---------------------------------------------------------//
+    number i
+    for i = 1 to 4
+        goForward(size)
+        turnRight(90)
+    endfor
+endfunction
+
+
+
+function webBox(number size, number angle) returns nothing
+//---------------------------------------------------------//
+//  Make a weblike pattern out of boxes.                   //
+//                                                         //
+//      params : (number) size == size of one side of box. //
+//               (number) angle == amount of turn for each //
+//                                 box. Smaller number ==  //
+//                                 more boxes.             //
+//     returns : void.                                     //
+//---------------------------------------------------------//
+    number i
+    for i = 1 to (360 / angle)
+        box(size)
+        turnRight(angle)
+    endfor
+endfunction
+
+
+function main() returns nothing
+    webBox(100, 2)
+endfunction
+
+// end of boxes.toby ...
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/colorBlocks.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,30 @@
+function main() returns nothing
+
+    number i
+
+    for i = 0 to 15
+        setPenColor(i)
+        fillBlock(i * 20, (i + 1) * 20)
+    endfor
+
+endfunction
+
+
+function fillBlock(number start, number stop) returns nothing
+
+    number i
+
+    setPenDown()
+
+    for i = start to stop
+        setTurtleXY(0, i)
+        setAngle(0)
+        goForward(30)
+    endfor
+
+endfunction
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/connie.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,74 @@
+//
+// Something quick to test STEP...first four
+//  circles should have turtle loop around
+//  it three times. The next four should just draw.
+//
+// Copyright (c) 1999 Lighting and Sound Technologies.
+//  Written by Ryan C. Gordon.
+
+function main() returns nothing
+	number i
+
+	setPenColor(1)	
+
+	for i = 1 to 360
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 1 to 360 step 1
+		turnLeft(3)
+		goForward(5)
+	endfor
+	turnRight(90)
+	for i = 360 downto 1
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 360 downto 1 step -1
+		turnLeft(3)
+		goForward(5)
+	endfor
+
+	setPenColor(2)	
+
+
+		// these four for loops should not run...
+	for i = 1 downto 360 step -1
+		goForward(1000)
+	endfor
+	for i = 360 to 1 step 1
+		goForward(1000)
+	endfor
+	for i = 1 downto 360 step -1.7
+		goForward(1000)
+	endfor
+	for i = 360 to 1 step 1.5
+		goForward(1000)
+	endfor
+
+	setPenColor(4)	
+
+	turnRight(45)
+	for i = 1 to 360 step 3.0
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 1 to 360 step 3
+		turnLeft(3)
+		goForward(5)
+	endfor
+	turnRight(90)
+	for i = 360 downto 1 step -3.0
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 360 downto 1 step -3
+		turnLeft(3)
+		goForward(5)
+	endfor
+
+
+	hideTurtle()
+endfunction
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/eyes.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,91 @@
+//------------------------------------------------------------
+// eyes.toby : draw some eyes on the screen.
+//
+//   Copyright (c) Lighting and Sound Technologies, 1998.
+//    Written by Ryan C. Gordon.
+//------------------------------------------------------------
+
+// Global variables...
+//number eyeballStep
+
+
+function eyeballs(number skip) returns nothing
+    number i
+    boolean isDrawTime
+
+    isDrawTime = false
+
+    setPenColor(4)
+    for i = 1 to 720
+        if (isDrawTime)
+            setPenDown()
+            isDrawTime = false
+        else
+            setPenUp()
+            isDrawTime = true
+        endif
+        goForward(skip)
+
+        if (i >= 360)
+            turnRight(1)
+        else
+            turnLeft(1)
+        endif
+    endfor
+endfunction
+
+
+function pupil(number x, number y) returns nothing
+    number color = 0
+    number i
+	number direction = 1
+
+	setTurtleXY(x, y)
+
+    for i = 1 to 360
+        setPenColor(color)
+        setPenDown()
+        goForward(30)
+        setPenUp()
+        goBackward(30)
+        turnRight(1)
+        color = color + direction
+        if (color >= 15)
+            direction = -1
+		elseif (color <= 0)
+			direction = 1
+        endif
+    endfor
+endfunction
+
+
+function main() returns nothing
+    number centerX
+    number centerY
+
+	centerX = getTurtleX()
+	centerY = getTurtleY()
+
+	eyeballs(2)
+
+//    center = calculateRadius(eyeballStep)
+
+
+	pupil(centerX - 115, centerY)
+	pupil(centerX + 115, centerY)
+
+		// use the turtle as a "nose."  :)
+	setTurtleXY(centerX, centerY + 50)
+	setAngle(90)
+
+endfunction
+
+// end of eyes.toby ...
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/flowerVines.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,53 @@
+number r = 0.0
+number g = 0.0
+number b = 0.0
+
+function main() returns nothing
+	hideTurtle()
+	disableFence()
+	rightDragon(20, 3)
+endfunction
+
+function leftDragon(number iteration, number dist) returns nothing
+	r = r + 0.001
+	if (r > 1.0)
+		r = 0.0
+	endif
+	setPenColorRGB(r, g, b)
+	if (iteration == 0)
+		g = g + 0.01
+		if (g > 1.0)
+			g = 0.0
+		endif
+		goForward(dist)
+	else
+		leftDragon(iteration - 1, dist)
+		turnLeft(90)
+		rightDragon(iteration - 1, dist)
+	endif
+endfunction
+
+
+function rightDragon(number iteration, number dist) returns nothing
+	b = b + 0.001
+	if (b > 1.0)
+		b = 0.0
+	endif
+	setPenColorRGB(r, g, b)
+	if (iteration == 0)
+		g = g + 0.01
+		if (g > 1.0)
+			g = 0.0
+		endif
+		goForward(dist)
+	else
+		leftDragon(iteration - 1, dist)
+		turnRight(90)
+		rightDragon(iteration - 1, dist)
+	endif
+endfunction
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/globTest.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,30 @@
+//---------------------------------------------------
+// If globals are working correctly, this should
+//  draw a line east, WAY off the edge of
+//  TurtleSpace. Otherwise, it'll just draw a 
+//  line somewhere other than due east, or maybe just
+//  draw a line about 5 pixels wide or give an error
+//  or something like that.
+//
+//Copyright (c) 1999 Lighting and Sound Technologies.
+// Written by Ryan C. Gordon.
+//---------------------------------------------------
+
+number thisIsGlobal = 90
+
+function main() returns nothing
+	disableFence()
+	turnRight(thisIsGlobal)
+	thisIsGlobal = 10000
+	testGlob()
+	goForward(thisIsGlobal)
+endfunction
+
+function testGlob() returns nothing
+	number thisIsGlobal
+
+	thisIsGlobal = 5
+endfunction
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/gradient.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,34 @@
+function main() returns nothing
+
+	number i = 0
+	number stepSizeH = 1 / getTurtleSpaceWidth()
+	number stepSizeV = 1 / getTurtleSpaceHeight()
+	number r = 0.0
+	number g = 1.0
+	number b = 0.0
+
+	disableFence()
+	hideTurtle()
+	turnRight(90)
+
+	for b = 0.0 to 1.0 step stepSizeV
+		setTurtleXY(0, i)
+		for r = 0.0 to 1.0 step stepSizeH
+			setPenColorRGB(r, g, b)
+			goForward(1)
+		endfor
+		g = g - stepSizeV
+		i = i + 1
+	endfor
+
+endfunction
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/gradient2.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,32 @@
+function main() returns nothing
+
+	number i = 0
+	number stepSizeH = 1 / getTurtleSpaceWidth()
+	number stepSizeV = 1 / getTurtleSpaceHeight()
+	number r = 0.0
+	number b = 0.0
+
+	disableFence()
+	hideTurtle()
+	turnRight(90)
+
+	for b = 0.0 to 1.0 step stepSizeV
+		setTurtleXY(0, i)
+		for r = 0.0 to 1.0 step stepSizeH
+			setPenColorRGB(r, 0.0, b)
+			goForward(1)
+		endfor
+		i = i + 1
+	endfor
+
+endfunction
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/greg1.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,34 @@
+function main() returns nothing
+    number i
+	number j
+
+	for j = 1 to 100
+    	for i = 1 to 360
+			goForward(1)
+			turnRight(1)
+		endfor
+		turnRight(j)
+	endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+	number color
+
+    for i = 1 to 360 step 4
+
+		color = round(random() * 10) + 1
+		setPenColor(color)
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/nesting.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,50 @@
+//--------------------------------------------------------
+// nesting.toby -- A program to test nested FORs and IFs.
+//
+// This program will draw boxes increasingly large, and
+//  in many colors, to test if Toby can handle some
+//  nested FORs and IFs. It should look like a square
+//  with different colored lines pulsing, and in the
+//  end, four squares, moving in different directions
+//  should be drawn.
+//
+// There are cleaner ways to write this program, but
+//  we wanted to nest stuff.
+//
+// Copyright (c) 1999 Lighting and Sound Technologies
+//  Written by Ryan C. Gordon.
+//--------------------------------------------------------
+
+function main() returns nothing
+	number totalIterations
+    number boxSize
+	number boxLoop
+	number color
+	number direction
+
+	hideTurtle()
+
+	for direction = 1 to 4
+		color = 0
+		for totalIterations = 1 to 5
+			for boxSize = 1 to 100
+				color = color + 1
+				if (color > 15)
+					color = 0
+				endif
+				setPenColor(color)
+				for boxLoop = 1 to 4
+					goForward(boxSize)
+					turnLeft(90)
+				endfor
+			endfor
+		endfor
+		turnRight(90)
+	endfor
+
+endfunction
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/nicki.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,53 @@
+number color
+
+function main() returns nothing
+	disableFence()
+	hideturtle()
+	flower(50, 100, 1)	
+endfunction 
+
+
+function flower(number start, number end, number hop) returns nothing
+// nicki is cool
+
+	number joe
+	number color = 0
+	number direction = 1
+
+	for joe = start to end step hop
+		color = color + direction
+
+		if (color > 11)
+			color = 11
+			direction = -1
+		endif
+
+		if (color < 0)
+			color = 0
+			direction = 1
+		endif
+
+		setPenColor(color)
+		webbox(joe)
+	endfor
+endfunction
+
+function webbox(number size) returns nothing
+	number x
+
+	for x = 1 to 360 / 10
+		octogon(size)
+		turnRight(15)
+	endfor
+endfunction
+
+
+function octogon(number size) returns nothing
+	number i
+
+	for i = 1 to 8
+		goForward(size)
+		turnRight(45)
+	endfor
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/psychedelic.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,36 @@
+number color
+
+function main() returns nothing
+    number i
+	color = 0
+	disableFence()
+hideTurtle()
+    for i = 1 to 360 step 2
+        circle()
+        turnRight(2)
+    endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+
+    for i = 1 to 360
+		color = color + 1
+		if (color > 11)
+			color = 0
+		endif
+		setPenColor(color)
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/psychedelic2.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,33 @@
+function main() returns nothing
+    number i
+	number color
+	color = 0
+
+	disableFence()
+    hideTurtle()
+
+    for i = 1 to 360 step 2
+		setPenColor(color)
+        circle()
+        turnRight(2)
+		color = color + 1
+		if (color > 15)
+			color = 0
+		endif
+    endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+
+    for i = 1 to 360
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/psychedelic3.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,28 @@
+function main() returns nothing
+    number i
+
+    for i = 1 to 360 step 2
+        circle()
+        turnRight(2)
+    endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+	number color
+
+    for i = 1 to 360
+
+		color = round(random() * 10) + 1
+		setPenColor(color)
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/psychedelic4.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,32 @@
+function main() returns nothing
+    number i
+	number angle = 0
+
+    for i = 1 to 360 step 2
+        circle()
+		homeTurtle()
+		angle = angle + 3
+        turnRight(angle)
+    endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+	number color
+
+    for i = 1 to 360 step 4
+
+		color = round(random() * 10) + 1
+		setPenColor(color)
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/rotateTurtle.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,14 @@
+// This just rotates the turtle once around.
+
+function main() returns nothing
+	number i
+
+	for i = 1 to 360
+		turnRight(1)
+		pause(5)
+	endfor
+endfunction
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/sabrina.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,44 @@
+function main() returns nothing
+	number xMax = getTurtleSpaceWidth()
+	number yMax = getTurtleSpaceHeight()
+	number xPos
+	number yPos
+	number angle
+	number distance
+	number color
+
+	disableFence()
+	hideTurtle()
+
+	while (true)
+		color = round(random() * 14) + 1
+		xPos = round(random() * xMax) + 1
+		yPos = round(random() * yMax) + 1
+		angle = round(random() * 360) + 1
+		distance = random() * (yMax / 2)
+
+		setPenColor(color)
+		setTurtleXY(xPos, yPos)
+		setAngle(angle)
+		goForward(distance)
+	endwhile
+
+endfunction
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/sabrina2.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,33 @@
+
+function main() returns nothing
+
+	number myValue
+
+	number i
+
+	while (true)
+		for i = 1 to 36
+			setPenColor(round(random() * 15))	
+			myValue = random() * 100
+			box(myValue)
+
+			turnRight(10)
+		endfor
+			cleanupTurtleSpace()
+	endwhile
+endfunction
+
+
+function box(number size) returns nothing
+
+	number counter
+
+	for counter = 1 to 4
+		goForward(size)
+		turnRight(90)
+	endfor
+
+endfunction
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/swirls.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,69 @@
+number r = 0.0
+number g = 0.0
+number b = 0.0
+
+function main() returns nothing
+	//doTopLeftFan()
+	doDragon()
+endfunction
+
+function doTopLeftFan() returns nothing
+	setTurtleXY(10, 100)
+	setAngle(90)
+	fanLeft(175, 10)
+endfunction
+
+function fanLeft(number distance, number angle) returns nothing
+	if (distance >= 0)
+		goForward(distance)
+		goBackward(distance - 10)
+		turnLeft(angle)
+		fanLeft(distance - 5, angle)
+	endif
+endfunction
+
+function doDragon() returns nothing
+	rightDragon(20, 3)
+endfunction
+
+function leftDragon(number iteration, number dist) returns nothing
+	r = r + 0.001
+	if (r > 1.0)
+		r = 0.0
+	endif
+	setPenColorRGB(r, g, b)
+	if (iteration == 0)
+		g = g + 0.01
+		if (g > 1.0)
+			g = 0.0
+		endif
+		goForward(dist)
+	else
+		leftDragon(iteration - 1, dist)
+		turnLeft(90)
+		rightDragon(iteration - 1, dist)
+	endif
+endfunction
+
+
+function rightDragon(number iteration, number dist) returns nothing
+	b = b + 0.001
+	if (b > 1.0)
+		b = 0.0
+	endif
+	setPenColorRGB(r, g, b)
+	if (iteration == 0)
+		g = g + 0.01
+		if (g > 1.0)
+			g = 0.0
+		endif
+		goForward(dist)
+	else
+		leftDragon(iteration - 1, dist)
+		turnRight(90)
+		rightDragon(iteration - 1, dist)
+	endif
+endfunction
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testArray.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,82 @@
+// this is not meant to be efficient. This is meant to
+// test arrays in Toby.  --ryan.
+
+function main() returns nothing
+	number i
+	array of number[1 to 2] screendim
+	array of number[1 to 13][0 to 1] myarray
+
+	screendim[1] = getTurtleSpaceWidth()
+	screendim[2] = getTurtleSpaceHeight()
+
+	homeTurtle()
+	drawMoon(screendim[1] - (screendim[1] / 4), screendim[2] - ((screendim[2] / 8) * 7))
+
+	homeTurtle()
+	myarray[1][0] = 90
+	myarray[1][1] = 100
+	myarray[2][0] = -90
+	myarray[2][1] = 100
+	myarray[3][0] = -90
+	myarray[3][1] = 200
+	myarray[4][0] = -90
+	myarray[4][1] = 100
+	myarray[5][0] = -90
+	myarray[5][1] = 100
+	myarray[6][0] = -90
+	myarray[6][1] = 50
+	myarray[7][0] = 90
+	myarray[7][1] = 25
+	myarray[8][0] = 90
+	myarray[8][1] = 50
+	myarray[9][0] = -90
+	myarray[9][1] = 75
+	myarray[10][0] = -90
+	myarray[10][1] = 100
+	myarray[11][0] = -60
+	myarray[11][1] = 115
+	myarray[12][0] = -60
+	myarray[13][1] = 115
+
+	runArray(myarray)
+
+	hideTurtle()
+endfunction
+
+
+/// !!! should be an error.
+function runArray(array of number [1 to 3][0 to 1] anArray) returns nothing
+	number i
+
+	for i = 1 to 13
+		turnRight(anArray[i][0])
+		goForward(anArray[i][1])
+	endfor 
+endfunction
+
+
+// this would be a sun, but I'm too lazy to draw more
+//  than a circle.  :)
+function drawMoon(number x, number y) returns nothing
+	number i
+	number moonstep = 2
+
+	setPenDown()
+	setTurtleXY(x - 29, y)
+
+	for i = 1 to 360 / moonstep
+		goForward(1)
+		turnRight(moonstep)
+	endfor
+endfunction
+
+// end of arrayTest.toby ...
+
+
+
+	
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testMultiTurtling.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+//---------------------------------------------------------
+// A basic test of multiturtling capabilities.
+//
+//   This should have four turtles each draw
+//    a circle, so you get a diamond-like
+//    cluster. The north circle should be blue,
+//    the west green, east cyan, and south red.
+//
+//  Written by Ryan C. Gordon.
+//   Copyright (c) Lighting and Sound Technologies, 2000.
+//---------------------------------------------------------
+
+function main() returns nothing
+	number i
+	number turtleId
+
+	disableFence()
+	addTurtle()
+	addTurtle()
+	addTurtle()
+
+	setPenColor(3)
+
+	useTurtle(1)
+	turnRight(90)
+	setPenColor(4)
+	useTurtle(2)
+	turnLeft(90)
+	setPenColor(1)
+	useTurtle(3)
+	turnLeft(180)
+	setPenColor(2)
+
+	for i = 1 to 360
+		for turtleId = 0 to 3
+			useTurtle(turtleId)
+			turnRight(1)
+			goForward(1)
+		endfor
+	endfor
+endfunction
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testRecursive.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,14 @@
+
+number counter = 0
+
+function main() returns nothing
+	goForward(100)
+	turnRight(90)
+
+	counter = counter + 1
+	if (counter < 4)
+		main()
+	endif
+endfunction
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testReturn.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,14 @@
+
+
+function main() returns nothing
+	number x = 10
+	x = returnOneThousand()
+	goForward(x)
+endfunction
+
+
+function returnOneThousand() returns number
+
+	return(1000)
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testStep.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,67 @@
+//
+// Something quick to test STEP...first four
+//  circles should have turtle loop around
+//  it three times. The next four should just draw.
+//
+// Copyright (c) 1999 Lighting and Sound Technologies.
+//  Written by Ryan C. Gordon.
+
+function main() returns nothing
+	number i
+
+	for i = 1 to 360
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 1 to 360 step 1
+		turnLeft(3)
+		goForward(5)
+	endfor
+	turnRight(90)
+	for i = 360 to 1
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 360 to 1 step -1
+		turnLeft(3)
+		goForward(5)
+	endfor
+
+		// these four for loops should not run...
+	for i = 1 to 360 step -1
+		goForward(1000)
+	endfor
+	for i = 360 to 1 step 1
+		goForward(1000)
+	endfor
+	for i = 1 to 360 step -1.7
+		goForward(1000)
+	endfor
+	for i = 360 to 1 step 1.5
+		goForward(1000)
+	endfor
+
+
+	turnRight(45)
+	for i = 1 to 360 step 3.0
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 1 to 360 step 3
+		turnLeft(3)
+		goForward(5)
+	endfor
+	turnRight(90)
+	for i = 360 to 1 step -3.0
+		turnRight(3)
+		goForward(5)
+	endfor
+	for i = 360 to 1 step -3
+		turnLeft(3)
+		goForward(5)
+	endfor
+
+	hideTurtle()
+endfunction
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testString.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,86 @@
+function main() returns nothing
+	string x
+	array of string[0 to 10] myStrings
+    number fontHeight = 12
+	number i
+	string leftRight
+
+	setPenUp()
+
+	leftRight = "Left side-=-Middle-=-Right side"
+	x = "test of stringlength() was successful."
+	x = rightString(x, stringlength(x) - 8)
+
+	myStrings[0] = "String array test."
+	myStrings[1] = "w00t, old boy, w00t!"
+	myStrings[2] = joinStrings("this string->", "<-was joined")
+	myStrings[3] = leftString(leftRight, 9)
+	myStrings[4] = substring(leftRight, 12, 6)
+	myStrings[5] = rightString(leftRight, 10)
+	myStrings[6] = upperCaseString("ThiS IS uPpER casEd.")
+	myStrings[7] = lowerCaseString("ThiS IS LoWEr casEd.")
+	myStrings[8] = x
+	myStrings[9] = "last one"
+
+	setTurtleXY(10, fontHeight)
+	setAngle(0)
+	x = "passing string in a variable to a function."
+	drawString(x)
+
+	setAngle(90)
+	goForward(fontHeight)
+	setAngle(0)
+	drawString("string literal in a function call.")
+
+	setAngle(90)
+	goForward(fontHeight)
+	setAngle(0)
+	if ("equality tester" == "equality tester")
+		drawString("equality operator working.")
+	else
+		drawString("equality operator NOT working!")
+	endif
+
+	setAngle(90)
+	goForward(fontHeight)
+	setAngle(0)
+	if ("abc" > "def")
+		drawString("greater-than operator working.")
+	else
+		drawString("greater-than operator NOT working!")
+	endif
+
+	setAngle(90)
+	goForward(fontHeight)
+	setAngle(0)
+	if ("abc" < "def")
+		drawString("less-than operator NOT working.")
+	else
+		drawString("less-than operator working!")
+	endif
+
+
+
+	homeTurtle()
+
+	for i = 0 to 10
+		setPenColor(i + 1)
+		goForward(fontHeight * 3)
+		drawString(myStrings[i])
+		goBackward(fontHeight * 3)
+		turnRight(36)
+	endfor
+
+	// test rotation.
+	// test strlen
+
+endfunction
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testTurtleSpace.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,68 @@
+//-------------------------------------------------------------------
+// Test that TurtleSpace coordinate functions are functioning
+//  properly. You should end up with four arrows, east west, north
+//  and south, extending to the edges of TurtleSpace, centered on the
+//  edge.
+//
+// Copyright (c) 1999 Lighting and Sound Technologies.
+//   Written by Ryan C. Gordon.
+//-------------------------------------------------------------------
+
+function main() returns nothing
+    number i
+	number maxX = getTurtleSpaceWidth()
+	number maxY = getTurtleSpaceHeight()
+	number centerX = getTurtleX()
+	number centerY = getTurtleY()
+
+	hideTurtle()
+
+		// horizontal shaft.
+	setTurtleXY(0, centerY)
+	setAngle(0)
+	goForward(maxX)
+
+		// vertical shaft.
+	setTurtleXY(centerX, 0)
+	setAngle(90)
+	goForward(maxY)
+
+		// western arrow.
+	setTurtleXY(0, centerY)
+	setAngle(-45)
+	goForward(100)
+	setTurtleXY(0, centerY)
+	setAngle(45)
+	goForward(100)
+
+		// eastern arrow.
+	setTurtleXY(maxX, centerY)
+	setAngle(-135)
+	goForward(100)
+	setTurtleXY(maxX, centerY)
+	setAngle(135)
+	goForward(100)
+
+		// northern arrow.
+	setTurtleXY(centerX, 0)
+	setAngle(135)
+	goForward(100)
+	setTurtleXY(centerX, 0)
+	setAngle(45)
+	goForward(100)
+
+		// southern arrow.
+	setTurtleXY(centerX, maxY)
+	setAngle(-135)
+	goForward(100)
+	setTurtleXY(centerX, maxY)
+	setAngle(-45)
+	goForward(100)
+endfunction
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/testWhile.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,56 @@
+//----------------------------------------------------
+// This is an over-glorified test of the
+//  WHILE/ENDWHILE construct, buried in the
+//  doTriangle() function. If it works, you should
+//  end up with three filled-in triangles.
+//
+// Copyright (c) 1999 Lighting and Sound Technologies.
+//  Written by Ryan C. Gordon.
+//----------------------------------------------------
+
+function main() returns nothing
+	hideTurtle()
+	nuclearSymbol(150)
+endfunction
+
+
+function nuclearSymbol(number size) returns nothing
+	number i
+
+	setPenColor(14)
+
+	for i = 1 to size
+		setAngle(300)
+		doTriangle(i)
+	
+		setAngle(180)
+		doTriangle(i)
+	
+		setAngle(60)
+		doTriangle(i)
+	endfor
+endfunction
+
+
+function doTriangle(number size) returns number
+	number i
+
+	i = 1
+
+	while (i <= 3)
+		i = i + 1
+		goForward(size)
+		turnRight(360 / 3)
+	endwhile
+endfunction
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/theLight.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+// theLight.toby : Just plain cool.
+
+function clockwise(number size) returns nothing
+    number i
+    for i = 1 to 360
+        setPenDown()
+        goForward(size)
+        setPenUp()
+        goBackward(size)
+        turnRight(1)
+    endfor
+endfunction
+
+
+function theLight() returns nothing
+
+// This will eventually step in a FOR loop...
+
+    clockwise(50)
+    clockwise(100)
+    clockwise(150)
+    clockwise(200)
+    clockwise(250)
+    clockwise(300)
+    clockwise(350)
+    clockwise(400)
+    clockwise(450)
+    clockwise(500)
+endfunction
+
+
+function main() returns nothing
+	disableFence()	
+    theLight()
+endfunction
+
+// end of theLight.toby ...
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/triangleWeb.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,45 @@
+function main() returns nothing
+	number top = getTurtleSpaceWidth()
+	if (top < getTurtleSpaceHeight())
+		top = getTurtleSpaceHeight()
+	endif
+
+	disableFence()
+	setPenColor(8)
+	spiderWeb(top, top * 0.03, top * 0.15)
+endfunction
+
+function spiderWeb(number max, number min, number increment) returns nothing
+	number i
+
+	if (increment > 0.0)
+		increment = increment * -1.0
+	endif
+
+	for i = max downto min step increment
+		triangleWheel(i, 12)
+	endfor
+endfunction
+
+
+function triangleWheel(number size, number angle) returns nothing
+	number i
+
+	for i = 1 to 360 / angle
+		isosceles(size)
+		turnRight(angle)
+	endfor
+endfunction
+
+
+function isosceles(number size) returns nothing
+	number i
+
+	for i = 1 to 3
+		goForward(size)
+		turnRight(120)
+	endfor
+endfunction
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/triangleWheel.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,31 @@
+function main() returns nothing
+	number i
+
+	for i = 1 to 4
+		triangleWheel(120, 12)
+		triangleWheel(80, 12)
+		triangleWheel(40, 12)
+		turnRight(90)
+	endfor
+endfunction
+
+function triangleWheel(number size, number angle) returns nothing
+	number i
+
+	for i = 1 to 360 / angle
+		isosceles(size)
+		turnRight(angle)
+	endfor
+endfunction
+
+
+function isosceles(number size) returns nothing
+	number i
+
+	for i = 1 to 3
+		goForward(size)
+		turnRight(60)
+	endfor
+endfunction
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/webBox.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,20 @@
+function box(number size) returns nothing
+    number i
+
+    for i = 1 to 4
+		setPenColor(i)
+        goForward(size)
+        turnRight(90)
+    endfor
+endfunction
+
+
+function main() returns nothing
+    number i
+
+    for i = 1 to 36
+        box(100)
+        turnRight(10)
+    endfor
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/wierdBox.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,20 @@
+function wierdBox(number size) returns nothing
+    number i
+
+    for i = 1 to 7
+		setPenColor(i)
+        goForward(size)
+        turnRight(90)
+    endfor
+endfunction
+
+
+function main() returns nothing
+    number i
+
+    for i = 1 to 36
+        wierdBox(100)
+        turnRight(10)
+    endfor
+endfunction
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/programs/wireOrb.toby	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,23 @@
+function main() returns nothing
+    number i
+
+    hideTurtle()
+
+    for i = 1 to 360 step 2
+        circle()
+        turnRight(2)
+    endfor
+endfunction
+
+
+function circle() returns nothing
+    number i
+
+    for i = 1 to 360
+        goForward(3)
+        turnRight(1)
+    endfor
+endfunction
+
+
+
Binary file splash.jpg has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/ExecException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,80 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_EXECEXCEPTION_H_
+#define _INCLUDE_EXECEXCEPTION_H_
+
+#include "exceptions/FlowException.h"
+
+
+/*
+ *  ExecExceptions are for interpretation errors at runtime, as opposed to
+ *   parsetime errors.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class ExecException : public FlowException
+{
+public:
+    static ExecException *getInstance(void)
+    {
+        return(new ExecException());  // !!!
+    } // ExecException::getInstance
+
+    static void _throw(const char *err, const char *p, int l)
+                                                throw (ExecException *)
+    {
+        ExecException *e = getInstance();
+        initThrow(e, err, p, l);
+        throw(e);
+    } // ExecException::_throw
+
+    static void _throw(const char *err, const char *pName)
+                                                throw (ExecException *)
+    {
+        ExecException *e = getInstance();
+        initThrow(e, err, pName);
+        throw(e);
+    } // ExecException::_throw
+
+    static void _throw(const char *err, int lineNum) throw (ExecException *)
+    {
+        ExecException *e = getInstance();
+        initThrow(e, err, lineNum);
+        throw(e);
+    } // ExecException::_throw
+
+    static void _throw(const char *err) throw (ExecException *)
+    {
+        ExecException *e = getInstance();
+        initThrow(e, err);
+        throw(e);
+    } // ExecException::_throw
+
+private:
+    // no public construction.
+    ExecException(void) : FlowException() {}
+    ExecException(char *_msg) : FlowException(_msg) {}
+}; // class ExecException
+
+#endif  // !defined _INCLUDE_EXECEXCEPTION_H_
+
+// end of ExecException.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/FlowException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,112 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_FLOWEXCEPTION_H_
+#define _INCLUDE_FLOWEXCEPTION_H_
+
+#include "exceptions/TobyException.h"
+
+
+// !!!
+#define LINENUM_UNDEFINED  -1
+
+/*
+ * FlowExceptions are anything that interrupts program flow: this includes
+ *  parsing/linking errors, runtime errors, and user-initiated aborts, plus
+ *  other forms of normal logic interruptions like return statements.
+ *
+ * This is a generic base class. Coders should look to the subclasses.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class FlowException : public TobyException
+{
+public:
+    // !!! public final static int LINENUM_UNDEFINED = -1;
+
+        // !!! These should be pooled...
+    virtual ~FlowException(void)
+    {
+        if (procName != NULL)
+            delete procName;
+    } // Destructor
+
+
+    const char *getProcName(void)
+    {
+        return(procName->c_str());
+    } // FlowException::getProcName
+
+
+    int getSourceLine(void)
+    {
+        return(exceptionLine);
+    } // FlowException::getSourceLine
+
+
+protected:
+    // no public construction.
+    FlowException(void) : TobyException(),
+            procName(new TobyString()), exceptionLine(LINENUM_UNDEFINED)
+    {
+    } // Constructor
+
+
+    FlowException(char *_msg) : TobyException(_msg),
+            procName(new TobyString()), exceptionLine(LINENUM_UNDEFINED)
+    {
+    } // Constructor
+
+
+    static void initThrow(FlowException *e, const char *err,
+                           const char *pName, int lineNum)
+    {
+        e->msg->assignCStr(err);
+        e->procName->assignCStr(pName);
+        e->exceptionLine = lineNum;
+    } // FlowException::initThrow (overloaded; the works.)
+
+
+    static void initThrow(FlowException *e, const char *err, const char *pName)
+    {
+        initThrow(e, err, pName, LINENUM_UNDEFINED);
+    } // FlowException::initThrow (overloaded; no line number.)
+
+
+    static void initThrow(FlowException *e, const char *err, int lineNum)
+    {
+        initThrow(e, err, NULL, lineNum);
+    } // FlowException::initThrow (overloaded; just line number.)
+
+
+    static void initThrow(FlowException *e, const char *err)
+    {
+        initThrow(e, err, NULL, LINENUM_UNDEFINED);
+    } // FlowException::initThrow (overloaded; no line number or procedure.)
+
+private:
+    TobyString *procName;
+    int exceptionLine;
+}; // class FlowException
+
+#endif  // !defined _INCLUDE_FLOWEXCEPTION_H_
+
+// end of FlowException.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/HaltException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,82 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_HALTEXCEPTION_H_
+#define _INCLUDE_HALTEXCEPTION_H_
+
+#include "exceptions/FlowException.h"
+
+
+/*
+ *  HaltExceptions are thrown when the user requests an early end to
+ *   interpretation by hitting ESC or selecting the "STOP" menu item
+ *   or whatnot. This allows for clean termination of the interpreter at
+ *   any time.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class HaltException : public FlowException
+{
+public:
+    static HaltException *getInstance(void)
+    {
+        return(new HaltException());  // !!!
+    } // HaltException::getInstance
+
+    static void _throw(const char *err, const char *p, int l)
+                                                throw (HaltException *)
+    {
+        HaltException *e = getInstance();
+        initThrow(e, err, p, l);
+        throw(e);
+    } // HaltException::_throw
+
+    static void _throw(const char *err, const char *pName)
+                                                throw (HaltException *)
+    {
+        HaltException *e = getInstance();
+        initThrow(e, err, pName);
+        throw(e);
+    } // HaltException::_throw
+
+    static void _throw(const char *err, int lineNum) throw (HaltException *)
+    {
+        HaltException *e = getInstance();
+        initThrow(e, err, lineNum);
+        throw(e);
+    } // HaltException::_throw
+
+    static void _throw(const char *err) throw (HaltException *)
+    {
+        HaltException *e = getInstance();
+        initThrow(e, err);
+        throw(e);
+    } // HaltException::_throw
+
+private:
+    // no public construction.
+    HaltException(void) : FlowException() {}
+    HaltException(char *_msg) : FlowException(_msg) {}
+}; // class HaltException
+
+#endif  // !defined _INCLUDE_HALTEXCEPTION_H_
+
+// end of HaltException.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/IOException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,42 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_IOEXCEPTION_H_
+#define _INCLUDE_IOEXCEPTION_H_
+
+#include "exceptions/TobyException.h"
+
+
+/*
+ *  IOExceptions are thrown when reading from or writing to something (disk,
+ *   network, etc) fails or encounters an unusual situation..
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class IOException : public TobyException
+{
+public:
+    IOException(char *_msg) : TobyException(_msg) {}
+    IOException(void) : TobyException() {}
+}; // class IOException
+
+#endif  // !defined _INCLUDE_IOEXCEPTION_H_
+
+// end of IOException.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/ParseException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,82 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_PARSEEXCEPTION_H_
+#define _INCLUDE_PARSEEXCEPTION_H_
+
+#include "exceptions/FlowException.h"
+
+
+/*
+ *  ParseExceptions are thrown when there is a syntax error or some other
+ *   incorrect language construct is encountered at parse time. This
+ *   exception is also used to signal an unresolved symbol during the "link"
+ *   stage.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class ParseException : public FlowException
+{
+public:
+    static ParseException *getInstance(void)
+    {
+        return(new ParseException());  // !!!
+    } // ParseException::getInstance
+
+    static void _throw(const char *err, const char *p, int l)
+                                                throw (ParseException *)
+    {
+        ParseException *e = getInstance();
+        initThrow(e, err, p, l);
+        throw(e);
+    } // ParseException::_throw
+
+    static void _throw(const char *err, const char *pName)
+                                                throw (ParseException *)
+    {
+        ParseException *e = getInstance();
+        initThrow(e, err, pName);
+        throw(e);
+    } // ParseException::_throw
+
+    static void _throw(const char *err, int lineNum) throw (ParseException *)
+    {
+        ParseException *e = getInstance();
+        initThrow(e, err, lineNum);
+        throw(e);
+    } // ParseException::_throw
+
+    static void _throw(const char *err) throw (ParseException *)
+    {
+        ParseException *e = getInstance();
+        initThrow(e, err);
+        throw(e);
+    } // ParseException::_throw
+
+private:
+    // no public construction.
+    ParseException(void) : FlowException() {}
+    ParseException(char *_msg) : FlowException(_msg) {}
+}; // class ParseException
+
+#endif  // !defined _INCLUDE_PARSEEXCEPTION_H_
+
+// end of ParseException.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/ReturnException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,65 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_RETURNEXCEPTION_H_
+#define _INCLUDE_RETURNEXCEPTION_H_
+
+#include "exceptions/FlowException.h"
+
+
+/*
+ *  ReturnExceptions are used to break the logic flow when a RETURN statement
+ *   is hit. FunctionLogicContexts explicitly listen for this and pass control
+ *   back to their parent contexts when such an exception is caught.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class ReturnException : public FlowException
+{
+public:
+    static ReturnException *getInstance(void)
+    {
+        return(new ReturnException());  // !!!
+    } // ReturnException::getInstance
+
+    public TobyObject *getReturnValue(void)
+    {
+        return(returnValue);
+    } // ReturnException::getReturnValue
+
+    static void _throw(TobyObject *value) throw (ReturnException *)
+    {
+        ReturnException *e = getInstance();
+        e->returnValue = value;
+        initThrow(e, "");
+        throw(e);
+    } // ReturnException::_throw
+
+private:
+    // no public construction.
+    ReturnException(void) : FlowException(), returnValue(NULL) {}
+    ReturnException(char *_msg) : FlowException(_msg), returnValue(NULL) {}
+    TobyObject *returnValue;
+}; // class ReturnException
+
+#endif  // !defined _INCLUDE_RETURNEXCEPTION_H_
+
+// end of ReturnException.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/exceptions/TobyException.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,56 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYEXCEPTION_H_
+#define _INCLUDE_TOBYEXCEPTION_H_
+
+#include "util/TobyObject.h"
+#include "util/TobyString.h"
+
+/*
+ *  ExecExceptions are for interpretation errors at runtime, as opposed to
+ *   parsetime errors.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyException : public TobyObject
+{
+public:
+    TobyException(char *_msg) : msg(new TobyString(_msg)) {}
+    TobyException(void) : msg(new TobyString("")) {}
+
+    virtual ~TobyException(void)
+    {
+        if (msg != NULL)
+            delete msg;
+    } // Destructor
+
+    const char *getMessage(void)
+    {
+        return(msg->c_str());
+    } // TobyException::getMessage
+
+protected:
+    TobyString *msg;
+}; // class TobyException
+
+#endif  // !defined TobyException
+
+// end of TobyException.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/i18n/example.tobylang	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,235 @@
+#
+# This text written by Ryan C. Gordon.
+#
+# If you are translating to a new language, do this:
+#
+#  1. Ask yourself, "Do I have a good enough grasp of Java and Toby to
+#     understand this file, and what its purpose is? Do I have sufficient
+#     translating skills? Do I have the ethics to NOT put naughty words that
+#     the Toby maintainers will not understand in here?" If you answered
+#     "no" to any of these questions, stop now.
+#  2. Change the "This text written by" line above to contain your
+#     name. DO NOT CHANGE THE COPYRIGHT. You will be given credit for your
+#     work, but by submitting your work, the maintainers of Toby gain
+#     sole ownership of it. If you don't like that, stop now.
+#  3. E-mail your completed work to Ryan at icculus@lokigames.com. He'll
+#     incorporate it into the next release of Toby.
+#  4. Lines beginning with '#' are ignored when this file is parsed.
+#     Lines with nothing but whitespace are also ignored.
+#  5. Only translate the text after the equal sign on each line. That is,
+#     a line that reads: "last.toby.util.TobyLanguage.MENUNAME_FILE   = File"
+#     You would translate "File", and not "last.toby.util..."
+#  6. Whitespace is trimmed from each side of the translated string at runtime.
+#  7. Sometimes strings need dynamic content. For example, there might be
+#     a string that needs to convey, "error in "MyFunction" on line 15.",
+#     to accomodate this, such strings would have "%0" and "%1", with
+#     a description of what each represents. You may move the tokens to
+#     whatever order they need to be in; %1 can come before %0 if your
+#     language requires this, so long as all of those replacing tokens
+#     continue to exist somewhere in the translated string.
+#  8. Please try out your translation in the program to make sure that the
+#     program parses the langfile correctly, and that everything looks good.
+#  9. Expect to be notified if we have more translating work for you
+#     in the future.  :)
+# 10. Questions about context of strings and other concerns can be addressed
+#     to icculus@lokigames.com. Please understand that I only speak English,
+#     and even that poorly.  :)
+#
+#                                   Have fun,
+#                                      --ryan.
+#
+
+# These are printed if there are problems in loading this langfile.
+#  Therefore, it's best to parse these at the top of the file.
+#  What the % values are suppose to represent are pretty obvious.
+last.toby.util.TobyLanguage.LANGIOEXCEPT    = LANGUAGE: IOException reading language data.
+last.toby.util.TobyLanguage.LANGBOGUSLINE   = LANGUAGE: Line %0 is bogus in %1.
+last.toby.util.TobyLanguage.LANGNOSUCHCLASS = LANGUAGE: No such class [%0] on line %1 in %2.
+last.toby.util.TobyLanguage.LANGNOSUCHFIELD = LANGUAGE: No such field [%0] on line %1 in %2.
+last.toby.util.TobyLanguage.LANGNOTPUBLIC   = LANGUAGE: Field [%0] is not public on line %1 in %2.
+last.toby.util.TobyLanguage.LANGNOTSTATIC   = LANGUAGE: Field [%0] is not static on line %1 in %2.
+last.toby.util.TobyLanguage.LANGNOTSTRING   = LANGUAGE: Field [%0] is not a string on line %1 in %2.
+last.toby.util.TobyLanguage.LANGISFINAL     = LANGUAGE: Field [%0] is final on line %1 in %2.
+last.toby.util.TobyLanguage.LANGSETFAILED   = LANGUAGE: Setting field [%0] failed with message [%1] on line %2 in %3.
+
+
+# The usage/commandline information. Printed to stderr.
+last.toby.util.TobyLanguage.USAGE = USAGE: Toby.class [--langfile=xxx] [sourceFile.toby]
+
+
+# Please change this to be your name, and the language you translated to.
+last.toby.util.TobyLanguage.TRANSLATION_BY = English language text by Ryan C. Gordon.
+
+
+# Translate the text, but don't change my name.  :)
+last.toby.util.TobyLanguage.WRITTENBY = Written by Ryan C. Gordon.
+last.toby.util.TobyLanguage.COPYRIGHT = Copyright (C) 1999 Ryan C. Gordon
+
+
+# This is a string in a message box's title bar.
+last.toby.util.TobyLanguage.ERROR = Error
+
+
+# This is a title bar string of a Yes/No "overwrite this file?" message box.
+last.toby.util.TobyLanguage.FILE_EXISTS = File exists
+
+
+# This is the string in the title bar of a Yes/No message box.
+last.toby.util.TobyLanguage.PLEASE_CONFIRM = Please confirm
+
+
+# Question in a yes/no message box.
+last.toby.util.TobyLanguage.SAVE_MODIFIED_PROG = Save modified program?
+
+
+# This is shown in the main window's title bar before a program is saved.
+#  Once saved, this is replaced with the filename where the program is stored.
+last.toby.util.TobyLanguage.NEW_PROGRAM = new program
+
+
+# %0 is replaced with a filename at runtime in these strings...
+last.toby.util.TobyLanguage.FILE_NOT_FOUND = File "%0" not found.
+last.toby.util.TobyLanguage.CANNOT_LOAD_FILE = Cannot load file "%0".
+last.toby.util.TobyLanguage.OVERWRITE_FILENAME = Overwrite "%0"?
+last.toby.util.TobyLanguage.CANNOT_WRITE_TO = Cannot write to "%0".
+
+
+# These three are printed to stderr on three separate lines if there's
+#  a class loading problem. Try not to use more than 80 characters per string.
+last.toby.util.TobyLanguage.MISSING_CLASS1 = Cannot find a necessary .class file.
+last.toby.util.TobyLanguage.MISSING_CLASS2 = Perhaps you need to set your CLASSPATH?
+last.toby.util.TobyLanguage.MISSING_CLASS3 = Also, make sure you have JDK 1.2 or later!
+
+
+# These are three separate strings that make up one sentence:
+#  one string per line; try not to use more than 80 characters per string,
+#  as this is printed to stderr.
+last.toby.util.TobyLanguage.NO_GUI1 = Your Java Virtual Machine has thrown an error...chances are, you don't have
+last.toby.util.TobyLanguage.NO_GUI2 = the GUI support you need. Please start your Window system before running this
+last.toby.util.TobyLanguage.NO_GUI3 = program.
+
+
+# This is printed to stderr after the NO_GUI strings, and is followed by
+#  whatever information is attached to the thrown error.
+last.toby.util.TobyLanguage.HERES_THE_ERR = For record, here's the error:
+
+
+# Other warnings and errors...
+last.toby.util.TobyLanguage.MSG_BAD_JAVA = Your Java Virtual Machine is too old; goto http://java.sun.com/ ...
+last.toby.util.TobyLanguage.SETICON_BROKEN = WARNING: setIconImage() is broken on this Java Virtual Machine!
+last.toby.util.TobyLanguage.TOOMANYFILES = More than one file specified on commandline! Just using the first one.
+
+
+# This is printed to stderr when a warning can be worked around (currently,
+#  the only warning is the setIconImage(), above).
+last.toby.util.TobyLanguage.WORK_AROUND_IT = (We will work around it, though.)
+
+
+# Menu items.
+last.toby.util.TobyLanguage.MENUNAME_FILE   = File
+last.toby.util.TobyLanguage.MENUITEM_NEW    = New
+last.toby.util.TobyLanguage.MENUITEM_OPEN   = Open...
+last.toby.util.TobyLanguage.MENUITEM_SAVE   = Save
+last.toby.util.TobyLanguage.MENUITEM_SAVEAS = Save as...
+last.toby.util.TobyLanguage.MENUITEM_PRINT  = Print...
+last.toby.util.TobyLanguage.MENUITEM_QUIT   = Quit
+
+last.toby.util.TobyLanguage.MENUNAME_HELP  = Help
+last.toby.util.TobyLanguage.MENUITEM_HELP  = Help...
+last.toby.util.TobyLanguage.MENUITEM_ABOUT = About...
+
+last.toby.util.TobyLanguage.MENUNAME_RUN       = Run
+last.toby.util.TobyLanguage.MENUITEM_STARTCODE = Start program
+last.toby.util.TobyLanguage.MENUITEM_STOPCODE  = Stop program
+last.toby.util.TobyLanguage.MENUITEM_CLEAR     = Cleanup TurtleSpace
+
+last.toby.util.TobyLanguage.MENUNAME_DEBUG     = Debug
+last.toby.util.TobyLanguage.MENUITEM_TRACE     = Trace
+last.toby.util.TobyLanguage.MENUITEM_STEP      = Step
+last.toby.util.TobyLanguage.MENUITEM_WATCHVARS = Watch variables
+
+
+# This is a file description for the file open dialog, and shows up in
+#  the dropdown for "show files of type" ...
+last.toby.util.TobyLanguage.TOBY_FILE_DESCRIPTION = TOBY source code
+
+
+# This is the current position of the text cursor in the editing window.
+#  %0 and %1 are replaced with numbers at runtime.
+last.toby.util.TobyLanguage.CARET_POSITION = line %0, column %1
+
+
+# %0 is another string (probably one of the ones below), that tells what
+#  sort of error occurred, such as "Syntax error."
+# %1 is a numeric. %2 is the name of a function in the user's Toby program.
+last.toby.util.TobyLanguage.ERR_IN_FUNC = %0 on line %1 in function %2
+
+
+# Same as above, but the error didn't occur inside a function.
+last.toby.util.TobyLanguage.ERR_OUT_FUNC = %0 on line %1
+
+
+
+# Error messages.
+#
+#  Please note that the capitalized words are keywords
+#  in the Toby language, and should not be translated.
+#  (unless you are also translating the keywords in
+#   in last.toby.parsers.toby.TobyParser, too, but those
+#   changes will not be accepted in an official Toby
+#   distribution.)
+last.toby.util.TobyLanguage.INTERNAL_ERROR  = Internal error
+last.toby.util.TobyLanguage.EXPECTED_TOKEN  = Expected token
+last.toby.util.TobyLanguage.SYNTAX_ERROR    = Syntax error
+last.toby.util.TobyLanguage.BAD_ASSIGNMENT  = Assignment not allowed
+last.toby.util.TobyLanguage.DOUBLE_DEF      = Duplicate definition
+last.toby.util.TobyLanguage.ORPHAN_CODE     = Code outside function
+last.toby.util.TobyLanguage.BAD_TYPE        = Bad variable type
+last.toby.util.TobyLanguage.NOT_VAR         = Expected variable
+last.toby.util.TobyLanguage.NO_MAINLINE     = Expected mainline
+last.toby.util.TobyLanguage.NO_RPAREN       = Expected ")"
+last.toby.util.TobyLanguage.NO_LPAREN       = Expected "("
+last.toby.util.TobyLanguage.NO_ASSIGN       = Expected "="
+last.toby.util.TobyLanguage.NOT_A_FUNC      = Undefined function
+last.toby.util.TobyLanguage.BADNUM_ARGS     = Wrong arguments
+last.toby.util.TobyLanguage.BAD_IDENT       = Invalid identifier
+last.toby.util.TobyLanguage.NO_ENDFOR       = FOR without ENDFOR
+last.toby.util.TobyLanguage.NO_FOR          = ENDFOR without FOR
+last.toby.util.TobyLanguage.NO_ENDWHILE     = WHILE without ENDWHILE
+last.toby.util.TobyLanguage.NO_WHILE        = ENDWHILE without WHILE
+last.toby.util.TobyLanguage.ORPHAN_ELIF     = ELSEIF without IF
+last.toby.util.TobyLanguage.ORPHAN_ELSE     = ELSE without IF
+last.toby.util.TobyLanguage.ORPHAN_ENDIF    = ENDIF without IF
+last.toby.util.TobyLanguage.TYPE_MMATCH     = Type mismatch
+last.toby.util.TobyLanguage.BAD_ARGUMENT    = Invalid argument
+last.toby.util.TobyLanguage.MAIN_RETVAL     = MAIN returns a value
+last.toby.util.TobyLanguage.BAD_GLOBAL      = Expected variable or FUNCTION
+last.toby.util.TobyLanguage.EXPECTED_END    = Expected ENDFUNCTION
+last.toby.util.TobyLanguage.NO_RETTYPE      = Expected RETURNS
+last.toby.util.TobyLanguage.ELIF_AFTER_ELSE = ELSEIF after ELSE
+last.toby.util.TobyLanguage.ELSE_AFTER_ELSE = Multiple ELSE statements
+last.toby.util.TobyLanguage.NO_VAR_DECL     = Can't declare variables here
+last.toby.util.TobyLanguage.FUNC_IN_FUNC    = FUNCTION within function
+last.toby.util.TobyLanguage.DIV_BY_ZERO     = Division by zero
+last.toby.util.TobyLanguage.NOCURTURTLE     = No current turtle
+last.toby.util.TobyLanguage.TURTLE_FENCED   = Turtle past fence
+last.toby.util.TobyLanguage.OUT_OF_RANGE    = Out of range
+last.toby.util.TobyLanguage.OVERFLOW        = Overflow
+last.toby.util.TobyLanguage.NOT_AN_ARRAY    = Expected array
+last.toby.util.TobyLanguage.NO_RARRAY       = Expected "]"
+last.toby.util.TobyLanguage.NO_LARRAY       = Expected "["
+last.toby.util.TobyLanguage.NOT_WHOLE_NUM   = Expected whole number
+
+
+# This is an internal error alert message.
+last.toby.util.TobyLanguage.SHOULDNOTBE = This should not happen. Email icculus@lokigames.com! (English only!)
+
+
+# Other stuff.
+last.toby.util.TobyLanguage.NOT_YET_IMPLEMENTED = Feature not yet implemented.
+
+
+# end of example.tobylang ...
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/i18n/french.tobylang	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,239 @@
+#
+# This text written by Ryan C. Gordon.
+#
+# If you are translating to a new language, do this:
+#
+#  1. Ask yourself, "Do I have a good enough grasp of Java and Toby to
+#     understand this file, and what its purpose is? Do I have sufficient
+#     translating skills? Do I have the ethics to NOT put naughty words that
+#     the Toby maintainers will not understand in here?" If you answered
+#     "no" to any of these questions, stop now.
+#  2. Change the "This text written by" line above to contain your
+#     name. DO NOT CHANGE THE COPYRIGHT. You will be given credit for your
+#     work, but by submitting your work, the maintainers of Toby gain
+#     sole ownership of it. If you don't like that, stop now.
+#  3. E-mail your completed work to Ryan at icculus@lokigames.com. He'll
+#     incorporate it into the next release of Toby.
+#  4. Lines beginning with '#' are ignored when this file is parsed.
+#     Lines with nothing but whitespace are also ignored.
+#  5. Only translate the text after the equal sign on each line. That is,
+#     a line that reads: "last.toby.util.TobyLanguage.MENUNAME_FILE   = File"
+#     You would translate "File", and not "last.toby.util..."
+#  6. Whitespace is trimmed from each side of the translated string at runtime.
+#  7. Sometimes strings need dynamic content. For example, there might be
+#     a string that needs to convey, "error in "MyFunction" on line 15.",
+#     to accomodate this, such strings would have "%0" and "%1", with
+#     a description of what each represents. You may move the tokens to
+#     whatever order they need to be in; %1 can come before %0 if your
+#     language requires this, so long as all of those replacing tokens
+#     continue to exist somewhere in the translated string.
+#  8. Please try out your translation in the program to make sure that the
+#     program parses the langfile correctly, and that everything looks good.
+#  9. Expect to be notified if we have more translating work for you
+#     in the future.  :)
+# 10. Questions about context of strings and other concerns can be addressed
+#     to icculus@lokigames.com. Please understand that I only speak English,
+#     and even that poorly.  :)
+#
+#                                   Have fun,
+#                                      --ryan.
+#
+
+# These are printed if there are problems in loading this langfile.
+#  Therefore, it's best to parse these at the top of the file.
+#  What the % values are suppose to represent are pretty obvious.
+last.toby.util.TobyLanguage.LANGIOEXCEPT    = LANGUAGE: IOException pendant lecture des données linguistiques.
+last.toby.util.TobyLanguage.LANGBOGUSLINE   = LANGUAGE: Ligne %0 est fausse à partir de colonne %1.
+last.toby.util.TobyLanguage.LANGNOSUCHCLASS = LANGUAGE: Classe: [%0]inexistante à la ligne %1 colonne %2.
+last.toby.util.TobyLanguage.LANGNOSUCHFIELD = LANGUAGE: Pas de champ [%0] à la ligne %1 colnone  %2.
+last.toby.util.TobyLanguage.LANGNOTPUBLIC   = LANGUAGE: Champ [%0] n'est pas publique à la ligne  %1 colonne %2.
+last.toby.util.TobyLanguage.LANGNOTSTATIC   = LANGUAGE: Champ [%0] n'est pas statique à la ligne %1 colonne %2.
+last.toby.util.TobyLanguage.LANGNOTSTRING   = LANGUAGE: Champ [%0] n'est pas une chaine à la ligne %1 colonne %2.
+last.toby.util.TobyLanguage.LANGISFINAL     = LANGUAGE: Champ [%0] est final à la ligne %1 colonne %2.
+last.toby.util.TobyLanguage.LANGSETFAILED   = LANGUAGE: Erreur assignation champ [%0] avec message [%1] à la ligne %2 colonne %3.
+
+
+# The usage/commandline information. Printed to stderr.
+last.toby.util.TobyLanguage.USAGE = USAGE: Toby.class [--langfile=xxx] [sourceFile.toby]
+
+
+# Please change this to be your name, and the language you translated to.
+last.toby.util.TobyLanguage.TRANSLATION_BY = English language text by Ryan C. Gordon.
+
+
+# Translate the text, but don't change my name.  :)
+last.toby.util.TobyLanguage.WRITTENBY = Written by Ryan C. Gordon.
+last.toby.util.TobyLanguage.COPYRIGHT = Copyright (C) 1999 Ryan C. Gordon
+
+
+# This is a string in a message box's title bar.
+last.toby.util.TobyLanguage.ERROR = Erreur
+
+
+# This is a title bar string of a Yes/No "overwrite this file?" message box.
+last.toby.util.TobyLanguage.FILE_EXISTS = Fichier existe
+
+
+# This is the string in the title bar of a Yes/No message box.
+last.toby.util.TobyLanguage.PLEASE_CONFIRM = Confirmez SVP
+
+
+# Question in a yes/no message box.
+last.toby.util.TobyLanguage.SAVE_MODIFIED_PROG = Sauver programme modifié?
+
+
+# This is shown in the main window's title bar before a program is saved.
+#  Once saved, this is replaced with the filename where the program is stored.
+last.toby.util.TobyLanguage.NEW_PROGRAM = nouveau programme
+
+
+# %0 is replaced with a filename at runtime in these strings...
+last.toby.util.TobyLanguage.FILE_NOT_FOUND = Fichier "%0" non trouvé.
+last.toby.util.TobyLanguage.CANNOT_LOAD_FILE = Ne peut charger fichier "%0".
+last.toby.util.TobyLanguage.OVERWRITE_FILENAME = Ecraser "%0"?
+last.toby.util.TobyLanguage.CANNOT_WRITE_TO = Ne peux écrire vers "%0".
+
+
+# These three are printed to stderr on three separate lines if there's
+#  a class loading problem. Try not to use more than 80 characters per string.
+last.toby.util.TobyLanguage.MISSING_CLASS1 = Ne peut pas trouver un fichier .class nécessaire.
+last.toby.util.TobyLanguage.MISSING_CLASS2 = Vérifier la valeur de CLASSPATH?
+last.toby.util.TobyLanguage.MISSING_CLASS3 = Vérifier la version JDK (>=JDK1.2) !
+
+
+# These are three separate strings that make up one sentence:
+#  one string per line; try not to use more than 80 characters per string,
+#  as this is printed to stderr.
+last.toby.util.TobyLanguage.NO_GUI1 = Votre machine virtuelle Java à lancé une exception...peut être n'avez vous pas
+last.toby.util.TobyLanguage.NO_GUI2 = le support graphique nécessaire. Démarrer votre système de fenêtre avant de démarrer
+last.toby.util.TobyLanguage.NO_GUI3 = ce programme.
+
+
+# This is printed to stderr after the NO_GUI strings, and is followed by
+#  whatever information is attached to the thrown error.
+last.toby.util.TobyLanguage.HERES_THE_ERR = Pour mémoire, voici l'erreur:
+
+
+# Other warnings and errors...
+last.toby.util.TobyLanguage.MSG_BAD_JAVA = Votre machine virtuelle Java est trop ancienne; aller à http://java.sun.com/ ...
+last.toby.util.TobyLanguage.SETICON_BROKEN = ATTENTION: setIconImage() ne fonctionne pas sur cette machine virtuelle Java!
+last.toby.util.TobyLanguage.TOOMANYFILES = Plusieurs fichiers spécifiés sur la ligne de commande! Utilise seulement le premier.
+
+
+# This is printed to stderr when a warning can be worked around (currently,
+#  the only warning is the setIconImage(), above).
+last.toby.util.TobyLanguage.WORK_AROUND_IT = (Nous continuons quand même.)
+
+
+# Menu items.
+last.toby.util.TobyLanguage.MENUNAME_FILE   = Fichier
+last.toby.util.TobyLanguage.MENUITEM_NEW    = Nouveau
+last.toby.util.TobyLanguage.MENUITEM_OPEN   = Ouvrir...
+last.toby.util.TobyLanguage.MENUITEM_SAVE   = Sauver
+last.toby.util.TobyLanguage.MENUITEM_SAVEAS = Sauver sous...
+last.toby.util.TobyLanguage.MENUITEM_PRINT  = Imprimer...
+last.toby.util.TobyLanguage.MENUITEM_QUIT   = Quitter
+
+last.toby.util.TobyLanguage.MENUNAME_HELP  = Aide
+last.toby.util.TobyLanguage.MENUITEM_HELP  = Aide...
+last.toby.util.TobyLanguage.MENUITEM_ABOUT = A propos...
+
+last.toby.util.TobyLanguage.MENUNAME_RUN       = Action
+last.toby.util.TobyLanguage.MENUITEM_STARTCODE = Démarrer programme
+last.toby.util.TobyLanguage.MENUITEM_STOPCODE  = Arrêter programme
+last.toby.util.TobyLanguage.MENUITEM_CLEAR     = Effacer zone tortue
+
+last.toby.util.TobyLanguage.MENUNAME_DEBUG     = Mis au point
+last.toby.util.TobyLanguage.MENUITEM_TRACE     = Trace
+last.toby.util.TobyLanguage.MENUITEM_STEP      = Pas à pas
+last.toby.util.TobyLanguage.MENUITEM_WATCHVARS = Voir variables
+
+
+# This is a file description for the file open dialog, and shows up in
+#  the dropdown for "show files of type" ...
+last.toby.util.TobyLanguage.TOBY_FILE_DESCRIPTION = TOBY code source
+
+
+# This is the current position of the text cursor in the editing window.
+#  %0 and %1 are replaced with numbers at runtime.
+last.toby.util.TobyLanguage.CARET_POSITION = ligne %0, colonne %1
+
+
+# %0 is another string (probably one of the ones below), that tells what
+#  sort of error occurred, such as "Syntax error."
+# %1 is a numeric. %2 is the name of a function in the user's Toby program.
+last.toby.util.TobyLanguage.ERR_IN_FUNC = %0 à la ligne %1 dans la fonction %2
+
+
+# Same as above, but the error didn't occur inside a function.
+last.toby.util.TobyLanguage.ERR_OUT_FUNC = %0 à la ligne %1
+
+
+
+# Error messages.
+#
+#  Please note that the capitalized words are keywords
+#  in the Toby language, and should not be translated.
+#  (unless you are also translating the keywords in
+#   in last.toby.parsers.toby.TobyParser, too, but those
+#   changes will not be accepted in an official Toby
+#   distribution.)
+last.toby.util.TobyLanguage.INTERNAL_ERROR  = Erreur interne
+last.toby.util.TobyLanguage.EXPECTED_TOKEN  = Expected token
+last.toby.util.TobyLanguage.SYNTAX_ERROR    = Erreur de syntaxe
+last.toby.util.TobyLanguage.BAD_ASSIGNMENT  = Assignation non autorisée
+last.toby.util.TobyLanguage.DOUBLE_DEF      = Définition dupliquée
+last.toby.util.TobyLanguage.ORPHAN_CODE     = Code en dehors de fonction
+last.toby.util.TobyLanguage.BAD_TYPE        = Type de variable incorrect
+last.toby.util.TobyLanguage.NOT_VAR         = Variable attendue
+last.toby.util.TobyLanguage.NO_MAINLINE     = Point d'entrée du programme exigé
+last.toby.util.TobyLanguage.NO_RPAREN       = ")" attendu
+last.toby.util.TobyLanguage.NO_LPAREN       = "(" attendu
+last.toby.util.TobyLanguage.NO_ASSIGN       = "=" attendu
+last.toby.util.TobyLanguage.NOT_A_FUNC      = Fonction indéfinie
+last.toby.util.TobyLanguage.BADNUM_ARGS     = Arguments invalides
+last.toby.util.TobyLanguage.BAD_IDENT       = Identifiant invalide
+last.toby.util.TobyLanguage.NO_ENDFOR       = POUR sans FINPOUR
+last.toby.util.TobyLanguage.NO_FOR          = FINPOUR sans POUR
+last.toby.util.TobyLanguage.NO_ENDWHILE     = TANTQUE sans FINTANTQUE
+last.toby.util.TobyLanguage.NO_WHILE        = FINTANTQUE sans TANTQUE
+last.toby.util.TobyLanguage.ORPHAN_ELIF     = SINONSI sans SI
+last.toby.util.TobyLanguage.ORPHAN_ELSE     = SINON sans SI
+last.toby.util.TobyLanguage.ORPHAN_ENDIF    = FINSI sans SI
+last.toby.util.TobyLanguage.TYPE_MMATCH     = Confusion de type
+last.toby.util.TobyLanguage.BAD_ARGUMENT    = Argument invalide
+last.toby.util.TobyLanguage.MAIN_RETVAL     = PRINCIPAL retourne une valeur
+last.toby.util.TobyLanguage.BAD_GLOBAL      = Variable ou FONCTION attendue
+last.toby.util.TobyLanguage.EXPECTED_END    = FINFONCTION attendu
+last.toby.util.TobyLanguage.NO_RETTYPE      = RETOUR attendu
+last.toby.util.TobyLanguage.ELIF_AFTER_ELSE = SINONSI après SINON
+last.toby.util.TobyLanguage.ELSE_AFTER_ELSE = Multiples SINON 
+last.toby.util.TobyLanguage.NO_VAR_DECL     = Ne peut pas déclarer de variable ici
+last.toby.util.TobyLanguage.FUNC_IN_FUNC    = FONCTION dans fonction
+last.toby.util.TobyLanguage.DIV_BY_ZERO     = Division par zero
+last.toby.util.TobyLanguage.NOCURTURTLE     = Pas de tortue courante
+last.toby.util.TobyLanguage.TURTLE_FENCED   = Tortue a dépassé la barrière
+
+# !!! FIXME: Localize this text!
+last.toby.util.TobyLanguage.OUT_OF_RANGE    = Out of range
+last.toby.util.TobyLanguage.OVERFLOW        = Overflow
+last.toby.util.TobyLanguage.NOT_AN_ARRAY    = Expected array
+last.toby.util.TobyLanguage.NO_RARRAY       = Expected "]"
+last.toby.util.TobyLanguage.NO_LARRAY       = Expected "["
+last.toby.util.TobyLanguage.NOT_WHOLE_NUM   = Expected whole number
+
+
+
+# This is an internal error alert message.
+last.toby.util.TobyLanguage.SHOULDNOTBE = Ceci ne devrait pas arriver. Envoyer un Email à icculus@lokigames.com! (en Anglais seulement!)
+
+
+# Other stuff.
+last.toby.util.TobyLanguage.NOT_YET_IMPLEMENTED = Fonctionalité non implémentée.
+
+
+# end of example.tobylang ...
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/i18n/tobykeywords.tobylang	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,98 @@
+#
+# Don't change this unless you know what you are doing.
+#  Please refer to example.tobylang for basic instructions.
+#
+# EVERYTHING IN HERE MUST BE LOWERCASE, OR YOU WILL GET STRANGE RUNTIME
+#  ERRORS. The Toby language is case insensitive to the end user, but for
+#  efficiency, some of the data sorting internally expects these strings to
+#  be lowercase.
+#
+#    --ryan c. gordon (icculus@lokigames.com)
+#
+
+last.toby.parsers.toby.TobyParser.OPER_LPAREN     = (
+last.toby.parsers.toby.TobyParser.OPER_RPAREN     = )
+last.toby.parsers.toby.TobyParser.OPER_SEPARATOR  = ,
+last.toby.parsers.toby.TobyParser.OPER_ASSIGNMENT = =
+last.toby.parsers.toby.TobyParser.OPER_EQUALS     = ==
+last.toby.parsers.toby.TobyParser.OPER_MULTIPLY   = *
+last.toby.parsers.toby.TobyParser.OPER_DIVIDE     = /
+last.toby.parsers.toby.TobyParser.OPER_MODULO     = %
+last.toby.parsers.toby.TobyParser.OPER_ADD        = +
+last.toby.parsers.toby.TobyParser.OPER_SUBTRACT   = -
+last.toby.parsers.toby.TobyParser.OPER_GREATER    = >
+last.toby.parsers.toby.TobyParser.OPER_LESS       = <
+last.toby.parsers.toby.TobyParser.OPER_GREATEREQL = >=
+last.toby.parsers.toby.TobyParser.OPER_LESSEQL    = <=
+last.toby.parsers.toby.TobyParser.OPER_LARRAY     = [
+last.toby.parsers.toby.TobyParser.OPER_RARRAY     = ]
+last.toby.parsers.toby.TobyParser.KEYWORD_NUMBER  = number
+last.toby.parsers.toby.TobyParser.KEYWORD_BOOLEAN = boolean
+last.toby.parsers.toby.TobyParser.KEYWORD_NOTHING = nothing
+last.toby.parsers.toby.TobyParser.KEYWORD_ARRAY   = array
+last.toby.parsers.toby.TobyParser.KEYWORD_STRING  = string
+last.toby.parsers.toby.TobyParser.KEYWORD_IF          = if
+last.toby.parsers.toby.TobyParser.KEYWORD_ELSEIF      = elseif
+last.toby.parsers.toby.TobyParser.KEYWORD_ELSE        = else
+last.toby.parsers.toby.TobyParser.KEYWORD_ENDIF       = endif
+last.toby.parsers.toby.TobyParser.KEYWORD_BEGINFOR    = for
+last.toby.parsers.toby.TobyParser.KEYWORD_TO          = to
+last.toby.parsers.toby.TobyParser.KEYWORD_OF          = of
+last.toby.parsers.toby.TobyParser.KEYWORD_DOWNTO      = downto
+last.toby.parsers.toby.TobyParser.KEYWORD_STEP        = step
+last.toby.parsers.toby.TobyParser.KEYWORD_ENDFOR      = endfor
+last.toby.parsers.toby.TobyParser.KEYWORD_RETURN      = return
+last.toby.parsers.toby.TobyParser.KEYWORD_BEGINFUNC   = function
+last.toby.parsers.toby.TobyParser.KEYWORD_ENDFUNC     = endfunction
+last.toby.parsers.toby.TobyParser.KEYWORD_TRUE        = true
+last.toby.parsers.toby.TobyParser.KEYWORD_FALSE       = false
+last.toby.parsers.toby.TobyParser.KEYWORD_RETURNS     = returns
+last.toby.parsers.toby.TobyParser.KEYWORD_BEGINWHILE  = while
+last.toby.parsers.toby.TobyParser.KEYWORD_ENDWHILE    = endwhile
+last.toby.parsers.toby.TobyParser.KEYWORD_MAINLINE    = main
+last.toby.parsers.toby.TobyParser.PROCNAME_ADDTURTLE      = addturtle
+last.toby.parsers.toby.TobyParser.PROCNAME_USETURTLE      = useturtle
+last.toby.parsers.toby.TobyParser.PROCNAME_REMTURTLE      = removeturtle
+last.toby.parsers.toby.TobyParser.PROCNAME_REMALLTURTLES  = removeallturtles
+last.toby.parsers.toby.TobyParser.PROCNAME_HIDETURTLE     = hideturtle
+last.toby.parsers.toby.TobyParser.PROCNAME_SHOWTURTLE     = showturtle
+last.toby.parsers.toby.TobyParser.PROCNAME_HIDEALLTURTLES = hideallturtles
+last.toby.parsers.toby.TobyParser.PROCNAME_SHOWALLTURTLES = showallturtles
+last.toby.parsers.toby.TobyParser.PROCNAME_FORWARD        = goforward
+last.toby.parsers.toby.TobyParser.PROCNAME_BACKWARD       = gobackward
+last.toby.parsers.toby.TobyParser.PROCNAME_RIGHT          = turnright
+last.toby.parsers.toby.TobyParser.PROCNAME_LEFT           = turnleft
+last.toby.parsers.toby.TobyParser.PROCNAME_SETPEN         = setpencolor
+last.toby.parsers.toby.TobyParser.PROCNAME_SETPENRGB      = setpencolorrgb
+last.toby.parsers.toby.TobyParser.PROCNAME_PENUP          = setpenup
+last.toby.parsers.toby.TobyParser.PROCNAME_PENDOWN        = setpendown
+last.toby.parsers.toby.TobyParser.PROCNAME_ISPENUP        = ispenup
+last.toby.parsers.toby.TobyParser.PROCNAME_ISPENDOWN      = ispendown
+last.toby.parsers.toby.TobyParser.PROCNAME_RANDOM         = random
+last.toby.parsers.toby.TobyParser.PROCNAME_ROUND          = round
+last.toby.parsers.toby.TobyParser.PROCNAME_TSPACEHIGH     = getturtlespaceheight
+last.toby.parsers.toby.TobyParser.PROCNAME_TSPACEWIDE     = getturtlespacewidth
+last.toby.parsers.toby.TobyParser.PROCNAME_STOP           = stopprogram
+last.toby.parsers.toby.TobyParser.PROCNAME_SETANGLE       = setangle
+last.toby.parsers.toby.TobyParser.PROCNAME_GETANGLE       = getangle
+last.toby.parsers.toby.TobyParser.PROCNAME_PAUSE          = pause
+last.toby.parsers.toby.TobyParser.PROCNAME_GETTURTLEX     = getturtlex
+last.toby.parsers.toby.TobyParser.PROCNAME_GETTURTLEY     = getturtley
+last.toby.parsers.toby.TobyParser.PROCNAME_SETTURTXY      = setturtlexy
+last.toby.parsers.toby.TobyParser.PROCNAME_HOMETURTLE     = hometurtle
+last.toby.parsers.toby.TobyParser.PROCNAME_HOMEALLTURTLES = homeallturtles
+last.toby.parsers.toby.TobyParser.PROCNAME_CLEANUP        = cleanupturtlespace
+last.toby.parsers.toby.TobyParser.PROCNAME_ENABLEFENCE    = enablefence
+last.toby.parsers.toby.TobyParser.PROCNAME_DISABLEFENCE   = disablefence
+last.toby.parsers.toby.TobyParser.PROCNAME_SETFENCE       = setfence
+last.toby.parsers.toby.TobyParser.PROCNAME_SUBSTRING      = substring
+last.toby.parsers.toby.TobyParser.PROCNAME_LEFTSTRING     = leftstring
+last.toby.parsers.toby.TobyParser.PROCNAME_RIGHTSTRING    = rightstring
+last.toby.parsers.toby.TobyParser.PROCNAME_UCASESTRING    = uppercasestring
+last.toby.parsers.toby.TobyParser.PROCNAME_LCASESTRING    = lowercasestring
+last.toby.parsers.toby.TobyParser.PROCNAME_DRAWSTRING     = drawstring
+last.toby.parsers.toby.TobyParser.PROCNAME_STRINGLEN      = stringlength
+last.toby.parsers.toby.TobyParser.PROCNAME_JOINSTRINGS    = joinstrings
+
+# end of tobykeywords.tobylang ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,408 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.h"
+
+#include "SDL.h"  // !!!
+
+FrameBufferTurtleSpaceRenderer::FrameBufferTurtleSpaceRenderer(void)
+    : TurtleSpaceRenderer(), defaultSurface(NULL)
+{
+} // Constructor
+
+
+FrameBufferTurtleSpaceRenderer::~FrameBufferTurtleSpaceRenderer(void)
+{
+    deleteSurface();
+} // Destructor
+
+
+bool FrameBufferTurtleSpaceRenderer::resize(int _w, int _h)
+{
+    if (screenResize(_w, _h) == false)
+        return(false);
+
+    toby_uint32 *oldbuf = NULL;
+    toby_uint32 *p = getSurface();
+
+    // need an extra copy so we don't createSurface() twice in a row.
+    if (p != NULL)
+    {
+        oldbuf = new toby_uint32[w * h];
+        memcpy(oldbuf, p, (w * h) * sizeof (toby_uint32));
+        deleteSurface();
+    } // if
+
+    createSurface(_w, _h);
+    p = getSurface();
+    if (p == NULL)
+    {
+        if (oldbuf == NULL)
+            delete[] oldbuf;
+        return(false);
+    } // if
+
+    blankPixels(p, _w, _h);
+    if (oldbuf != NULL)
+    {
+        // !!! copy old framebuffer to new, centered.
+        delete[] oldbuf;
+    } // if
+
+    w = _w;
+    h = _h;
+    return(true);
+} // FrameBufferTurtleSpaceRenderer::resize
+
+
+void FrameBufferTurtleSpaceRenderer::notifyGrabbed(void)
+{
+} // FrameBufferTurtleSpaceRenderer::notifyGrabbed(void)
+
+
+void FrameBufferTurtleSpaceRenderer::notifyUngrabbed(void)
+{
+} // FrameBufferTurtleSpaceRenderer::notifyUngrabbed
+
+
+void FrameBufferTurtleSpaceRenderer::blankPixels(toby_uint32 *p, int _w, int _h)
+{
+        // !!! This could optimize, I bet.
+    int max = _w * _h;
+    for (int i = 0; i < max; i++)
+        p[i] = 0xFF000000;  // Full alpha, no red or green or blue.
+} // FrameBufferTurtleSpaceRenderer::blankPixels
+
+
+double FrameBufferTurtleSpaceRenderer::getTurtleSpaceWidth(void)
+{
+    return(w);
+} // FrameBufferTurtleSpaceRenderer::getTurtleSpaceWidth
+
+
+double FrameBufferTurtleSpaceRenderer::getTurtleSpaceHeight(void)
+{
+    return(h);
+} // FrameBufferTurtleSpaceRenderer::getTurtleSpaceHeight
+
+
+double FrameBufferTurtleSpaceRenderer::getDesiredTurtleWidth(void)
+{
+    return(w * 0.02);
+} // FrameBufferTurtleSpaceRenderer::getDesiredTurtleWidth
+
+
+double FrameBufferTurtleSpaceRenderer::getDesiredTurtleHeight(void)
+{
+    return(getDesiredTurtleWidth());
+} // FrameBufferTurtleSpaceRenderer::getDesiredTurtleHeight
+
+
+void FrameBufferTurtleSpaceRenderer::renderString(double x, double y,
+                                                  double angle,
+                                                  float r, float b,
+                                                  float g, float a,
+                                                    const char *str)
+{
+} // FrameBufferTurtleSpaceRenderer::renderString
+
+
+#define LINEBLITCHUNKS 10
+
+void FrameBufferTurtleSpaceRenderer::renderLine(double _x1, double _y1,
+                                                double _x2, double _y2,
+                                                float r, float b,
+                                                float g, float a)
+{
+    // This is a standard Bresenham line-drawing algorithm, but the specific
+    //  implementation was borrowed, optimized, and mangled from
+    //  SGE's DoLine code:
+    //   http://www.etek.chalmers.se/~e8cal1/sge/
+
+    toby_uint32 pval = constructPixelValue(r, g, b, a);
+    int x1 = TobyGeometry::roundDoubleToInt(_x1);
+    int y1 = TobyGeometry::roundDoubleToInt(_y1);
+    int x2 = TobyGeometry::roundDoubleToInt(_x2);
+    int y2 = TobyGeometry::roundDoubleToInt(_y2);
+
+    FrameBufferRect rects[LINEBLITCHUNKS];
+    toby_uint32 *p = getSurface();
+
+    _D(("LFB: rendering line...(%d, %d)-(%d, %d), (%f, %f, %f, %f)...\n",
+        x1, y1, x2, y2, r, g, b, a));
+
+	int dx, dy, sdx, sdy, x, y, px, py, incr;
+
+    dx = x2 - x1;
+    dy = y2 - y1;
+
+    sdx = (dx < 0) ? -1 : 1;
+    sdy = (dy < 0) ? -1 : 1;
+
+    dx = sdx * dx + 1;
+    dy = sdy * dy + 1;
+
+    x = y = 0;
+
+    px = x1;
+    py = y1;
+
+    if ((dx == 1) && (dy == 1))
+    {
+        _D(("LFB: Single pixel line fastpath.\n"));
+        *(((toby_uint32 *) p) + ((py * w) + px)) = pval;
+        putToScreen(p, px, py, 1, 1);
+        return;
+    } // if
+
+    else if (dx == 1)
+    {
+        _D(("LFB: Vertical line fastpath.\n"));
+        toby_uint32 *linep = ((toby_uint32 *) p) + ((py * w) + px);
+        incr = w * sdy;
+        for (y = 0; y < dy; y++)
+        {
+            *linep = pval;
+            linep += incr;
+        } // for
+        putToScreen(p, (x1 < x2) ? x1 : x2, (y1 < y2) ? y1 : y2, 1, dy);
+        return;
+    } // else if
+
+    else if (dy == 1)
+    {
+        _D(("LFB: Horizontal line fastpath.\n"));
+        toby_uint32 *linep = ((toby_uint32 *) p) + ((py * w) + px);
+        incr = sdx;
+        for (x = 0; x < dx; x++)
+        {
+            *linep = pval;
+            linep += incr;
+        } // for
+        putToScreen(p, (x1 < x2) ? x1 : x2, (y1 < y2) ? y1 : y2, dx, 1);
+        return;
+    } // else if
+
+    else if (dx >= dy)
+    {
+        _D(("LFB: Line with major axis of X.\n"));
+
+        int lastX = px;
+        int thisY = py;
+        int rectidx = 0;
+
+        for (x = 0; x < dx; x++)
+        {
+            *( ((toby_uint32 *) p) + ((py * w) + px) ) = pval;
+
+            y += dy;
+            if (y >= dx)   // run length completed.
+            {
+                if (rectidx != -1)
+                {
+                    rects[rectidx].x = (lastX < px) ? lastX : px;
+                    rects[rectidx].y = thisY;
+                    rects[rectidx].w = (px - lastX) * sdx;
+                    rects[rectidx].h = 1;
+
+                    rectidx++;
+                    if (rectidx >= LINEBLITCHUNKS)
+                        rectidx = -1;
+                } // if
+
+                y -= dx;
+                py += sdy;
+
+                lastX = px;
+                thisY = py;
+            } // if
+            px += sdx;
+        } // for
+
+        if (rectidx != -1)
+            putMultToScreen(p, rectidx, rects);
+        else
+            goto tobylfb_blit_slanted_line;
+
+        return;
+    } // else if
+
+    else
+    {
+        _D(("LFB: Line with major axis of Y.\n"));
+
+        int lastY = py;
+        int thisX = px;
+        int rectidx = 0;
+
+        for (y = 0; y < dy; y++)
+        {
+            *( ((toby_uint32 *) p) + ((py * w) + px) ) = pval;
+
+            x += dx;
+            if (x >= dy)  // run length completed.
+            {
+                if (rectidx != -1)
+                {
+                    rects[rectidx].x = thisX;
+                    rects[rectidx].y = (lastY < py) ? lastY : py;
+                    rects[rectidx].w = 1;
+                    rects[rectidx].h = (py - lastY) * sdy;
+
+                    rectidx++;
+                    if (rectidx >= LINEBLITCHUNKS)
+                        rectidx = -1;
+                } // if
+
+                x -= dy;
+                px += sdx;
+
+                lastY = py;
+                thisX = px;
+            } // if
+            py += sdy;
+        } // for
+
+        if (rectidx != -1)
+            putMultToScreen(p, rectidx, rects);
+        else
+            goto tobylfb_blit_slanted_line;
+
+        return;
+    } // else
+
+    assert(0);  // should have return'd or goto'd by here.
+
+tobylfb_blit_slanted_line:
+        // !!! This isn't rendering right in all cases.
+
+    float chunkX = ((float) dx) / ((float) LINEBLITCHUNKS);
+    float chunkY = ((float) dy) / ((float) LINEBLITCHUNKS);
+    float yincr;
+    float fx, fy;
+
+    fx = (float) ((x1 < x2) ? x1 : x2);
+
+    if ( ((sdx > 0) && (sdy > 0)) ||   // line from q1 to q4.
+         ((sdx < 0) && (sdy < 0)) )
+    {
+        fy = (float) ((y1 < y2) ? y1 : y2);
+        yincr = chunkY;
+    } // if
+
+    else   // line from q3 to q2.
+    {
+        fy = (float) (((y1 > y2) ? y1 : y2)) - chunkY;
+        yincr = -chunkY;
+    } // else
+
+    for (int i = 0; i < LINEBLITCHUNKS; i++)
+    {
+        rects[i].x = (int) (fx);
+        rects[i].y = (int) (fy);
+        rects[i].w = (int) (chunkX + 0.5);
+        rects[i].h = (int) (chunkY + 0.5);
+
+        if (rects[i].w == 0)
+            rects[i].w++;
+
+        if (rects[i].h == 0)
+            rects[i].h++;
+
+        fx += chunkX;
+        fy += yincr;
+    } // for
+
+    putMultToScreen(p, LINEBLITCHUNKS, rects);
+} // FrameBufferTurtleSpaceRenderer::renderLine
+
+
+void FrameBufferTurtleSpaceRenderer::renderTurtle(Turtle *turtle) throw (ExecException *)
+{
+    _D(("LFB: renderTurtle() called. NOT IMPLEMENTED.\n"));
+} // FrameBufferTurtleSpaceRenderer::renderTurtle
+
+
+void FrameBufferTurtleSpaceRenderer::blankTurtle(Turtle *turtle) throw (ExecException *)
+{
+    _D(("LFB: blankTurtle() called. NOT IMPLEMENTED.\n"));
+} // FrameBufferTurtleSpaceRenderer::blankTurtle
+
+
+void FrameBufferTurtleSpaceRenderer::cleanup(void) throw (ExecException *)
+{
+    blankPixels(getSurface(), w, h);
+} // FrameBufferTurtleSpaceRenderer::cleanup
+
+
+inline toby_uint32 FrameBufferTurtleSpaceRenderer::constructPixelValue(
+                                                                float r,
+                                                                float g,
+                                                                float b,
+                                                                float a)
+{
+        // !!! check this.
+    return(
+            (((int) (a * 255.0)) << 24) |
+            (((int) (r * 255.0)) << 16) |
+            (((int) (b * 255.0)) <<  8) |
+            (((int) (g * 255.0))      )
+          );
+
+#if 0
+        _D(("%f, %f, %f, %f == ", r, b, g, a));
+
+        for (unsigned int i = 1 << 31; i != 0; i >>= 1)
+            _D(("%d", (int) ((pval & i) / i)));
+
+        _D(("\n"));
+#endif
+
+} // FrameBufferTurtleSpaceRenderer::constructPixelValue
+
+
+void FrameBufferTurtleSpaceRenderer::createSurface(int _w, int _h)
+{
+    defaultSurface = new toby_uint32[_w * _h];
+} // FrameBufferTurtleSpaceRenderer::createSurface
+
+
+void FrameBufferTurtleSpaceRenderer::deleteSurface(void)
+{
+    if (defaultSurface != NULL)
+        delete[] defaultSurface;
+} // FrameBufferTurtleSpaceRenderer::deleteSurface
+
+
+toby_uint32 *FrameBufferTurtleSpaceRenderer::getSurface(void)
+{
+    return(defaultSurface);
+} // FrameBufferTurtleSpaceRenderer::getSurface
+
+
+void FrameBufferTurtleSpaceRenderer::putMultToScreen(toby_uint32 *pix,
+                                                     int rectCount,
+                                                     FrameBufferRect *rects)
+{
+    for (int i = 0; i < rectCount; i++)
+       putToScreen(pix, rects[i].x, rects[i].y, rects[i].w, rects[i].h);
+} // FrameBufferTurtleSpaceRenderer::putMultToScreen
+
+// end of FrameBufferTurtleSpaceRenderer.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,135 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_FRAMEBUFFERTURTLESPACERENDERER_H_
+#define _INCLUDE_FRAMEBUFFERTURTLESPACERENDERER_H_
+
+#include "turtlespace/TurtleSpaceRenderer.h"
+#include "util/TobyGeometry.h"
+
+
+typedef struct __STRUCT_FrameBufferRect
+{
+    int x;
+    int y;
+    int w;
+    int h;
+} FrameBufferRect;
+
+/*
+ * An implementation of TurtleSpaceRenderer that writes to a linear
+ *  framebuffer in memory. Internally, this framebuffer is 32-bits per
+ *  pixel: 8 bits each for red, green, blue, and alpha. Rendering into
+ *  this framebuffer is done within this class, which expects a subclass
+ *  to take responsibility for getting the bits to the screen. The subclass
+ *  is also responsible for converting the 32-bit format to their visual's
+ *  format, including alpha-blending.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class FrameBufferTurtleSpaceRenderer : public TurtleSpaceRenderer
+{
+public:
+    FrameBufferTurtleSpaceRenderer(void);
+    virtual ~FrameBufferTurtleSpaceRenderer(void);
+
+        // Do NOT override this. This base class will call screenResize(),
+        //  where you can perform your own setup.
+    virtual bool resize(int _w, int _h);
+
+        // Grab notifications are currently no-ops in this class, but if you
+        //  override them, please call the superclass's version first, just
+        //  in case.
+    virtual void notifyGrabbed(void);
+    virtual void notifyUngrabbed(void);
+
+        // These will probably not need overriding.
+    virtual double getTurtleSpaceWidth(void);
+    virtual double getTurtleSpaceHeight(void);
+    virtual double getDesiredTurtleWidth(void);
+    virtual double getDesiredTurtleHeight(void);
+    virtual void renderString(double x, double y, double angle,
+                                float r, float b, float g, float a,
+                                const char *str);
+    virtual void renderLine(double x1, double y1, double x2, double y2,
+                                float r, float b, float g, float a);
+    virtual void renderTurtle(Turtle *turtle) throw (ExecException *);
+    virtual void blankTurtle(Turtle *turtle) throw (ExecException *);
+    virtual void cleanup(void) throw (ExecException *);
+
+
+protected:
+
+        // This returns a 32-bit value based on four floats that represent
+        //  intensity of the color channels in the range of 0.0 to 1.0.
+    inline toby_uint32 constructPixelValue(float r, float g, float b, float a);
+
+        // Set the screen surface (the window, the fullscreen resolution,
+        //  whatever) to (_w) by (_h) pixels. Returns (true) if successful,
+        //  (false) otherwise. If this succeeds, this base class will then
+        //  attempt to build an offscreen surface (via createSurface()).
+        //  You must implement this.
+    virtual bool screenResize(int _w, int _h) = 0;
+
+        // Some toolkits can accelerate blits to the screen if they manage
+        //  their own offscreen memory surface. In such a case, this method
+        //  should be overridden to build a platform-specific surface. The
+        //  offscreen surface must be a linear framebuffer, 32-bits per pixel,
+        //  in format 0xAARRBBGG (Alpha, Red, Blue, Green). If not overridden,
+        //  this base class will allocate a block of memory for itself.
+    virtual void createSurface(int _w, int _h);
+
+        // Free resources allocated by createSurface(). The base class will
+        //  always call deleteSurface() before calling createSurface() again
+        //  (in case of resizing, etc). This, by default, cleans up an
+        //  internal buffer created by this base class. You must override
+        //  this if you overrode createSurface()!
+    virtual void deleteSurface(void);
+
+        // Get the offscreen surface's linear framebuffer. This, by default,
+        //  returns the memory buffer allocated by this base class. If
+        //  createSurface() could not build an offscreen surface, this method
+        //  should return NULL. You must override this if you overrode
+        //  createSurface()!
+    virtual toby_uint32 *getSurface(void);
+
+        // Take the framebuffer pointed to by (pix) and display the pixels
+        //  within the rectangle specified by (x), (y), (w), and (h).
+        // You must implement this!
+    virtual void putToScreen(toby_uint32 *pix, int x, int y, int w, int h) = 0;
+
+        // If your renderer can accelerate putting multiple rectangles to
+        //  the screen at the same time, then override this.
+        // The default implementation just calls putToScreen() on each
+        //  rectangle in the array.
+    virtual void putMultToScreen(toby_uint32 *pix, int rectCount,
+                                    FrameBufferRect *rects);
+
+private:
+    toby_uint32 *defaultSurface;
+    int w;
+    int h;
+
+    void blankPixels(toby_uint32 *p, int _w, int _h);
+}; // class FrameBufferTurtleSpaceRenderer
+
+#endif // !defined _INCLUDE_FRAMEBUFFERTURTLESPACERENDERER_H_
+
+// end of FrameBufferTurtleSpaceRenderer.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,313 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.h"
+
+
+// !!! make these into instance members!
+static volatile bool window_still_not_displayed = true;
+static volatile bool quit_event_caught = false;
+
+static gboolean on_gtkcanvas_expose(GtkWidget       *widget,
+                                    GdkEventExpose  *event,
+                                    gpointer         user_data)
+{
+    GTKTurtleSpaceRenderer *r = (GTKTurtleSpaceRenderer *) user_data;
+    assert(r != NULL);
+
+    gint _x = event->area.x;
+    gint _y = event->area.y;
+    gint _w = event->area.width;
+    gint _h = event->area.height;
+
+    GdkGC *_gc = gdk_gc_new(widget->window);
+    GdkPixmap *p = r->getOffscreenPixmap();
+    if (p == NULL)
+    {
+        gdk_rgb_gc_set_foreground(_gc, 0x000000);
+        gdk_draw_rectangle(widget->window, _gc, TRUE, _x, _y, _w, _h);
+    } // if
+    else
+    {
+        gdk_draw_pixmap(widget->window, _gc, p, _x, _y, _x, _y, _w, _h);
+    } // else
+
+    gdk_gc_unref(_gc);
+
+    window_still_not_displayed = false;
+
+    return(FALSE);
+} // on_gtkcanvas_expose
+
+
+GTKTurtleSpaceRenderer::GTKTurtleSpaceRenderer(void)
+    : gc(NULL), offscreen_pixmap(NULL),
+      canvas(gtk_drawing_area_new())
+{
+    gtk_widget_ref(canvas);
+    gdk_rgb_init();
+    gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
+    gtk_widget_set_default_visual(gdk_rgb_get_visual());
+
+    gtk_signal_connect(GTK_OBJECT(canvas), "expose_event",
+                        GTK_SIGNAL_FUNC(on_gtkcanvas_expose), this);
+} // Constructor
+
+
+GTKTurtleSpaceRenderer::~GTKTurtleSpaceRenderer(void)
+{
+    if (canvas != NULL)
+    {
+        gtk_widget_hide(canvas);
+        gtk_widget_unref(canvas);
+    } // if
+
+    if (offscreen_pixmap != NULL)
+    {
+        gdk_pixmap_unref(offscreen_pixmap);
+    } // if
+} // Destructor
+
+
+bool GTKTurtleSpaceRenderer::resize(int w, int h)
+{
+    _D(("GTK canvas resize: (%d, %d).\n", w, h));
+
+    if (canvas == NULL)
+        return(false);
+
+    GdkPixmap *pix = gdk_pixmap_new(canvas->window, w, h, -1);
+    if (pix == NULL)
+        return(false);
+
+    GtkStyle *_style = gtk_style_copy(gtk_widget_get_style(canvas));
+    memcpy(&(_style->bg[GTK_STATE_NORMAL]), &_style->black, sizeof (GdkColor));
+    gtk_widget_set_style(canvas, _style);
+
+    gtk_widget_set_usize(canvas, w, h);
+    gtk_widget_show(canvas);
+
+    GdkGC *_gc = gdk_gc_new(canvas->window);
+    gdk_rgb_gc_set_foreground(_gc, 0x00000000);
+    gdk_draw_rectangle(pix, _gc, TRUE, 0, 0, w, h);
+
+    if (offscreen_pixmap != NULL)
+    {
+        // !!! move old image to new pixmap. gdk_draw_pixmap(
+        gdk_pixmap_unref(offscreen_pixmap);
+    } // if
+
+    gdk_gc_unref(_gc);
+    offscreen_pixmap = pix;
+
+    while ((window_still_not_displayed) || (gtk_events_pending()))
+        gtk_main_iteration();
+
+    while ((canvas->allocation.width != w) || (canvas->allocation.height != h))
+        gtk_main_iteration();
+
+    return(true);
+} // GTKTurtleSpaceRenderer::resize
+
+
+void GTKTurtleSpaceRenderer::notifyGrabbed(void)
+{
+    gc = gdk_gc_new(canvas->window);
+    assert(gc != NULL);
+
+    while (gtk_events_pending())
+        gtk_main_iteration();
+} // GTKTurtleSpaceRenderer::notifyGrabbed
+
+
+void GTKTurtleSpaceRenderer::notifyUngrabbed(void)
+{
+    if (gc != NULL)
+    {
+        gdk_gc_destroy(gc);
+        gc = NULL;
+    } // if
+
+    while (gtk_events_pending())
+        gtk_main_iteration();
+} // GTKTurtleSpaceRenderer::notifyUngrabbed
+
+
+double GTKTurtleSpaceRenderer::getTurtleSpaceWidth(void)
+{
+    assert(canvas != NULL);
+    return((double) canvas->allocation.width);
+} // GTKTurtleSpaceRenderer::getTurtleSpaceWidth
+
+
+double GTKTurtleSpaceRenderer::getTurtleSpaceHeight(void)
+{
+    assert(canvas != NULL);
+    return((double) canvas->allocation.height);
+} // GTKTurtleSpaceRenderer::getTurtleSpaceHeight
+
+
+double GTKTurtleSpaceRenderer::getDesiredTurtleWidth(void)
+{
+    return(canvas->allocation.width * 0.02);
+} // GTKTurtleSpaceRenderer::getDesiredTurtleWidth
+
+
+double GTKTurtleSpaceRenderer::getDesiredTurtleHeight(void)
+{
+    return(canvas->allocation.height * 0.02);
+} // GTKTurtleSpaceRenderer::getDesiredTurtleHeight
+
+
+inline guint32 GTKTurtleSpaceRenderer::constructPixelValue(float r, float g,
+                                                           float b, float a)
+{
+        // !!! check this.
+    return(
+            //(((int) (a * 255.0)) << 24) |
+            (((int) (r * 255.0)) << 16) |
+            (((int) (b * 255.0)) <<  8) |
+            (((int) (g * 255.0))      )
+          );
+} // FrameBufferTurtleSpaceRenderer::constructPixelValue
+
+
+void GTKTurtleSpaceRenderer::renderString(double x, double y, double angle,
+                                          float r, float b, float g, float a,
+                                          const char *str)
+{
+} // GTKTurtleSpaceRenderer::renderString
+
+
+void GTKTurtleSpaceRenderer::renderLine(double _x1, double _y1,
+                                        double _x2, double _y2,
+                                        float r, float b,
+                                        float g, float a)
+{
+
+    assert(canvas != NULL);
+    assert(offscreen_pixmap != NULL);
+    assert(gc != NULL);
+
+    guint32 pval = constructPixelValue(r, g, b, a);
+
+    gdk_rgb_gc_set_foreground(gc, pval);
+
+    int x1 = TobyGeometry::roundDoubleToInt(_x1);
+    int y1 = TobyGeometry::roundDoubleToInt(_y1);
+    int x2 = TobyGeometry::roundDoubleToInt(_x2);
+    int y2 = TobyGeometry::roundDoubleToInt(_y2);
+
+    gdk_draw_line(offscreen_pixmap, gc, x1, y1, x2, y2);
+    gdk_draw_line(canvas->window, gc, x1, y1, x2, y2);
+} // GTKTurtleSpaceRenderer::renderLine
+
+
+void GTKTurtleSpaceRenderer::renderTurtle(Turtle *t) throw (ExecException *)
+{
+} // GTKTurtleSpaceRenderer::renderTurtle
+
+
+void GTKTurtleSpaceRenderer::blankTurtle(Turtle *t) throw (ExecException *)
+{
+} // GTKTurtleSpaceRenderer::blankTurtle
+
+
+void GTKTurtleSpaceRenderer::cleanup(void) throw (ExecException *)
+{
+    assert(canvas != NULL);
+    assert(gc != NULL);
+
+    gdk_rgb_gc_set_foreground(gc, 0x00000000);
+    gdk_draw_rectangle(canvas->window, gc, TRUE, 0, 0,
+                       canvas->allocation.width, canvas->allocation.height);
+
+    while (gtk_events_pending())
+        gtk_main_iteration();
+} // GTKTurtleSpaceRenderer::cleanup
+
+
+GtkWidget *GTKTurtleSpaceRenderer::getDrawingAreaWidget(void)
+{
+    return(canvas);
+} // GTKTurtleSpaceRenderer::getDrawingAreaWidget
+
+
+GdkPixmap *GTKTurtleSpaceRenderer::getOffscreenPixmap(void)
+{
+    return(offscreen_pixmap);
+} // GTKTurtleSpaceRenderer::getOffscreenPixmap
+
+
+static gint on_gtk_window_delete(GtkWidget *widget,
+                          GdkEvent  *event,
+                          gpointer   data )
+{
+    quit_event_caught = true;
+    return(FALSE);
+} // on_gtk_window_delete
+
+
+TurtleSpaceRenderer *__platformBuildStandaloneRenderer(char *winTitle,
+                                                       int *argc, char ***argv)
+{
+    window_still_not_displayed = true;
+    quit_event_caught = false;
+
+    gtk_init(argc, argv);
+
+    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    assert(window != NULL);
+
+        // prevent user from resizing window...
+    gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE);
+
+    gtk_window_set_title(GTK_WINDOW(window), winTitle);
+
+    GTKTurtleSpaceRenderer *retval = new GTKTurtleSpaceRenderer();
+    assert(retval != NULL);
+    GtkWidget *darea = retval->getDrawingAreaWidget();
+    assert(darea != NULL);
+
+    gtk_signal_connect(GTK_OBJECT(window), "delete_event",
+                        GTK_SIGNAL_FUNC(on_gtk_window_delete), darea);
+
+    gtk_widget_realize(window);
+    gtk_container_add(GTK_CONTAINER(window), darea);
+    gtk_widget_realize(darea);
+    gtk_widget_show(darea);
+    gtk_widget_show(window);
+
+    while (gtk_events_pending())
+        gtk_main_iteration();
+
+    return(retval);
+} // __platformBuildStandaloneRenderer
+
+
+bool __platformRendererDoEvents(void)
+{
+    while (gtk_events_pending())
+        gtk_main_iteration();
+
+    return(!quit_event_caught);
+} // __platformRendererDoEvents
+
+// end of GTKTurtleSpaceRenderer.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/gtkrenderer/GTKTurtleSpaceRenderer.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,72 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_GTKTURTLESPACERENDERER_H_
+#define _INCLUDE_GTKTURTLESPACERENDERER_H_
+
+#include <gtk/gtk.h>
+#include "turtlespace/TurtleSpaceRenderer.h"
+#include "util/TobyGeometry.h"
+
+/*
+ * A GTK+-based TurtleSpaceRenderer. GTK+ and related libraries can be
+ *  found at http://www.gtk.org/.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class GTKTurtleSpaceRenderer : public TurtleSpaceRenderer
+{
+public:
+    GTKTurtleSpaceRenderer(void);
+    virtual ~GTKTurtleSpaceRenderer(void);
+
+    virtual bool resize(int _w, int _h);
+    virtual void notifyGrabbed(void);
+    virtual void notifyUngrabbed(void);
+    virtual double getTurtleSpaceWidth(void);
+    virtual double getTurtleSpaceHeight(void);
+    virtual double getDesiredTurtleWidth(void);
+    virtual double getDesiredTurtleHeight(void);
+    virtual void renderString(double x, double y, double angle,
+                                float r, float b, float g, float a,
+                                const char *str);
+    virtual void renderLine(double x1, double y1, double x2, double y2,
+                                float r, float b, float g, float a);
+    virtual void renderTurtle(Turtle *turtle) throw (ExecException *);
+    virtual void blankTurtle(Turtle *turtle) throw (ExecException *);
+    virtual void cleanup(void) throw (ExecException *);
+
+    virtual GtkWidget *getDrawingAreaWidget(void);
+    virtual GdkPixmap *getOffscreenPixmap(void);
+
+protected:
+        // This returns a 32-bit value based on four floats that represent
+        //  intensity of the color channels in the range of 0.0 to 1.0.
+    inline guint32 constructPixelValue(float r, float g, float b, float a);
+
+private:
+    GdkGC *gc;
+    GdkPixmap *offscreen_pixmap;
+    GtkWidget *canvas;
+}; // class GTKTurtleSpaceRenderer
+
+#endif // !defined _INCLUDE_GTKTURTLESPACERENDERER_H_
+
+// end of GTKTurtleSpaceRenderer.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,145 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.h"
+
+
+SDLTurtleSpaceRenderer::SDLTurtleSpaceRenderer(Uint32 flags)
+    : FrameBufferTurtleSpaceRenderer(),
+      sdlflags(flags),
+      swsurface(NULL)
+{
+} // Constructor
+
+
+SDLTurtleSpaceRenderer::~SDLTurtleSpaceRenderer(void)
+{
+    deleteSurface();
+    SDL_QuitSubSystem(SDL_INIT_VIDEO);
+} // Destructor
+
+
+bool SDLTurtleSpaceRenderer::screenResize(int _w, int _h)
+{
+    if (SDL_Init(SDL_INIT_VIDEO) < 0)
+        return(false);
+
+    SDL_WM_SetCaption("Toby", "Toby");
+    SDL_Surface *screen = SDL_SetVideoMode(_w, _h, 32, sdlflags);
+    return(screen != NULL);
+} // SDLTurtleSpaceRenderer::screenResize
+
+
+void SDLTurtleSpaceRenderer::createSurface(int _w, int _h)
+{
+    swsurface = SDL_CreateRGBSurface(SDL_SWSURFACE, _w, _h, 32,
+                                     0x00FF0000, 0x0000FF00,
+                                     0x000000FF, 0xFF000000);
+} // SDLTurtleSpaceRenderer::createSurface
+
+
+void SDLTurtleSpaceRenderer::deleteSurface(void)
+{
+    if (swsurface != NULL)
+    {
+        SDL_FreeSurface(swsurface);
+        swsurface = NULL;
+    } // if
+} // SDLTurtleSpaceRenderer::deleteSurface
+
+
+void SDLTurtleSpaceRenderer::putToScreen(toby_uint32 *pix,
+                                         int x, int y,
+                                         int w, int h)
+{
+    assert(pix == swsurface->pixels);
+    SDL_Rect rect = {x, y, w, h};
+    SDL_Surface *screen = SDL_GetVideoSurface();
+    assert(screen != NULL);
+
+    if (SDL_MUSTLOCK(screen))
+        SDL_LockSurface(screen);
+
+    SDL_BlitSurface(swsurface, &rect, screen, &rect);
+
+    if (SDL_MUSTLOCK(screen))
+        SDL_UnlockSurface(screen);
+
+    SDL_UpdateRect(screen, x, y, w, h);  // !!! need this?
+} // SDLTurtleSpaceRenderer::putToScreen
+
+
+void SDLTurtleSpaceRenderer::putMultToScreen(toby_uint32 *pix, int rectCount,
+                                             FrameBufferRect *rects)
+{
+    assert(pix == swsurface->pixels);
+    SDL_Surface *screen = SDL_GetVideoSurface();
+    assert(screen != NULL);
+
+    if (SDL_MUSTLOCK(screen))
+        SDL_LockSurface(screen);
+
+    for (int i = 0; i < rectCount; i++)
+    {
+        SDL_Rect r = {rects[i].x, rects[i].y, rects[i].w, rects[i].h};
+        SDL_BlitSurface(swsurface, &r, screen, &r);
+        SDL_UpdateRect(screen, r.x, r.y, r.w, r.h);
+    } // for
+
+    if (SDL_MUSTLOCK(screen))
+        SDL_UnlockSurface(screen);
+
+//    SDL_UpdateRects(screen, rectCount, (SDL_Rect *) rects);  // !!! need this?
+} // SDLTurtleSpaceRenderer::putToScreen
+
+
+toby_uint32 *SDLTurtleSpaceRenderer::getSurface(void)
+{
+    if (swsurface == NULL)
+        return(NULL);
+
+    return((toby_uint32 *) swsurface->pixels);
+} // SDLTurtleSpaceRenderer::getSurface
+
+
+TurtleSpaceRenderer *__platformBuildStandaloneRenderer(char *winTitle,
+                                                       int *argc, char ***argv)
+{
+    SDLTurtleSpaceRenderer *retval = new SDLTurtleSpaceRenderer(0);
+    SDL_WM_SetCaption(winTitle, winTitle);
+    return(retval);
+} // __platformBuildStandaloneRenderer
+
+
+bool __platformRendererDoEvents(void)
+{
+    bool retval = true;
+    SDL_Event event;
+
+    while (SDL_PollEvent(&event))
+    {
+        if (event.type == SDL_QUIT)
+            retval = false;
+    } // while
+
+    return(retval);
+} // __platformRendererDoEvents
+
+// end of SDLTurtleSpaceRenderer.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/renderers/sdlrenderer/SDLTurtleSpaceRenderer.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,62 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_SDLTURTLESPACERENDERER_H_
+#define _INCLUDE_SDLTURTLESPACERENDERER_H_
+
+#include "SDL.h"
+#include "platform/renderers/fbrenderer/FrameBufferTurtleSpaceRenderer.h"
+
+/*
+ * An implementation of TurtleSpaceRenderer that does its drawing through
+ *  FrameBufferTurtleSpaceRenderer as a superclass, and uses SDL for getting
+ *  the bits to the screen. SDL stands for Simple Directmedia Layer, and
+ *  is a fast, easy-to-use, cross-platform library for graphics, sound,
+ *  input, etc.
+ *
+ *    SDL can be found at http://www.libsdl.org/
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class SDLTurtleSpaceRenderer : public FrameBufferTurtleSpaceRenderer
+{
+public:
+    SDLTurtleSpaceRenderer(Uint32 sdlflags);
+    virtual ~SDLTurtleSpaceRenderer(void);
+
+    virtual bool screenResize(int _w, int _h);
+
+protected:
+    virtual void createSurface(int _w, int _h);
+    virtual void deleteSurface(void);
+    virtual toby_uint32 *getSurface(void);
+    virtual void putToScreen(toby_uint32 *pix, int x, int y, int w, int h);
+    virtual void putMultToScreen(toby_uint32 *pix, int rectCount,
+                                    FrameBufferRect *rects);
+
+private:
+    Uint32 sdlflags;
+    SDL_Surface *screen;
+    SDL_Surface *swsurface;
+}; // class SDLTurtleSpaceRenderer
+
+#endif // !defined _INCLUDE_SDLTURTLESPACERENDERER_H_
+
+// end of SDLTurtleSpaceRenderer.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/nullthreads/NullMutex.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,56 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/nullthreads/NullMutex.h"
+
+
+NullMutex::NullMutex(void)
+{
+    _D(("NullMutex::NullMutex() called!\n"));
+} // Constructor
+
+
+NullMutex::~NullMutex(void)
+{
+    _D(("NullMutex::~NullMutex() called!\n"));
+} // Destructor
+
+
+void NullMutex::request(void)
+{
+    _D(("NullMutex::release() called!\n"));
+} // NullMutex::request
+
+
+void NullMutex::release(void)
+{
+    _D(("NullMutex::release() called!\n"));
+} // NullMutex::request
+
+
+
+// eine kleine platform glue...
+
+TobyMutex *__platformBuildMutex(void)
+{
+    return(new NullMutex());
+} // __platformBuildMutex
+
+// end of NullMutex.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/nullthreads/NullMutex.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,43 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_NULLMUTEX_H_
+#define _INCLUDE_NULLMUTEX_H_
+
+#include "util/TobyMutex.h"
+
+/*
+ * A null implementation of TobyMutex. Use this as a stub to get you going
+ *  until you can implement your own platform-specify mutex implementation.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class NullMutex : public TobyMutex
+{
+public:
+    NullMutex(void);
+    virtual ~NullMutex(void);
+    virtual void request(void);
+    virtual void release(void);
+}; // class NullMutex
+
+#endif // !defined _INCLUDE_NULLMUTEX_H_
+
+// end of NullMutex.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/nullthreads/NullThread.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,66 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/nullthreads/NullThread.h"
+
+
+NullThread::NullThread(void)
+{
+    _D(("NullThread::NullThread() called!\n"));
+} // Constructor
+
+
+NullThread::~NullThread(void)
+{
+    _D(("NullThread::~NullThread() called!\n"));
+} // Destructor
+
+
+void NullThread::start(void *(*runfunc)(void *))
+{
+    _D(("NullThread::start() called!\n"));
+} // NullThread::start
+
+
+void NullThread::waitForTermination(void)
+{
+    _D(("NullThread::waitForTermination() called!\n"));
+} // NullThread::waitForTermination
+
+
+bool NullThread::isTerminated(void)
+{
+    _D(("NullThread::isTerminated() called!\n"));
+    return(true);
+} // NullThread::isTerminated
+
+
+TobyThread *__platformBuildThread(void)
+{
+    return(new NullThread());
+} // __platformBuildThread
+
+
+void __platformThreadYieldCurrent(void)
+{
+    _D(("Null version of __platformThreadYieldCurrent() called!\n"));
+} // __platformThreadYieldCurrent
+
+// end of NullThread.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/nullthreads/NullThread.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_NULLTHREAD_H_
+#define _INCLUDE_NULLTHREAD_H_
+
+#include <unistd.h>
+#include <sched.h>
+#include "util/TobyThread.h"
+
+/*
+ * A null implementation of TobyThreads. Use this as a stub until you can get
+ *  platform-specific code written.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class NullThread : public TobyThread
+{
+public:
+    NullThread(void);
+    virtual ~NullThread(void);
+    virtual void start(void *(*runfunc)(void *));
+    virtual void waitForTermination(void);
+    virtual bool isTerminated(void);
+}; // class NullThread
+
+#endif // !defined _INCLUDE_NULLTHREAD_H_
+
+// end of NullThread.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/pthreads/PthreadsMutex.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,56 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/pthreads/PthreadsMutex.h"
+
+
+PthreadsMutex::PthreadsMutex(void)
+{
+    // !!!
+} // Constructor
+
+
+PthreadsMutex::~PthreadsMutex(void)
+{
+    // !!!
+} // Destructor
+
+
+void PthreadsMutex::request(void)
+{
+    // !!!
+} // PthreadsMutex::request
+
+
+void PthreadsMutex::release(void)
+{
+    // !!!
+} // PthreadsMutex::request
+
+
+
+// eine kleine platform glue...
+
+TobyMutex *__platformBuildMutex(void)
+{
+    return(new PthreadsMutex());
+} // __platformBuildMutex
+
+// end of PthreadsMutex.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/pthreads/PthreadsMutex.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,42 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_PTHREADSMUTEX_H_
+#define _INCLUDE_PTHREADSMUTEX_H_
+
+#include "util/TobyMutex.h"
+
+/*
+ *  A POSIX threads implementation of TobyMutex.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class PthreadsMutex : public TobyMutex
+{
+public:
+    PthreadsMutex(void);
+    virtual ~PthreadsMutex(void);
+    virtual void request(void);
+    virtual void release(void);
+}; // class PthreadsMutex
+
+#endif // !defined _INCLUDE_PTHREADSMUTEX_H_
+
+// end of PthreadsMutex.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/pthreads/PthreadsThread.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,65 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/pthreads/PthreadsThread.h"
+
+
+PthreadsThread::PthreadsThread(void)
+{
+} // Constructor
+
+
+PthreadsThread::~PthreadsThread(void)
+{
+} // Destructor
+
+
+void PthreadsThread::start(void *(*runfunc)(void *))
+{
+} // PthreadsThread::start
+
+
+void PthreadsThread::waitForTermination(void)
+{
+} // PthreadsThread::waitForTermination
+
+
+bool PthreadsThread::isTerminated(void)
+{
+    return(true);
+} // PthreadsThread::isTerminated
+
+
+TobyThread *__platformBuildThread(void)
+{
+    return(new PthreadsThread());
+} // __platformBuildThread
+
+
+void __platformThreadYieldCurrent(void)
+{
+#if (defined _POSIX_PRIORITY_SCHEDULING)
+    sched_yield();
+#else
+#warning There is no sched_yield() on this platform...
+#endif
+} // __platformThreadYieldCurrent
+
+// end of PthreadsThread.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/pthreads/PthreadsThread.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_PTHREADSTHREAD_H_
+#define _INCLUDE_PTHREADSTHREAD_H_
+
+#include <unistd.h>
+#include <sched.h>
+#include "util/TobyThread.h"
+
+/*
+ * A Pthreads-based implementation of TobyThreads. This covers most Unixes,
+ *  and other POSIX-compliant systems.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class PthreadsThread : public TobyThread
+{
+public:
+    PthreadsThread(void);
+    virtual ~PthreadsThread(void);
+    virtual void start(void *(*runfunc)(void *));
+    virtual void waitForTermination(void);
+    virtual bool isTerminated(void);
+}; // class PthreadsThread
+
+#endif // !defined _INCLUDE_PTHREADSTHREAD_H_
+
+// end of PthreadsThread.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/sdlthreads/SDLMutex.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,56 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/sdlthreads/SDLMutex.h"
+
+
+SDLMutex::SDLMutex(void)
+{
+    // !!!
+} // Constructor
+
+
+SDLMutex::~SDLMutex(void)
+{
+    // !!!
+} // Destructor
+
+
+void SDLMutex::request(void)
+{
+    // !!!
+} // SDLMutex::request
+
+
+void SDLMutex::release(void)
+{
+    // !!!
+} // SDLMutex::request
+
+
+
+// eine kleine platform glue...
+
+TobyMutex *__platformBuildMutex(void)
+{
+    return(new SDLMutex());
+} // __platformBuildMutex
+
+// end of SDLMutex.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/sdlthreads/SDLMutex.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,47 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_SDLMUTEX_H_
+#define _INCLUDE_SDLMUTEX_H_
+
+#include "SDL.h"
+#include "util/TobyMutex.h"
+
+/*
+ * An implementation of TobyMutex that uses Simple Directmedia Layer
+ *  for platform-indepent synchronization. Might as well use this if you
+ *  are using the SDL renderer, too.
+ *
+ * SDL source code and docs can be found at http://www.libsdl.org/  ...
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class SDLMutex : public TobyMutex
+{
+public:
+    SDLMutex(void);
+    virtual ~SDLMutex(void);
+    virtual void request(void);
+    virtual void release(void);
+}; // class SDLMutex
+
+#endif // !defined _INCLUDE_SDLMUTEX_H_
+
+// end of SDLMutex.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/sdlthreads/SDLThread.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,61 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "platform/threads/sdlthreads/SDLThread.h"
+
+
+SDLThread::SDLThread(void)
+{
+} // Constructor
+
+
+SDLThread::~SDLThread(void)
+{
+} // Destructor
+
+
+void SDLThread::start(void *(*runfunc)(void *))
+{
+} // SDLThread::start
+
+
+void SDLThread::waitForTermination(void)
+{
+} // SDLThread::waitForTermination
+
+
+bool SDLThread::isTerminated(void)
+{
+    return(true);
+} // SDLThread::isTerminated
+
+
+TobyThread *__platformBuildThread(void)
+{
+    return(new SDLThread());
+} // __platformBuildThread
+
+
+void __platformThreadYieldCurrent(void)
+{
+    SDL_Delay(1);
+} // __platformThreadYieldCurrent
+
+// end of SDLThread.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/platform/threads/sdlthreads/SDLThread.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,45 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_SDLTHREAD_H_
+#define _INCLUDE_SDLTHREAD_H_
+
+#include "SDL.h"
+#include "util/TobyThread.h"
+
+/*
+ * A SDL-based implementation of TobyThreads. This covers most Unixes,
+ *  and other POSIX-compliant systems.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class SDLThread : public TobyThread
+{
+public:
+    SDLThread(void);
+    virtual ~SDLThread(void);
+    virtual void start(void *(*runfunc)(void *));
+    virtual void waitForTermination(void);
+    virtual bool isTerminated(void);
+}; // class SDLThread
+
+#endif // !defined _INCLUDE_SDLTHREAD_H_
+
+// end of SDLThread.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/standalone.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,153 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+/*
+ * This is a program entry point for a standalone Toby interpreter.
+ *  There is no user interface, it just takes a source file on the command
+ *  line and fires up the interpreter and renderer.
+ *
+ *   Written by Ryan C. Gordon (icculus@linuxgames.com)
+ */
+
+#include <sys/time.h>
+#include <unistd.h>
+#include "turtlespace/TurtleSpace.h"
+#include "turtlespace/TurtleSpaceRenderer.h"
+#include "util/TobyThread.h"
+
+int main(int argc, char **argv)
+{
+    bool no_timing = false;
+    struct timeval start_time;
+    struct timeval end_time;
+    TurtleSpaceRenderer *renderer;
+
+    renderer = __platformBuildStandaloneRenderer(TobyLanguage::NAME,
+                                                  &argc, &argv);
+
+    if ((renderer == NULL) || (renderer->resize(640, 480) == false))
+    {
+        printf("failed to create TurtleSpaceRenderer.\n");
+        return(0);
+    } // if
+
+    TurtleSpace tspace(renderer);
+
+    if (gettimeofday(&start_time, NULL) == -1)
+    {
+        perror("WARNING! gettimeofday() failed");
+        no_timing = true;
+    } // if
+
+    try
+    {
+        tspace.grabTurtleSpace();
+        tspace.removeAllTurtles();
+        tspace.addTurtle();
+        tspace.useTurtle(0);
+        tspace.defaultAllTurtles();
+        tspace.cleanup();
+        tspace.enableFence();
+
+#if 1
+
+        tspace.setPenColor(0.0, 1.0, 0.0, 0.0);
+
+        for (int j = 0; j < 360; j++)
+        {
+            for (int i = 0; i < 4; i++)
+            {
+                tspace.advanceTurtle(165);
+                tspace.rotateTurtle(90);
+            } // for
+            tspace.rotateTurtle(1);
+        } // for
+
+#else
+
+        float r = 0.0;
+        float g = 1.0;
+        float b = 0.0;
+        float a = 0.0;
+
+        double xmax = tspace.getTurtleSpaceWidth();
+        double ymax = tspace.getTurtleSpaceHeight();
+    
+        float xincr = (1.0 / (float) xmax) * 2.0;
+        float yincr = (1.0 / (float) ymax) * 2.0;
+
+        tspace.rotateTurtle(90);
+
+        for (double y = 0.0; y < ymax; y += 1.0)
+        {
+            r = 0.0;
+            for (double x = 0.0; x < xmax; x += 1.0)
+            {
+                tspace.setPenColor(r, b, g, a);
+                tspace.setTurtleXY(x, y);
+                tspace.advanceTurtle(1);
+                r += xincr;
+                if ((xincr > 0.0) && (x >= (xmax / 2)))
+                    xincr = -xincr;
+            } // for
+            xincr = -xincr;
+
+            g -= yincr;
+            b += yincr;
+
+            if ((yincr > 0.0) && (y >= (ymax / 2)))
+                yincr = -yincr;
+        } // for
+
+#endif
+
+
+        tspace.releaseTurtleSpace();
+    } // try
+
+    catch (TobyException *e)
+    {
+        printf("Exception!\n[%s]\n", e->getMessage());
+        delete e;
+    } // catch
+
+    if (gettimeofday(&end_time, NULL) == -1)
+    {
+        perror("WARNING! gettimeofday() failed");
+        no_timing = true;
+    } // if
+
+    if (no_timing == false)
+    {
+        unsigned long ms;
+        ms = (unsigned long) (((end_time.tv_sec - start_time.tv_sec) * 1000) +
+                              ((end_time.tv_usec - start_time.tv_usec) / 1000));
+        printf("total time == (%ld) milliseconds.\n", ms);
+    } // if
+
+    while (__platformRendererDoEvents())
+    {
+        __platformThreadYieldCurrent();
+    } // while
+
+    delete renderer;
+    return(0);
+} // main
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/turtlespace/Turtle.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,167 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "turtlespace/Turtle.h"
+
+void Turtle::setSize(double newSize)
+{
+    sideLength = newSize;
+} // Turtle::setSize
+
+
+void Turtle::setWidth(double newSize)
+{
+    setSize(newSize);
+} // Turtle::setWidth
+
+
+void Turtle::setHeight(double newSize)
+{
+    setSize(newSize);
+} // Turtle::setHeight
+
+
+double Turtle::getWidth(void)
+{
+    return(sideLength);
+} // Turtle::getWidth
+
+
+double Turtle::getHeight(void)
+{
+    return(sideLength);
+} // Turtle::getHeight
+
+
+void Turtle::setVisible(bool visibility)
+{
+    isVisible = visibility;
+} // Turtle::setVisible
+
+
+bool Turtle::getVisible(void)
+{
+    return(isVisible);
+} // Turtle::setVisible
+
+
+void Turtle::setXY(double x, double y)
+{
+    turtleX = x;
+    turtleY = y;
+} // Turtle::setXY
+
+
+void Turtle::setX(double x)
+{
+    turtleX = x;
+} // Turtle::setX
+
+
+void Turtle::setY(double y)
+{
+        turtleY = y;
+} // Turtle::setY
+
+
+double Turtle::getX()
+{
+    return(turtleX);
+} // Turtle::getX
+
+
+double Turtle::getY()
+{
+    return(turtleY);
+} // getY
+
+
+void Turtle::getXY(double *x, double *y)
+{
+    if (x != NULL)
+        *x = turtleX;
+
+    if (y != NULL)
+        *y = turtleY;
+} // Turtle::getXY
+
+
+void Turtle::rotate(double degrees)
+{
+    setAngle(angle + degrees);
+} // Turtle::rotate
+
+
+double Turtle::getAngle(void)
+{
+    return(angle);
+} // getAngle
+
+
+void Turtle::setAngle(double newAngle)
+{
+    angle = newAngle;
+    while (angle < 0)
+        angle += 360.0;
+
+    // !!! can't do mod with floating point?   angle %= 360.0;
+    while (angle >= 360.0)
+        angle -= 360.0;
+} // Turtle::setAngle
+
+
+void Turtle::setPenDown(bool newState)
+{
+    shouldDraw = newState;
+} // Turtle::setPenDown
+
+
+bool Turtle::isPenDown(void)
+{
+    return(shouldDraw);
+} // Turtle::isPenDown
+
+
+void Turtle::getPenColor(float *r, float *g, float *b, float *a)
+{
+    if (r != NULL)
+        *r = penRed;
+
+    if (g != NULL)
+        *g = penGreen;
+
+    if (b != NULL)
+        *b = penBlue;
+
+    if (a != NULL)
+        *a = penAlpha;
+} // Turtle::getPenColor
+
+
+void Turtle::setPenColor(float r, float g, float b, float a)
+{
+    penRed = r;
+    penGreen = g;
+    penBlue = b;
+    penAlpha = a;
+} // Turtle::setPenColor
+
+
+// end of Turtle.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/turtlespace/Turtle.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,82 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TURTLE_H_
+#define _INCLUDE_TURTLE_H_
+
+#include "util/TobyObject.h"
+
+/*
+ *  The Turtle class. This is all the state related to one of those little
+ *   line-drawing cursors that roams around TurtleSpace. Note that changing
+ *   state like visibility or size doesn't affect the visual representation
+ *   by default; these are just data structures. The TurtleSpace and
+ *   TurtleSpaceRenderer classes handle getting those changes to the screen.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class Turtle : public TobyObject
+{
+public:
+    Turtle(void) : sideLength(0.0), angle(270.0),
+                   turtleX(0.0), turtleY(0.0),
+                   isVisible(false), shouldDraw(true),
+                   penRed(1.0), penGreen(1.0), penBlue(1.0), penAlpha(1.0) {}
+
+    virtual ~Turtle(void) {}
+
+    void setWidth(double newSize);
+    void setHeight(double newSize);
+    double getWidth(void);
+    double getHeight(void);
+    void setVisible(bool visibility);
+    bool getVisible(void);
+    void setXY(double x, double y);
+    void setX(double x);
+    void setY(double y);
+    double getX(void);
+    double getY(void);
+    void getXY(double *x, double *y);
+    void rotate(double degrees);
+    double getAngle(void);
+    void setAngle(double newAngle);
+    void setPenDown(bool newState);
+    bool isPenDown(void);
+    void getPenColor(float *r, float *g, float *b, float *a);
+    void setPenColor(float r, float g, float b, float a);
+
+private:
+    double sideLength;     // Size of one side of Turtle.
+    double angle;          // 0 - 360 degrees. Direction faced.
+    double turtleX;        // X location of Turtle.
+    double turtleY;        // Y location of Turtle.
+    bool isVisible;        // Should we even paint this guy?
+    bool shouldDraw;       // Should we leave trails?
+    float penRed;          // Turtle's pen's red element.
+    float penGreen;        // Turtle's pen's green element.
+    float penBlue;         // Turtle's pen's blue element.
+    float penAlpha;        // Turtle's pen's alpha element.
+
+    void setSize(double newSize);   // !!! remove. Turtle is not necessarily square.
+}; // class Turtle
+
+#endif  // !defined _INCLUDE_TURTLE_H_
+
+// end of Turtle.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/turtlespace/TurtleSpace.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,888 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "turtlespace/TurtleSpace.h"
+
+TurtleSpace::TurtleSpace(TurtleSpaceRenderer *_renderer) :
+        dueNorth(270.0), turtles(NULL), turtlesArraySize(0),
+        turtlePool(new TobyStack()), fenceEnabled(false), turtle(NULL),
+        renderer(_renderer), turtleSync(__platformBuildMutex())
+{
+    assert(_renderer != NULL);
+} // Constructor
+
+
+TurtleSpace::~TurtleSpace(void)
+{
+    for (int i = 0; i < turtlesArraySize; i++)
+    {
+        if (turtles[i] != NULL)
+            delete turtles[i];
+    } // for
+
+    if (turtles != NULL)
+        free(turtles);
+
+    while (turtlePool->isEmpty() == false)
+        delete turtlePool->remove(0);
+
+    delete turtlePool;
+
+} // Destructor
+
+
+static inline void clampFloat(float *x, float min, float max)
+{
+    if (*x < min)
+        *x = min;
+    else if (*x > max)
+        *x = max;
+} // clampFloat
+
+
+static inline void clampColorValues(float *r, float *g, float *b, float *a)
+{
+    clampFloat(r, 0.0, 1.0);
+    clampFloat(g, 0.0, 1.0);
+    clampFloat(b, 0.0, 1.0);
+    clampFloat(a, 0.0, 1.0);
+} // clampColorValues
+
+
+TurtleSpaceRenderer *TurtleSpace::getTurtleSpaceRenderer(void)
+{
+    return(renderer);
+} // TurtleSpace::getTurtleSpaceRenderer
+
+double TurtleSpace::getTurtleSpaceWidth(void)
+{
+    return(renderer->getTurtleSpaceWidth());
+} // TurtleSpace::getTurtleSpaceWidth
+
+
+double TurtleSpace::getTurtleSpaceHeight(void)
+{
+    return(renderer->getTurtleSpaceHeight());
+} // TurtleSpace::getTurtleSpaceWidth
+
+
+double TurtleSpace::getDueNorth(void)
+{
+    return(dueNorth);
+} // TurtleSpace::getDueNorth
+
+
+void TurtleSpace::setDueNorth(double angle)
+{
+    dueNorth = angle;
+} // TurtleSpace::setDueNorth
+
+
+Turtle *TurtleSpace::getTurtleByIndex(int turtleIndex)
+{
+    Turtle *retVal = NULL;
+
+    turtleSync->request();
+
+    if (turtles != NULL)
+    {
+        if ((turtleIndex >= 0) && (turtleIndex < turtlesArraySize))
+            retVal = turtles[turtleIndex];
+    } // if
+
+    turtleSync->release();
+
+    return(retVal);
+} // TurtleSpace::getTurtleByIndex
+
+
+int TurtleSpace::getTurtleCount(void)
+{
+    int retVal = 0;
+
+    turtleSync->request();
+
+    if (turtles != NULL)
+    {
+        for (int i = 0; i < turtlesArraySize; i++)
+        {
+            if (turtles[i] != NULL)
+                retVal++;
+        } // for
+    } // if
+
+    turtleSync->release();
+
+    return(retVal);
+} // TurtleSpace::getTurtleCount
+
+
+Turtle *TurtleSpace::buildNewTurtle(void) throw (ExecException *)
+{
+    Turtle *retVal = NULL;
+
+    turtleSync->request();
+    retVal = (Turtle *) turtlePool->pop();
+    turtleSync->release();
+
+    if (retVal == NULL)
+        retVal = new Turtle();
+
+    defaultTurtle(retVal);
+
+    return(retVal);
+} // TurtleSpace::buildNewTurtle
+
+
+int TurtleSpace::addTurtle(void) throw (ExecException *)
+{
+    Turtle *newTurtle = buildNewTurtle();
+
+    turtleSync->request();
+
+    if (turtles != NULL)
+    {
+        for (int i = 0; i < turtlesArraySize; i++)
+        {
+            if (turtles[i] == NULL)
+            {
+                turtles[i] = newTurtle;
+                turtleSync->release();
+                return(i);
+            } // if
+        } // for
+    } // if
+
+    // if we landed here, we need to increase the size of the array...
+
+    turtlesArraySize++;
+    turtles = (Turtle **)realloc(turtles, turtlesArraySize * sizeof(Turtle *));
+    assert(turtles != NULL);
+    turtles[turtlesArraySize - 1] = newTurtle;
+    turtleSync->release();
+    return(turtlesArraySize - 1);
+} // TurtleSpace::addTurtle
+
+
+bool TurtleSpace::removeTurtle(int turtleIndex) throw (ExecException *)
+{
+    bool retVal = false;
+    Turtle *t = getTurtleByIndex(turtleIndex);
+
+    if (turtle == t)     // set selected turtle to none if removing selected.
+        turtle = NULL;
+
+    // !!! Should we throw an ExecException if turtleIndex is bogus?
+
+    if (t != NULL)   // ...if removing a valid, existing turtle...
+    {
+        renderer->blankTurtle(t);
+        t->setVisible(false);
+        turtleSync->request();
+        turtlePool->push(t);
+        turtles[turtleIndex] = NULL;
+        turtleSync->release();
+        retVal = true;
+    } // if
+
+    return(retVal);
+} // TurtleSpace::removeTurtle
+
+
+void TurtleSpace::removeAllTurtles(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtles != NULL)
+    {
+        for (int i = 0; i < turtlesArraySize; i++)
+        {
+            if (turtles[i] != NULL)
+                removeTurtle(i);
+        } // for
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::removeAllTurtles
+
+
+void TurtleSpace::grabTurtleSpace(void)
+{
+    renderer->notifyGrabbed();
+} // TurtleSpace::grabTurtleSpace
+
+
+void TurtleSpace::releaseTurtleSpace(void)
+{
+    renderer->notifyUngrabbed();
+} // TurtleSpace::grabTurtleSpace
+
+
+void TurtleSpace::verifyPointInsideFence(double x, double y)
+                                                    throw (ExecException *)
+{
+    if (fenceEnabled == true)
+    {
+        if ( (x < 0.00) || (x > renderer->getTurtleSpaceWidth()) ||
+             (y < 0.00) || (y > renderer->getTurtleSpaceHeight()) )
+        {
+            ExecException::_throw(TobyLanguage::TURTLE_FENCED);
+        } // if
+    } // if
+} // TurtleSpace::verifyPointInsideFence
+
+
+void TurtleSpace::enableFence(void) throw (ExecException *)
+{
+    setFence(true);
+} // TurtleSpace::enableFence
+
+
+void TurtleSpace::disableFence(void) throw (ExecException *)
+{
+    setFence(false);
+} // TurtleSpace::disableFence
+
+
+void TurtleSpace::setFence(bool buildFence) throw (ExecException *)
+{
+    fenceEnabled = buildFence;
+
+    turtleSync->request();
+
+    try
+    {
+        if ((buildFence == true) && (turtles != NULL))
+        {
+            Turtle *t;
+
+            for (int i = 0; i < turtlesArraySize; i++)
+            {
+                t = turtles[i];
+                if (t != NULL)
+                    verifyPointInsideFence(t->getX(), t->getY());
+            } // for
+        } // if
+    } // try
+
+    catch (TobyObject *obj)
+    {
+        turtleSync->release();
+        throw obj;
+    } // catch
+
+    turtleSync->release();
+} // TurtleSpace::setFence
+
+
+void TurtleSpace::useTurtle(int turtleIndex) throw (ExecException *)
+{
+    turtleSync->request();
+
+    Turtle *newTurtle = getTurtleByIndex(turtleIndex);
+    if (newTurtle != NULL)
+        turtle = newTurtle;
+    else
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::BAD_ARGUMENT);
+    } // else
+
+    turtleSync->release();
+} // TurtleSpace::useTurtle
+
+
+double TurtleSpace::getTurtleX(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    double retval = turtle->getX();
+    turtleSync->release();
+    return(retval);
+} // TurtleSpace::getTurtleX
+
+
+double TurtleSpace::getTurtleY(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    double retval = turtle->getY();
+    turtleSync->release();
+    return(retval);
+} // TurtleSpace::getTurtleY
+
+
+double TurtleSpace::getTurtleWidth(void) throw (ExecException *)
+{
+    turtleSync->request();
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    double retval = turtle->getWidth();
+    turtleSync->release();
+    return(retval);
+} // TurtleSpace::getTurtleWidth
+
+
+double TurtleSpace::getTurtleHeight(void) throw (ExecException *)
+{
+    turtleSync->request();
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    double retval = turtle->getHeight();
+    turtleSync->release();
+    return(retval);
+} // TurtleSpace::getTurtleHeight
+
+
+void TurtleSpace::setTurtleX(double x) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if (x == turtle->getX())
+        turtleSync->release();
+    else
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setX(x);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+
+        double y = turtle->getY();
+        turtleSync->release();
+        verifyPointInsideFence(x, y);
+    } // else
+} // TurtleSpace::setTurtleX
+
+
+void TurtleSpace::setTurtleY(double y) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if (y == turtle->getY())
+        turtleSync->release();
+    else
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setY(y);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+
+        double x = turtle->getX();
+        turtleSync->release();
+        verifyPointInsideFence(x, y);
+    } // else
+} // TurtleSpace::setTurtleY
+
+
+void TurtleSpace::setTurtleXY(double x, double y) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if ((y == turtle->getY()) && (x == turtle->getX()))
+        turtleSync->release();
+    else
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setXY(x, y);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+
+        turtleSync->release();
+        verifyPointInsideFence(x, y);
+    } // else
+} // TurtleSpace::setTurtleXY
+
+
+void TurtleSpace::setTurtleWidth(double newWidth) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if (newWidth != turtle->getWidth())
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setWidth(newWidth);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::setTurtleWidth
+
+
+void TurtleSpace::setTurtleHeight(double newHeight) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if (newHeight != turtle->getHeight())
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setHeight(newHeight);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::setTurtleHeight
+
+
+void TurtleSpace::setTurtleVisibility(Turtle *t, bool isVis)
+                                                    throw (ExecException *)
+{
+    if (isVis != t->getVisible())
+    {
+        t->setVisible(isVis);
+
+        if (isVis == true)
+            renderer->renderTurtle(t);
+        else
+            renderer->blankTurtle(t);
+    } // if
+} // TurtleSpace::setTurtleVisibility
+
+
+void TurtleSpace::setTurtleVisibility(bool isVis) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    setTurtleVisibility(turtle, isVis);
+    turtleSync->release();
+} // TurtleSpace::setTurtleVisible
+        
+
+void TurtleSpace::showTurtle(void) throw (ExecException *)
+{
+    setTurtleVisibility(true);
+} // TurtleSpace::showTurtle
+
+
+void TurtleSpace::showAllTurtles(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    for (int i = 0; i < turtlesArraySize; i++)
+    {
+        if (turtles[i] != NULL)
+            setTurtleVisibility(turtles[i], true);
+    } // for
+
+    turtleSync->release();
+} // TurtleSpace::showAllTurtles
+
+
+void TurtleSpace::hideTurtle(void) throw (ExecException *)
+{
+    setTurtleVisibility(false);
+} // TurtleSpace::hideTurtle
+
+
+void TurtleSpace::hideAllTurtles(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    for (int i = 0; i < turtlesArraySize; i++)
+    {
+        if (turtles[i] != NULL)
+            setTurtleVisibility(turtles[i], false);
+    } // for
+
+    turtleSync->release();
+} // TurtleSpace::hideAllTurtles
+
+
+void TurtleSpace::advanceTurtle(double distance) throw (ExecException *)
+{
+    if (distance == 0.0)
+        return;
+
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    double angle = turtle->getAngle();
+    double turtleX = turtle->getX();
+    double turtleY = turtle->getY();
+    double x, y;
+
+    TobyGeometry::calculateLine(angle, distance, turtleX, turtleY, &x, &y);
+
+    bool isVis = turtle->getVisible();
+    if (isVis == true)
+        renderer->blankTurtle(turtle);
+
+    if (turtle->isPenDown())   // draw the line covering path turtle took?
+    {
+        float r, g, b, a;
+        turtle->getPenColor(&r, &g, &b, &a);
+
+// !!! needs to clamp lines to dimensions of TurtleSpace.
+        renderer->renderLine(turtleX, turtleY, x, y, r, b, g, a);
+    } // if
+
+    turtle->setXY(x, y);
+
+    if (isVis == true)
+        renderer->renderTurtle(turtle);
+
+    turtleSync->release();
+
+    verifyPointInsideFence(x, y);
+} // TurtleSpace::advanceTurtle
+
+
+void TurtleSpace::setTurtleAngle(double angle) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    if (angle != turtle->getAngle())
+    {
+        bool isVis = turtle->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(turtle);
+
+        turtle->setAngle(angle);
+
+        if (isVis == true)
+            renderer->renderTurtle(turtle);
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::setTurtleAngle
+
+
+void TurtleSpace::rotateTurtle(double degree) throw (ExecException *)
+{
+    if (degree == 0.0)
+        return;
+
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    setTurtleAngle(turtle->getAngle() + degree);
+
+    turtleSync->release();
+} // TurtleSpace::rotateTurtle
+
+
+void TurtleSpace::homeTurtle(Turtle *t) throw (ExecException *)
+{
+    double x = renderer->getTurtleSpaceWidth() / 2;
+    double y = renderer->getTurtleSpaceHeight() / 2;
+
+    turtleSync->request();
+
+    if ((x != t->getX()) || (y != t->getY()))
+    {
+        bool isVis = t->getVisible();
+        if (isVis == true)
+            renderer->blankTurtle(t);
+
+        t->setXY(x, y);
+
+        if (isVis == true)
+            renderer->renderTurtle(t);
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::homeTurtle
+
+
+void TurtleSpace::homeTurtle(void) throw (ExecException *)
+{
+        // !!! This code is always the same... can we get this in a macro
+        // !!!  or inline function?
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    homeTurtle(turtle);
+
+    turtleSync->release();
+} // TurtleSpace::homeTurtle
+
+
+void TurtleSpace::homeAllTurtles(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    for (int i = 0; i < turtlesArraySize; i++)
+    {
+        if (turtles[i] != NULL)
+            homeTurtle(turtles[i]);
+    } // for
+
+    turtleSync->release();
+} // TurtleSpace::homeAllTurtles
+
+
+void TurtleSpace::defaultTurtle(Turtle *t) throw (ExecException *)
+{
+    assert(t != NULL);
+
+    float r = getDefaultPenRed();
+    float g = getDefaultPenGreen();
+    float b = getDefaultPenBlue();
+    float a = getDefaultPenAlpha();
+
+    clampColorValues(&r, &g, &b, &a); // better safe than sorry.
+
+    bool isVis = t->getVisible();
+
+    if (t->getAngle() != dueNorth)
+    {
+        if (isVis == true)
+        {
+            renderer->blankTurtle(t);
+            isVis = false;
+        } // if
+        t->setAngle(dueNorth);
+    } // if
+
+    t->setPenDown(true);
+    t->setPenColor(r, g, b, a);
+
+    double x = renderer->getTurtleSpaceWidth() / 2;
+    double y = renderer->getTurtleSpaceHeight() / 2;
+    if ((t->getX() != x) || (t->getY() != y))
+    {
+        if (isVis == true)
+        {
+            renderer->blankTurtle(t);
+            isVis = false;
+        } // if
+        t->setXY(x, y);
+    } // if
+
+    t->setVisible(true);
+    if (isVis == false)
+        renderer->renderTurtle(t);
+} // TurtleSpace::defaultTurtle
+
+
+void TurtleSpace::defaultTurtle(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    defaultTurtle(turtle);
+
+    turtleSync->release();
+} // TurtleSpace::defaultTurtle
+
+
+void TurtleSpace::defaultAllTurtles(void) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtles != NULL)
+    {
+        for (int i = 0; i < turtlesArraySize; i++)
+            defaultTurtle(turtles[i]);
+    } // if
+
+    turtleSync->release();
+} // TurtleSpace::defaultAllTurtles
+
+
+void TurtleSpace::setPenColor(float r, float g, float b, float a)
+                                                        throw (ExecException *)
+{
+    clampColorValues(&r, &g, &b, &a);
+
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    turtle->setPenColor(r, g, b, a);
+
+    turtleSync->release();
+} // TurtleSpace::setPenColor
+
+
+void TurtleSpace::setPen(bool drawing) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    turtle->setPenDown(drawing);
+
+    turtleSync->release();
+} // TurtleSpace::setPen
+
+
+void TurtleSpace::setPenUp(void) throw (ExecException *)
+{
+    setPen(false);
+} // TurtleSpace::setPenUp
+
+
+void TurtleSpace::setPenDown(void) throw (ExecException *)
+{
+    setPen(true);
+} // TurtleSpace::setPenDown
+
+
+void TurtleSpace::drawString(const char *str) throw (ExecException *)
+{
+    turtleSync->request();
+
+    if (turtle == NULL)
+    {
+        turtleSync->release();
+        ExecException::_throw(TobyLanguage::NOCURTURTLE);
+    } // if
+
+    float r, g, b, a;
+    double x = turtle->getX();
+    double y = turtle->getY();
+    double angle = turtle->getAngle();
+    turtle->getPenColor(&r, &g, &b, &a);
+
+    turtleSync->release();
+
+    renderer->renderString(x, y, angle, r, g, b, a, str);
+} // TurtleSpace::renderString
+
+
+void TurtleSpace::cleanup(void) throw (ExecException *)
+{
+    renderer->cleanup();
+
+    turtleSync->request();
+
+    for (int i = 0; i < turtlesArraySize; i++)
+    {
+        if (turtles[i]->getVisible())
+            renderer->renderTurtle(turtles[i]);
+    } // for
+
+    turtleSync->release();
+} // TurtleSpace::cleanup
+
+
+// end of TurtleSpace.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/turtlespace/TurtleSpace.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,128 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TURTLESPACE_H_
+#define _INCLUDE_TURTLESPACE_H_
+
+#include "util/TobyObject.h"
+#include "util/TobyLanguage.h"
+#include "util/TobyMutex.h"
+#include "util/TobyStack.h"
+#include "util/TobyGeometry.h"
+#include "turtlespace/Turtle.h"
+#include "turtlespace/TurtleSpaceRenderer.h"
+
+/*
+ *  This is TurtleSpace, the interpreted program's interface to the
+ *   screen. This specific class has no physical representation; the actual
+ *   widget/window/whatever is managed by an implementation of the
+ *   TurtleSpaceRenderer class, which takes commands from this class and
+ *   gets the bits to the screen. Besides being the abstract link between
+ *   the renderer and the interpreted program, TurtleSpace handles Turtle
+ *   maintenance and other TurtleGraphics-related state.
+ *
+ *   Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TurtleSpace : public TobyObject
+{
+public:
+    TurtleSpace(TurtleSpaceRenderer *_renderer);
+    virtual ~TurtleSpace(void);
+
+        // Basic TurtleSpace information queries.
+    TurtleSpaceRenderer *getTurtleSpaceRenderer(void);
+    double getTurtleSpaceWidth(void);
+    double getTurtleSpaceHeight(void);
+    double getDueNorth(void);
+    void   setDueNorth(double angle);
+    static float getDefaultPenRed(void)    { return(1.0); }
+    static float getDefaultPenGreen(void)  { return(1.0); }
+    static float getDefaultPenBlue(void)   { return(1.0); }
+    static float getDefaultPenAlpha(void)  { return(1.0); }
+
+        // Turtle pool manipulation.
+    int getTurtleCount(void);
+    int addTurtle(void) throw (ExecException *);
+    bool removeTurtle(int turtleIndex) throw (ExecException *);
+    void removeAllTurtles(void) throw (ExecException *);
+
+        // Rendering state-machine interface.
+    void grabTurtleSpace(void);
+    void releaseTurtleSpace(void);
+
+        // Fence state-machine interface.
+    void enableFence(void) throw (ExecException *);
+    void disableFence(void) throw (ExecException *);
+    void setFence(bool buildFence) throw (ExecException *);
+
+        // Turtle state-machine interface.
+    void useTurtle(int turtleIndex) throw (ExecException *);
+    double getTurtleX(void) throw (ExecException *);
+    double getTurtleY(void) throw (ExecException *);
+    double getTurtleWidth(void) throw (ExecException *);
+    double getTurtleHeight(void) throw (ExecException *);
+    void setTurtleX(double x) throw (ExecException *);
+    void setTurtleY(double y) throw (ExecException *);
+    void setTurtleXY(double x, double y) throw (ExecException *);
+    void setTurtleWidth(double newWidth) throw (ExecException *);
+    void setTurtleHeight(double newHeight) throw (ExecException *);
+    void setTurtleVisibility(bool isVis) throw (ExecException *);
+    void showTurtle(void) throw (ExecException *);
+    void showAllTurtles(void) throw (ExecException *);
+    void hideTurtle(void) throw (ExecException *);
+    void hideAllTurtles(void) throw (ExecException *);
+    void advanceTurtle(double distance) throw (ExecException *);
+    void setTurtleAngle(double angle) throw (ExecException *);
+    void rotateTurtle(double degree) throw (ExecException *);
+    void homeTurtle(void) throw (ExecException *);
+    void homeAllTurtles(void) throw (ExecException *);
+    void defaultTurtle(void) throw (ExecException *);
+    void defaultAllTurtles(void) throw (ExecException *);
+    void setPenColor(float r, float g, float b, float a) throw (ExecException *);
+    void setPen(bool drawing) throw (ExecException *);
+    void setPenUp(void) throw (ExecException *);
+    void setPenDown(void) throw (ExecException *);
+
+        // miscellaneous rendering stuff.
+    void drawString(const char *str) throw (ExecException *);
+    void cleanup(void) throw (ExecException *);
+
+protected:
+    Turtle *getTurtleByIndex(int turtleIndex);
+    Turtle *buildNewTurtle(void) throw (ExecException *);
+    void homeTurtle(Turtle *t) throw (ExecException *);
+    void defaultTurtle(Turtle *t) throw (ExecException *);
+    void verifyPointInsideFence(double x, double y) throw (ExecException *);
+    void setTurtleVisibility(Turtle *t, bool isVis) throw (ExecException *);
+
+private:
+    double dueNorth;
+    Turtle **turtles;
+    int turtlesArraySize;
+    TobyStack *turtlePool;
+    bool fenceEnabled;
+    Turtle *turtle;
+    TurtleSpaceRenderer *renderer;
+    TobyMutex *turtleSync;
+}; // class TurtleSpace
+
+#endif // !defined _INCLUDE_TURTLESPACE_H_
+
+// end of TurtleSpace.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/turtlespace/TurtleSpaceRenderer.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,117 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TURTLESPACERENDERER_H_
+#define _INCLUDE_TURTLESPACERENDERER_H_
+
+#include "util/TobyObject.h"
+#include "exceptions/ExecException.h"
+#include "turtlespace/Turtle.h"
+
+/*
+ * The TurtleSpaceRenderer interface. This is a pure virtual class, so
+ *  you'll need to implement it for your given platform. This class has the
+ *  physical representation of TurtleSpace, and gets the bits to the screen.
+ *
+ * Examples of subclasses would be a Qt implementation, an SDL
+ *  implementation, a Win32 implementation, etc.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TurtleSpaceRenderer : public TobyObject
+{
+public:
+    TurtleSpaceRenderer(void) {}
+    virtual ~TurtleSpaceRenderer(void) {}
+
+        // Create a screen surface: windows should be created, or resolutions
+        //  should be changed in this method. If the screen surface can not
+        //  be created to satisfaction, this should return (false). If the
+        //  screen initialization was successful, this should return (true).
+        // Note that this method may be called multiple times during the
+        //  existance of the object, whether previous calls failed or not.
+        //  If there is a resize call after/during rendering (even while
+        //  TurtleSpace is "grabbed"), then the renderer should strive to
+        //  maintain the currently rendered image in the new size.
+    virtual bool resize(int w, int h) = 0;
+
+        // These notification methods are called when TurtleSpace rendering
+        //  begins and ends, presumably at program interpretation start and
+        //  finish. This is for your renderer's informational purposes only,
+        //  and you aren't required to do anything at all in these methods.
+    virtual void notifyGrabbed(void) = 0;
+    virtual void notifyUngrabbed(void) = 0;
+
+        // Get the dimensions of the current screen surface in pixels.
+    virtual double getTurtleSpaceWidth(void) = 0;
+    virtual double getTurtleSpaceHeight(void) = 0;
+
+        // Get the preferred default dimensions for a turtle in pixels, which
+        //  may or may not be ignored completely. Note the turtle may also be
+        //  arbitrarily resized during program interpretation.
+    virtual double getDesiredTurtleWidth(void) = 0;
+    virtual double getDesiredTurtleHeight(void) = 0;
+
+        // Render a text string to the screen, starting at coordinate (x), (y),
+        //  and tilted at (angle), where 270.0 is due north. The color
+        //  channels, (r), (b), (g), and (a), are the red, blue, green, and
+        //  alpha, are specified in a range of 0.0 (no intensity on that
+        //  channel) to 1.0 (full intensity on that channel). (str) is, of
+        //  course, the string to render. Extra credit for antialiasing.
+    virtual void renderString(double x, double y, double angle,
+                                float r, float b, float g, float a,
+                                const char *str) = 0;
+
+
+        // Render a line segment between 2 points, in the specified color.
+        //  The color values will be clamped between 0.0 and 1.0, and the
+        //  line coordinates will be clamped to be inside the dimensions of
+        //  TurtleSpace.
+    virtual void renderLine(double x1, double y1, double x2, double y2,
+                                float r, float b, float g, float a) = 0;
+
+        // These need to be replaced by !!!
+    virtual void renderTurtle(Turtle *turtle) throw (ExecException) = 0;
+    virtual void blankTurtle(Turtle *turtle) throw (ExecException) = 0;
+
+        // Blank TurtleSpace to full alpha, and zero red, green, and blue.
+        //  Turtles that need rerendering will be handled by calls to
+        //  the renderTurtle() method after this call.
+    virtual void cleanup(void) throw (ExecException) = 0;
+}; // class TurtleSpaceRenderer
+
+
+    // This gets filled in along with the platform-specific subclass.
+    //  It should be a standalone TurtleSpace, or return NULL if it can't.
+    //  For example, a GTK+ widget-based TurtleSpace should build a GtkWindow
+    //  around it so that it needs nothing else to display. Width and height
+    //  are specified in pixels.
+TurtleSpaceRenderer *__platformBuildStandaloneRenderer(char *winTitle,
+                                                       int *argc, char ***argv);
+
+    // This gets called to give you a chance to run a toolkit-specific
+    //  event queue or other idle-time upkeep you may need. If a quit event
+    //  or some other reason to abort the program arises, return false,
+    //  otherwise, return true.
+bool __platformRendererDoEvents(void);
+
+#endif // !defined _INCLUDE_TURTLESPACERENDERER_H_
+
+// end of TurtleSpaceRenderer.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyCollection.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,126 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "util/TobyCollection.h"
+
+
+TobyCollection::TobyCollection(void) : list(NULL)
+{
+} // Constructor
+
+
+TobyCollection::~TobyCollection(void)
+{
+    TobyLinkedList *next = NULL;
+
+    while (list != NULL)
+    {
+        next = list->next;
+        delete list;
+        list = next;
+    } // while
+} // Destructor
+
+
+void TobyCollection::insertElement(TobyObject *elem, int pos)
+{
+    int count = 0;
+
+    for (TobyLinkedList *i = list; i != NULL; i = i->next)
+    {
+        if (count == pos)
+        {
+            TobyLinkedList *node = new TobyLinkedList;
+            assert(node != NULL);
+
+            node->obj = elem;
+            node->next = i;
+            node->prev = i->prev;
+            i->prev = node;
+            if (node->prev != NULL)
+                node->prev->next = node;
+
+            return;
+        } // if
+
+        count++;
+    } // for
+} // TobyCollection::insertElement
+
+
+TobyObject *TobyCollection::elementAt(int pos)
+{
+    int count = 0;
+
+    for (TobyLinkedList *i = list; i != NULL; i = i->next)
+    {
+        if (count == pos)
+            return(i->obj);
+
+        count++;
+    } // for
+
+    return(NULL);
+} // TobyCollection::insertElement
+
+
+TobyObject *TobyCollection::remove(int pos)
+{
+    int count = 0;
+
+    for (TobyLinkedList *i = list; i != NULL; i = i->next)
+    {
+        if (count == pos)
+        {
+            TobyObject *retval = i->obj;
+            if (i->prev != NULL)
+                i->prev->next = i->next;
+
+            if (i->next != NULL)
+                i->next->prev = i->prev;
+
+            delete i;
+            return(retval);
+        } // if
+        count++;
+    } // for
+
+    return(NULL);
+} // TobyCollection::remove
+
+
+bool TobyCollection::isEmpty(void)
+{
+    return(list == NULL);
+} // TobyCollection::isEmpty
+
+
+int TobyCollection::size(void)
+{
+    // O(n), not O(1).
+    int retval = 0;
+
+    for (TobyLinkedList *i = list; i != NULL; i = i->next)
+        retval++;
+
+    return(retval);
+} // TobyCollection::size
+
+// end of TobyCollection.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyCollection.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,57 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYCOLLECTION_H_
+#define _INCLUDE_TOBYCOLLECTION_H_
+
+#include "util/TobyObject.h"
+
+/*
+ * This is a base class for linear collections: lists, stacks, etc.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+
+// internally, this is just a linked list.
+typedef struct TobyLinkedListStruct
+{
+    TobyObject *obj;
+    struct TobyLinkedListStruct *prev;
+    struct TobyLinkedListStruct *next;
+} TobyLinkedList;
+
+class TobyCollection : public TobyObject
+{
+public:
+    TobyCollection(void);
+    virtual ~TobyCollection(void);
+    virtual void insertElement(TobyObject *elem, int pos);
+    virtual TobyObject *elementAt(int pos);
+    virtual TobyObject *remove(int pos);
+    virtual bool isEmpty(void);
+    virtual int size(void);
+
+protected:
+    TobyLinkedList *list;
+}; // class TobyCollection
+
+#endif  // !defined _INCLUDE_TOBYCOLLECTION_H_
+
+// end of TobyCollection.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyGeometry.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,134 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYGEOMETRY_H_
+#define _INCLUDE_TOBYGEOMETRY_H_
+
+#include <math.h>
+#include "util/TobyObject.h"
+
+
+/*
+ * Some needed math routines.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyGeometry
+{
+public:
+    static inline double degreesToRadians(double degrees)
+    {
+        return(degrees * (M_PI / 180.0));
+    } // TobyGeometry::degreesToRadians
+
+
+    static inline double radiansToDegrees(double radians)
+    {
+        return(radians * (180.0 / M_PI));
+    } // TobyGeometry::degreesToRadians
+
+
+    static inline int roundDoubleToInt(double dbl)
+    {
+        return((int) (dbl + 0.5));
+    } // TobyGeometry::roundDoubleToInt
+
+
+    static inline void calculateLine(double heading, double distance,
+                              double startX, double startY,
+                              double *endX, double *endY)
+    /*
+     * This procedure calculates coordinates for a line. No line is actually
+     *  drawn by this procedure, though.
+     *
+     *   params : heading  == 0 - 360 degree direction line goes.
+     *            distance == total space line should cover.
+     *            startX   == Starting x coordinate for line.
+     *            startY   == Starting y coordinate for line.
+     *            *endX    == filled with end point on X-axis.
+     *            *endY    == filled with end point on Y-axis.
+     *   returns : void. Data is return in (endX) and (endY).
+     */
+    {
+        assert(endX != NULL);
+        assert(endY != NULL);
+
+        double rad = degreesToRadians(heading);
+        *endX = (cos(rad) * (double) distance) + startX;
+        *endY = (sin(rad) * (double) distance) + startY;
+    } // TobyGeometry::calculateLine
+
+    /*
+     * This converts a float in the range of 0.0 to 1.0 to an 8-bit integer.
+     *  A value of 0.0 (zero percent) yields a return of 0. A value of 1.0
+     *  (one hundred percent) yields a return of 255. Everything else is
+     *  somewhere inbetween. Values not in the range of 0.0 to 1.0 are clamped
+     *  before conversion.
+     */
+    static inline toby_uint8 floatTo8Bit(float val)
+    {
+        if (val > 1.0)
+            val = 1.0;
+        else if (val < 0.0)
+            val = 0.0;
+
+        return((toby_uint8) (val * 255.0));
+    } // TobyGeometry::floatTo8Bit
+
+
+    static inline double pythagorian(double s1, double hypotenuse)
+    /*
+     *  The Pythagorian Theorem: Figure out the length of the third side
+     *   of a right triangle, based on the lengths of the other two.
+     *
+     *  The formula is like this: The sum of the squares of the lengths of
+     *   the two non-hypotenuse sides of a right triangle will equal the
+     *   square of the hypotenuse. So, if we know two sides of a right
+     *   triangle, we can get the third. (In this function, you need to know
+     *   which is the hypotenuse, but you can easily write a version of
+     *   this that figures out the hypotenuse based on the other two sides.
+     *
+     *  To find a non-hypotenuse side:
+     *    (H2 represents hypotenuse, squared.)
+     *    (X2 represents 1st non-hypotenuse side, squared.)
+     *    (Y2 represents 2nd non-hypotenuse side, squared.)
+     *
+     *       H2 = X2 + Y2
+     *       H2 - X2 = Y2 + X2 - X2
+     *       H2 - X2 = Y2
+     *       H2 - H2 - X2 = Y2 - H2
+     *       -X2 = Y2 - H2
+     *       X2 = - Y2 + H2
+     *       X2 = H2 - Y2
+     *
+     *      params : s1 == length of known non-hypotenuse side of rt. triangle.
+     *               hypotenuse == length of hypotenuse of right triangle.
+     *     returns : length of third side of right triangle.
+     */
+    {
+        return(sqrt((hypotenuse * hypotenuse) - (s1 * s1)));
+    } // TobyGeometry::pythagorian
+
+}; // class TobyGeometry
+
+#endif // !defined _INCLUDE_TOBYGEOMETRY_H_
+
+// end of TobyGeometry.h ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyLanguage.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,171 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "util/TobyLanguage.h"
+
+
+        // Do NOT translate the strings in here!
+        //  The program will default to English (using the below strings)
+        //  if it doesn't load langfiles to use a different language.
+        //  Translations should be done from a separate langfile.
+
+char *TobyLanguage::NAME = "Toby";
+
+char *TobyLanguage::USAGE = "USAGE: Toby.class [--langfile=xxx] [sourceFile.toby]";
+
+char *TobyLanguage::TRANSLATION_BY =
+                                    "English language text by Ryan C. Gordon.";
+
+char *TobyLanguage::WRITTENBY = "Written by Ryan C. Gordon.";
+char *TobyLanguage::COPYRIGHT = "Copyright (C) 1999 Ryan C. Gordon";
+
+char *TobyLanguage::ERROR = "Error";
+char *TobyLanguage::NOT_YET_IMPLEMENTED = "Feature not yet implemented.";
+char *TobyLanguage::NODETREE_LOCKED = "NodeTree already locked.";
+char *TobyLanguage::NODETREE_ULOCKED = "NodeTree already unlocked.";
+char *TobyLanguage::BAD_CHILD_NODE  = "Adding bad child type to NodeTree";
+char *TobyLanguage::USING_FREE_NODE = "Attempt to use NodeTree"
+                                      " that has already called"
+                                      " freeResources()!";
+
+char *TobyLanguage::NEW_PROGRAM = "new program";
+char *TobyLanguage::PLEASE_CONFIRM = "Whoa!";
+char *TobyLanguage::SAVE_MODIFIED_PROG = "Save modified program?";
+char *TobyLanguage::FILE_NOT_FOUND = "File \"%0\" not found.";
+char *TobyLanguage::CANNOT_LOAD_FILE = "Cannot load file \"%0\".";
+char *TobyLanguage::FILE_EXISTS = "File exists";
+char *TobyLanguage::OVERWRITE_FILENAME = "Overwrite \"%0\"?";
+char *TobyLanguage::CANNOT_WRITE_TO = "Cannot write to \"%0\".";
+
+char *TobyLanguage::TOOMANYFILES = "More than one file specified on"
+                                   " commandline! Just using the first one.";
+
+char *TobyLanguage::REPLACE_FORMAT_ERR =
+                        "Format string contains no \"%\" sequence!";
+char *TobyLanguage::REPLACE_RANGE_ERR =
+                        "Replace index must be between (0) and (9).";
+
+char *TobyLanguage::NO_GUI1 = "There was an error while starting the"
+                              " graphics engine...";
+char *TobyLanguage::NO_GUI2 = " Chances are, you don't have the GUI support"
+                              " you need. Please start";
+char *TobyLanguage::NO_GUI3 = " your Window system before running"
+                              " this program.";
+
+char *TobyLanguage::HERES_THE_ERR = "For record, here's the error:";
+
+char *TobyLanguage::TOBY_FILE_DESCRIPTION = "TOBY source code";
+
+char *TobyLanguage::CARET_POSITION = "line %0, column %1";
+
+char *TobyLanguage::ERR_IN_FUNC = "%0 on line %1 in function %2";
+char *TobyLanguage::ERR_OUT_FUNC = "%0 on line %1";
+
+char *TobyLanguage::SHOULDNOTBE = "This should not happen."
+                                  " Email icculus@linuxgames.com!"
+                                  " (English only!)";
+
+        // Menuitems...
+char *TobyLanguage::MENUNAME_FILE   = "File";
+char *TobyLanguage::MENUITEM_NEW    = "New";
+char *TobyLanguage::MENUITEM_OPEN   = "Open...";
+char *TobyLanguage::MENUITEM_SAVE   = "Save";
+char *TobyLanguage::MENUITEM_SAVEAS = "Save as...";
+char *TobyLanguage::MENUITEM_PRINT  = "Print...";
+char *TobyLanguage::MENUITEM_QUIT   = "Quit";
+
+char *TobyLanguage::MENUNAME_HELP  = "Help";
+char *TobyLanguage::MENUITEM_HELP  = "Help...";
+char *TobyLanguage::MENUITEM_ABOUT = "About...";
+
+char *TobyLanguage::MENUNAME_RUN       = "Run";
+char *TobyLanguage::MENUITEM_STARTCODE = "Start program";
+char *TobyLanguage::MENUITEM_STOPCODE  = "Stop program";
+char *TobyLanguage::MENUITEM_CLEAR     = "Cleanup TurtleSpace";
+
+char *TobyLanguage::MENUNAME_DEBUG     = "Debug";
+char *TobyLanguage::MENUITEM_TRACE     = "Trace";
+char *TobyLanguage::MENUITEM_STEP      = "Step";
+char *TobyLanguage::MENUITEM_WATCHVARS = "Watch variables";
+
+
+        // Constants representing error messages...
+char *TobyLanguage::INTERNAL_ERROR  = "Internal error";
+char *TobyLanguage::EXPECTED_TOKEN  = "Expected token";
+char *TobyLanguage::SYNTAX_ERROR    = "Syntax error";
+char *TobyLanguage::BAD_ASSIGNMENT  = "Assignment not allowed";
+char *TobyLanguage::DOUBLE_DEF      = "Duplicate definition";
+char *TobyLanguage::ORPHAN_CODE     = "Code outside function";
+char *TobyLanguage::BAD_TYPE        = "Bad variable type";
+char *TobyLanguage::NOT_VAR         = "Expected variable";
+char *TobyLanguage::NO_MAINLINE     = "Expected mainline";
+char *TobyLanguage::NO_RPAREN       = "Expected \")\"";
+char *TobyLanguage::NO_LPAREN       = "Expected \"(\"";
+char *TobyLanguage::NO_ASSIGN       = "Expected \"=\"";
+char *TobyLanguage::NOT_A_FUNC      = "Undefined function";
+char *TobyLanguage::BADNUM_ARGS     = "Wrong arguments";
+char *TobyLanguage::BAD_IDENT       = "Invalid identifier";
+char *TobyLanguage::NO_ENDFOR       = "FOR without ENDFOR";
+char *TobyLanguage::NO_FOR          = "ENDFOR without FOR";
+char *TobyLanguage::NO_ENDWHILE     = "WHILE without ENDWHILE";
+char *TobyLanguage::NO_WHILE        = "ENDWHILE without WHILE";
+char *TobyLanguage::ORPHAN_ELIF     = "ELSEIF without IF";
+char *TobyLanguage::ORPHAN_ELSE     = "ELSE without IF";
+char *TobyLanguage::ORPHAN_ENDIF    = "ENDIF without IF";
+char *TobyLanguage::TYPE_MMATCH     = "Type mismatch";
+char *TobyLanguage::BAD_ARGUMENT    = "Invalid argument";
+char *TobyLanguage::MAIN_RETVAL     = "MAIN returns a value";
+char *TobyLanguage::BAD_GLOBAL      = "Expected variable or FUNCTION";
+char *TobyLanguage::EXPECTED_END    = "Expected ENDFUNCTION";
+char *TobyLanguage::NO_RETTYPE      = "Expected RETURNS";
+char *TobyLanguage::ELIF_AFTER_ELSE = "ELSEIF after ELSE";
+char *TobyLanguage::ELSE_AFTER_ELSE = "Multiple ELSE statements";
+char *TobyLanguage::NO_VAR_DECL     = "Can't declare variables here";
+char *TobyLanguage::FUNC_IN_FUNC    = "FUNCTION within function";
+char *TobyLanguage::DIV_BY_ZERO     = "Division by zero";
+char *TobyLanguage::NOCURTURTLE     = "No current turtle";
+char *TobyLanguage::TURTLE_FENCED   = "Turtle past fence";
+char *TobyLanguage::OUT_OF_RANGE    = "Out of range";
+char *TobyLanguage::OVERFLOW        = "Overflow";
+char *TobyLanguage::NOT_AN_ARRAY    = "Expected array";
+char *TobyLanguage::NO_RARRAY       = "Expected \"]\"";
+char *TobyLanguage::NO_LARRAY       = "Expected \"[\"";
+char *TobyLanguage::NOT_WHOLE_NUM   = "Expected whole number";
+
+char *TobyLanguage::LANGIOEXCEPT    = "LANGUAGE: IOException reading"
+                                      " language data.";
+char *TobyLanguage::LANGBOGUSLINE   = "LANGUAGE: Line %0 is bogus in %1.";
+char *TobyLanguage::LANGNOSUCHCLASS = "LANGUAGE: No such class [%0] on"
+                                      " line %1 in %2.";
+char *TobyLanguage::LANGNOSUCHFIELD = "LANGUAGE: No such field [%0] on"
+                                      " line %1 in %2.";
+char *TobyLanguage::LANGNOTPUBLIC   = "LANGUAGE: Field [%0] is not"
+                                      " on line %1 in %2.";
+char *TobyLanguage::LANGNOTSTATIC   = "LANGUAGE: Field [%0] is not"
+                                      " on line %1 in %2.";
+char *TobyLanguage::LANGNOTSTRING   = "LANGUAGE: Field [%0] is not"
+                                      " a string on line %1 in %2.";
+char *TobyLanguage::LANGISFINAL     = "LANGUAGE: Field [%0] is final"
+                                      " on line %1 in %2.";
+char *TobyLanguage::LANGSETFAILED   = "LANGUAGE: Setting field [%0] "
+                                      " failed with message [%1]"
+                                      " on line %2 in %3.";
+
+// end of TobyLanguage.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyLanguage.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,335 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYLANGUAGE_H_
+#define _INCLUDE_TOBYLANGUAGE_H_
+
+#include "util/TobyObject.h"
+
+/*
+ *  This class contains all the literal strings used throughout Toby.
+ *   By keeping these all in one place, it becomes trivial to change
+ *   not only individual text within the program, but also the entire
+ *   language.
+ *
+ *  To use a different language than English, just specify
+ *    --langfile=/path/langfile or --langfile=url://hostname/path/langfile
+ *    on the command line.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyLanguage
+{
+private:
+    TobyLanguage(void) {}   // prevent public construction.
+
+public:
+    static char *NAME;
+    static char *USAGE;
+    static char *TRANSLATION_BY;
+    static char *WRITTENBY;
+    static char *COPYRIGHT;
+    static char *ERROR;
+    static char *NOT_YET_IMPLEMENTED;
+    static char *NODETREE_LOCKED;
+    static char *NODETREE_ULOCKED;
+    static char *BAD_CHILD_NODE;
+    static char *USING_FREE_NODE;
+    static char *NEW_PROGRAM;
+    static char *PLEASE_CONFIRM;
+    static char *SAVE_MODIFIED_PROG;
+    static char *FILE_NOT_FOUND;
+    static char *CANNOT_LOAD_FILE;
+    static char *FILE_EXISTS;
+    static char *OVERWRITE_FILENAME;
+    static char *CANNOT_WRITE_TO;
+    static char *TOOMANYFILES;
+    static char *REPLACE_FORMAT_ERR;
+    static char *REPLACE_RANGE_ERR;
+    static char *NO_GUI1;
+    static char *NO_GUI2;
+    static char *NO_GUI3;
+    static char *HERES_THE_ERR;
+    static char *TOBY_FILE_DESCRIPTION;
+    static char *CARET_POSITION;
+    static char *ERR_IN_FUNC;
+    static char *ERR_OUT_FUNC;
+    static char *SHOULDNOTBE;
+    static char *MENUNAME_FILE;
+    static char *MENUITEM_NEW;
+    static char *MENUITEM_OPEN;
+    static char *MENUITEM_SAVE;
+    static char *MENUITEM_SAVEAS;
+    static char *MENUITEM_PRINT;
+    static char *MENUITEM_QUIT;
+    static char *MENUNAME_HELP;
+    static char *MENUITEM_HELP;
+    static char *MENUITEM_ABOUT;
+    static char *MENUNAME_RUN;
+    static char *MENUITEM_STARTCODE;
+    static char *MENUITEM_STOPCODE;
+    static char *MENUITEM_CLEAR;
+    static char *MENUNAME_DEBUG;
+    static char *MENUITEM_TRACE;
+    static char *MENUITEM_STEP;
+    static char *MENUITEM_WATCHVARS;
+    static char *INTERNAL_ERROR;
+    static char *EXPECTED_TOKEN;
+    static char *SYNTAX_ERROR;
+    static char *BAD_ASSIGNMENT;
+    static char *DOUBLE_DEF;
+    static char *ORPHAN_CODE;
+    static char *BAD_TYPE;
+    static char *NOT_VAR;
+    static char *NO_MAINLINE;
+    static char *NO_RPAREN;
+    static char *NO_LPAREN;
+    static char *NO_ASSIGN;
+    static char *NOT_A_FUNC;
+    static char *BADNUM_ARGS;
+    static char *BAD_IDENT;
+    static char *NO_ENDFOR;
+    static char *NO_FOR;
+    static char *NO_ENDWHILE;
+    static char *NO_WHILE;
+    static char *ORPHAN_ELIF;
+    static char *ORPHAN_ELSE;
+    static char *ORPHAN_ENDIF;
+    static char *TYPE_MMATCH;
+    static char *BAD_ARGUMENT;
+    static char *MAIN_RETVAL;
+    static char *BAD_GLOBAL;
+    static char *EXPECTED_END;
+    static char *NO_RETTYPE;
+    static char *ELIF_AFTER_ELSE;
+    static char *ELSE_AFTER_ELSE;
+    static char *NO_VAR_DECL;
+    static char *FUNC_IN_FUNC;
+    static char *DIV_BY_ZERO;
+    static char *NOCURTURTLE;
+    static char *TURTLE_FENCED;
+    static char *OUT_OF_RANGE;
+    static char *OVERFLOW;
+    static char *NOT_AN_ARRAY;
+    static char *NO_RARRAY;
+    static char *NO_LARRAY;
+    static char *NOT_WHOLE_NUM;
+    static char *LANGIOEXCEPT;
+    static char *LANGBOGUSLINE;
+    static char *LANGNOSUCHCLASS;
+    static char *LANGNOSUCHFIELD;
+    static char *LANGNOTPUBLIC;
+    static char *LANGNOTSTATIC;
+    static char *LANGNOTSTRING;
+    static char *LANGISFINAL;
+    static char *LANGSETFAILED;
+
+
+#if 0
+// !!! PUT THIS BACK IN!
+
+        /*
+         * Read a string from a langfile. This will read until a non-blank
+         *  line that isn't a comment is found.
+         *
+         *    params: ir == InputReader that is reading a langfile.
+         *   returns: char *in a given language.
+         *  @exception IOException on i/o errors.
+         */
+    static String readLangString(InputReader ir) throw (IOException)
+    {
+        String retVal = null;
+
+        do
+        {
+            retVal = br.readLine();
+
+            if (retVal == null)
+                return(null);
+
+            retVal = retVal.trim();
+            if ((retVal.length() > 0) && (retVal.charAt(0) != '#'))
+                return(retVal);
+
+        } while (true);
+    } // readLangString
+
+
+    static Class retrieveLangClass(String cName, int line, String file)
+    {
+        Class retVal = null;
+        try
+        {
+            retVal = Class.forName(cName);
+        } // try
+        catch (ClassNotFoundException cnfe)
+        {
+            String s = TobyLanguage.LANGNOSUCHCLASS;
+            s = replaceFmtTokenInStr(0, s, cName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+        } // catch
+
+        return(retVal);
+    } // retrieveLangClass
+
+
+    static Field retrieveLangField(Class c, String fName,
+                                            int line, String file)
+    {
+        Field retVal = null;
+
+        try
+        {
+            retVal = c.getField(fName);
+        } // try
+        catch (NoSuchFieldException nsfe)
+        {
+            String s = TobyLanguage.LANGNOSUCHFIELD;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+            return(null);
+        } // catch
+
+        int mods = retVal.getModifiers();
+
+        if (java.lang.reflect.Modifier.isPublic(mods) == false)
+        {
+            String s = TobyLanguage.LANGNOTPUBLIC;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+            return(null);
+        } // if
+
+        else if (java.lang.reflect.Modifier.isStatic(mods) == false)
+        {
+            String s = TobyLanguage.LANGNOTSTATIC;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+            return(null);
+        } // else if
+
+        else if (java.lang.reflect.Modifier.isFinal(mods) == true)
+        {
+            String s = TobyLanguage.LANGISFINAL;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+            return(null);
+        } // else if
+
+        else if (retVal.getType().getName().equals("java.lang.String") == false)
+        {
+            String s = TobyLanguage.LANGNOTSTRING;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, line);
+            s = replaceFmtTokenInStr(2, s, file);
+            System.err.println(s);
+            return(null);
+        } // else if
+
+        return(retVal);
+    } // retrieveLangField
+
+
+    static boolean setLangField(String cName, String fName, String val,
+                                        int line, String file)
+    {
+        Class c = retrieveLangClass(cName, line, file);
+        if (c == null)
+            return(false);
+
+        Field f = retrieveLangField(c, fName, line, file);
+        if (f == null)
+            return(false);
+
+        try
+        {
+            f.set(null, val);
+        } // try
+        catch (Exception e)
+        {
+            String s = TobyLanguage.LANGSETFAILED;
+            s = replaceFmtTokenInStr(0, s, fName);
+            s = replaceFmtTokenInStr(1, s, e.getMessage());
+            s = replaceFmtTokenInStr(2, s, line);
+            s = replaceFmtTokenInStr(3, s, file);
+            System.err.println(s);
+            return(false);
+        } // catch
+
+        return(true);
+    } // setLangField
+
+
+    static void reportBogusLangLine(int lineNum, String fname)
+    {
+        String s = TobyLanguage.LANGBOGUSLINE;
+        s = replaceFmtTokenInStr(0, s, lineNum);
+        s = replaceFmtTokenInStr(1, s, fname);
+        System.err.println(s);
+    } // reportBogusLangLine
+
+
+    static void loadLangFile(LineNumberReader lnr, String file) throws IOException
+    {
+        String langString = null;
+
+        while ( (langString = readLangString(lnr)) != null )
+        {
+            int pos = langString.indexOf('=');
+            int line = lnr.getLineNumber();
+            if (pos == -1)
+            {
+                reportBogusLangLine(line, file);
+                continue;
+            } // if
+
+            String fullName = langString.substring(0, pos).trim();
+            String value = langString.substring(pos + 1).trim();
+
+            pos = fullName.lastIndexOf('.');
+            if (pos == -1)
+            {
+                reportBogusLangLine(line, file);
+                continue;
+            } // if
+
+            String className = fullName.substring(0, pos);
+            String fieldName = fullName.substring(pos + 1);
+
+            setLangField(className, fieldName, value, line, file);
+        } // while
+    } // loadLangFile
+#endif
+
+}; // class TobyLanguage
+
+#endif  // !defined _INCLUDE_TOBYLANGUAGE_H_
+
+// end of TobyLanguage.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyMutex.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,46 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYMUTEX_H_
+#define _INCLUDE_TOBYMUTEX_H_
+
+#include "util/TobyObject.h"
+
+/*
+ *  An abstraction over platform-specific threading mutexes.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyMutex : public TobyObject
+{
+public:
+    TobyMutex(void) {}
+    virtual ~TobyMutex(void) {}
+    virtual void request(void) = 0;
+    virtual void release(void) = 0;
+}; // class TobyMutex
+
+
+// This gets filled in along with the platform-specific subclass...
+TobyMutex *__platformBuildMutex(void);
+
+#endif // !defined _INCLUDE_TOBYMUTEX_H_
+
+// end of TobyMutex.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyObject.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,58 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYOBJECT_H_
+#define _INCLUDE_TOBYOBJECT_H_
+
+#include <stdio.h>   // ...gotta have my printf.  :)
+#include <stdlib.h>  // make sure NULL is always defined.
+#include <assert.h>  // make sure assert() is always defined.
+
+// !!! This needs to change.
+typedef signed long    toby_sint32;
+typedef unsigned long  toby_uint32;
+typedef signed short   toby_sint16;
+typedef unsigned short toby_uint16;
+typedef signed char    toby_sint8;
+typedef unsigned char  toby_uint8;
+
+
+#if (defined DEBUG)
+#define _D(x) printf x;
+#else
+#define _D(x)
+#endif
+
+
+/*
+ * This is a common base class for all other Toby class.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyObject
+{
+
+    // !!! assert(0) in the copy constructor.
+
+}; // class TobyObject
+
+#endif  // !defined _INCLUDE_TOBYOBJECT_H_
+
+// end of TobyObject.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyStack.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,35 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "util/TobyStack.h"
+
+void TobyStack::push(TobyObject *elem)
+{
+    insertElement(elem, 0);
+} // TobyStack::push
+
+
+TobyObject *TobyStack::pop(void)
+{
+    return(remove(0));
+} // TobyStack::pop
+
+// end of TobyStack.cpp ...
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyStack.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,42 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYSTACK_H_
+#define _INCLUDE_TOBYSTACK_H_
+
+#include "util/TobyCollection.h"
+
+/*
+ * This is a general object stack. First in, last out.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyStack : public TobyCollection
+{
+public:
+//    TobyStack(void);
+//    virtual ~TobyStack(void);
+    virtual void push(TobyObject *elem);
+    virtual TobyObject *pop(void);
+}; // class TobyStack
+
+#endif  // !defined _INCLUDE_TOBYSTACK_H_
+
+// end of TobyStack.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyString.cpp	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,98 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include "util/TobyString.h"
+
+TobyString::TobyString(void) : str(NULL)
+{
+    assignCStr("");
+} // Constructor
+
+TobyString::TobyString(const char *_str) : str(NULL)
+{
+    assignCStr("");
+} // Constructor
+
+TobyString::TobyString(const TobyString *_str) : str(NULL)
+{
+    assignCStr(_str->c_str());
+} // Constructor
+
+TobyString::~TobyString(void)
+{
+    if (str != NULL)
+        free(str);
+} // Destructor
+
+const char *TobyString::c_str(void) const
+{
+    return(str);   // READ. ONLY.
+} // TobyString::c_str
+
+#if 0
+// !!!
+char *TobyString::operator char *(void)
+{
+    return((const char *) str);
+} // TobyString::operator char *
+#endif
+
+void TobyString::assignCStr(const char *_str)
+{
+    if (_str == NULL)
+        _str = "";
+
+    str = (char *) realloc(str, strlen(_str) + 1);
+    strcpy(str, _str);
+} // assignCStr
+
+
+bool TobyString::replaceFormatToken(int n, const char *val)
+{
+    assert(val != NULL);
+    assert((n >= 0) && (n <= 9));
+
+    char token[3] = {'%', '0' + n, '\0'};
+    char *ptr;
+
+    ptr = strstr(str, token);
+    if (ptr == NULL)
+        return(false);
+
+    char *buf = new char[strlen(str) + strlen(val) + 1];
+    *ptr = '\0';  // chop string at "%n".
+    strcpy(buf, str);
+    strcat(buf, val);
+    strcat(buf, ptr + 2);
+    assignCStr(buf);
+    delete[] buf;
+
+    return(true);
+} // TobyString::replaceFormatToken
+
+
+bool TobyString::replaceFormatToken(int n, int val)
+{
+    char buf[128];
+    snprintf(buf, sizeof (buf), "%d", val);
+    return(replaceFormatToken(n, buf));
+} // TobyString::replaceFormatToken
+
+// end of TobyString.cpp ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyString.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,57 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYSTRING_H_
+#define _INCLUDE_TOBYSTRING_H_
+
+#include <stdio.h>
+#include <string.h>
+#include "util/TobyObject.h"
+
+/*
+ * This is a relatively minimal string class, for dealing with the
+ *  ugliness of string memory management.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyString : public TobyObject
+{
+public:
+    TobyString(void);
+    TobyString(const char *_str);
+    TobyString(const TobyString *_str);
+
+    virtual ~TobyString(void);
+
+    const char *c_str(void) const;
+    //char * operator char *(void);
+
+    bool replaceFormatToken(int n, const char *val);
+    bool replaceFormatToken(int n, int val);
+
+    void assignCStr(const char *str);
+
+private:
+    char *str;
+}; // class TobyString
+
+#endif  // !defined _INCLUDE_TOBYSTRING_H_
+
+// end of TobyString.h ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/util/TobyThread.h	Wed Apr 18 23:47:38 2001 +0000
@@ -0,0 +1,52 @@
+/*
+ * TOBY -- An abstract interpreter engine and system for learning.
+ * Copyright (C) 1999  Ryan C. Gordon.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef _INCLUDE_TOBYTHREAD_H_
+#define _INCLUDE_TOBYTHREAD_H_
+
+#include "util/TobyObject.h"
+
+/*
+ *  An abstraction over platform-specific threads: multiple contexts of
+ *   execution in the same process space, sharing resources.
+ *
+ *     Written by Ryan C. Gordon. (icculus@linuxgames.com)
+ */
+class TobyThread : public TobyObject
+{
+public:
+    TobyThread(void) {}
+    virtual ~TobyThread(void) {}
+    virtual void start(void *(*runfunc)(void *)) = 0;
+    virtual void waitForTermination(void) = 0;
+    virtual bool isTerminated(void) = 0;
+}; // class TobyThread
+
+
+// This gets filled in along with the platform-specific subclass...
+TobyThread *__platformBuildThread(void);
+
+// This gets called to yield the currently executing thread, which may be the
+//  main thread, for which no corresponding TobyThread exists.
+void __platformThreadYieldCurrent(void);
+
+#endif // !defined _INCLUDE_TOBYTHREAD_H_
+
+// end of TobyThread.h ...
+