diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..bed31158b81b150c55fb035eb2328ed3ece708d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+.config
+InstalledFiles
+FXRuby.spec
+scripts/make-installers.rb
+*.iss
+*.iss.in
+doap.rdf
+Makefile
+*.tmproj
+doc/api
+doc/*.html
+ext/fox16/*_wrap.cpp
+ext/fox16/*.o
+ext/fox16/conftest.dSYM
+ext/fox16/include/inlinestubs.h
+ext/fox16/librb.c
+ext/fox16/extconf.rb
+ext/fox16/fox16.bundle
+ext/fox16/mkmf.log
+lib/fox16/version.rb
+lib/fox16/kwargs.rb
+pre-config.rb
+swig-interfaces/dependencies
diff --git a/Rakefile b/Rakefile
index 34bbe01878d08fdfa1a0c9940b77fbc964727f50..9483fc640ff296ff717bccc1cb0deeb3b3ac0bc5 100755
--- a/Rakefile
+++ b/Rakefile
@@ -1,13 +1,16 @@
-require 'hoe'
+require 'date'
+require 'rake/gempackagetask'
+require 'rake/rdoctask'
+require 'rake/testtask'
 
 # FXRuby version number
-PKG_VERSION = "1.6.6"
+PKG_VERSION = "1.6.18"
 
 # Minimum version of FOX required for compatibility
 FOX_VERSION = "1.6.0"
 
 # Path to local installation of FOX (Windows only)
-FOX_INSTALL_DIR = "c:\\src\\fox-1.6.20"
+FOX_INSTALL_DIR = "e:\\src\\fox-1.6.33"
 
 # Path to local installation of FXScintilla (Windows only)
 FXSCINTILLA_INSTALL_DIR = "c:\\src\\fxscintilla"
@@ -15,32 +18,6 @@ FXSCINTILLA_INSTALL_DIR = "c:\\src\\fxscintilla"
 # Path to local installation of InnoSetup command-line compiler
 ISCC = "C:\\Progra~1\\InnoSe~1\\ISCC.exe"
 
-# Generate Hoe tasks
-=begin
-Hoe.new('FXRuby', PKG_VERSION) do |p|
-  p.url = "http://www.fxruby.org/"
-  p.author = "Lyle Johnson"
-  p.email = "lyle@rubyforge.org"
-  p.changes = "See the change history at http://www.fxruby.org/doc/changes.html"
-  p.description = "FXRuby is the Ruby binding to the FOX GUI toolkit."
-  p.summary = "FXRuby is the Ruby binding to the FOX GUI toolkit."
-  p.clean_globs = %w{config.save InstalledFiles ext/**/*.o ext/**/*.bundle}
-  p.test_globs = ['tests/**/TC_*.rb']
-  p.rdoc_pattern = /^(lib|bin)|txt$/
-  p.extra_deps = []
-  p.spec_extras = {}
-  p.need_tar = true
-  p.need_zip = false
-  p.spec_extras = {
-    'require_paths' => ['ext/fox16', 'lib'],
-    'rdoc_options' => ['--main', File.join('rdoc-sources', 'README.rdoc'), '--exclude', 'ext/fox16'],
-    'extensions' => ["ext/fox16/extconf.rb"],
-    'extra_rdoc_files' => ['rdoc-sources', File.join('rdoc-sources', 'README.rdoc')],
-    'test_suite_file' => "tests/TS_All.rb"
-  }
-end
-=end
-
 DISTFILES = [
   "ANNOUNCE",
   "LICENSE",
@@ -49,10 +26,7 @@ DISTFILES = [
   "pre-config.rb",
   "install.rb",
   "doap.rdf",
-  "FXRuby-ruby1.6-i586-mswin32.iss",
-  "FXRuby-ruby1.8.2-i386-msvcrt.iss",
-  "FXRuby-ruby1.8.4-i386-msvcrt.iss",
-  "FXRuby-ruby1.8.5-i386-msvcrt.iss",
+  "FXRuby-ruby1.8.6-i386-msvcrt.iss",
   "Rakefile",
   "index.html",
   "doc/*.css",
@@ -77,10 +51,6 @@ DISTFILES = [
   "tests/README",
   "tests/*.rb",
   "tests/*.ps",
-  "web/*.html",
-  "web/*.css",
-  "web/art/*.png",
-  "web/art/*.gif",
   "rdoc-sources/*.rb",
   "rdoc-sources/README.rdoc",
   "scripts/make-installers.rb"
@@ -90,7 +60,7 @@ def distdir
   "FXRuby-#{PKG_VERSION}"
 end
 
-task :distdir => [:swig, :docs, :setversions] do
+task :distdir => [:swig, :docs, :setversions, :generate_kwargs_lib] do
   rm_rf "#{distdir}"
   mkdir "#{distdir}"
   chmod(0777, distdir)
@@ -111,6 +81,7 @@ task :distdir => [:swig, :docs, :setversions] do
   rm_f "#{distdir}/examples/rapt-gui.rb"
   rm_f "#{distdir}/examples/WhatAQuietStiff.rb"
   rm_f "#{distdir}/examples/gembrowser.rb"
+  rm_f "#{distdir}/examples/rmagick.rb"
   rm_f "#{distdir}/examples/tablenew.rb"
 end
 
@@ -141,9 +112,12 @@ task :website => [:doap] do
   system %{scp -Cq doc/*.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby/1.6/doc}
   system %{scp -Cq doc/images/*.png lyle@rubyforge.org:/var/www/gforge-projects/fxruby/1.6/doc/images}
   system %{scp -Cq examples/*.rb lyle@rubyforge.org:/var/www/gforge-projects/fxruby/1.6/examples}
-  system %{scp -Cq index.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby}
-  system %{scp -Cq web/*.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby/web}
-  system %{scp -Cq web/art/*.gif web/art/*.png lyle@rubyforge.org:/var/www/gforge-projects/fxruby/web/art}
+  system %{scp -Cq web/index.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby}
+  system %{scp -Cq web/community.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby}
+  system %{scp -Cq web/documentation.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby}
+  system %{scp -Cq web/downloads.html lyle@rubyforge.org:/var/www/gforge-projects/fxruby}
+  system %{scp -Cq web/images/* lyle@rubyforge.org:/var/www/gforge-projects/fxruby/images}
+  system %{scp -Cq web/css/*.css lyle@rubyforge.org:/var/www/gforge-projects/fxruby/css}
 end
 
 desc "Upload the DOAP file to the Web site"
@@ -153,7 +127,40 @@ end
 
 desc "Upload the RDocs"
 task :upload_rdoc do
-  system %{scp -Cqr doc/api lyle@rubyforge.org:/var/www/gforge-projects/fxruby/1.6/doc}
+# system %{scp -Cqr doc/api lyle@rubyforge.org:/var/www/gforge-projects/fxruby/1.6/doc}
+  host = "lyle@rubyforge.org"
+  remote_dir = "/var/www/gforge-projects/fxruby/doc/api"
+  local_dir = 'doc/api'
+  sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
+end
+
+desc "Upload release files to RubyForge"
+task :rubyforge do
+  require 'rubyforge'
+  rubyforge = RubyForge.new
+  rubyforge.login
+  if PLATFORM =~ /mswin32/
+    rubyforge.userconfig['processor_id'] = 'i386'
+    rubyforge.add_file    "fxruby", "FXRuby 1.6", PKG_VERSION, "fxruby-#{PKG_VERSION}-mswin32.gem"
+    rubyforge.add_file    "fxruby", "FXRuby 1.6", PKG_VERSION, "FXRuby-#{PKG_VERSION}-ruby186.exe"
+  else
+    rubyforge.add_release "fxruby", "FXRuby 1.6", PKG_VERSION, "FXRuby-#{PKG_VERSION}.tar.gz"
+    rubyforge.add_file    "fxruby", "FXRuby 1.6", PKG_VERSION, "fxruby-#{PKG_VERSION}.gem"
+  end
+# rubyforge add_release      fxruby "FXRuby 1.6" "1.6.9" FXRuby-1.6.9.tar.gz
+# rubyforge add_file         fxruby "FXRuby 1.6" "1.6.9" fxruby-1.6.9.gem
+# rubyforge add_file -o i386 fxruby "FXRuby 1.6" "1.6.9" fxruby-1.6.9-mswin32.gem
+# rubyforge add_file -o i386 fxruby "FXRuby 1.6" "1.6.9" FXRuby-1.6.9-ruby186.exe
+end
+
+desc "Tag this release in Subversion"
+task :tag do
+  require 'rexml/document'
+  doc = REXML::Document.new(`svn info --xml`)
+  branch = doc.get_elements("/info/entry/url").first.text
+  root   = doc.get_elements("/info/entry/repository/root").first.text
+  tag = root + "/tags/REL-#{PKG_VERSION}"
+  sh %{svn copy -m "Created tag for version #{PKG_VERSION}" #{branch} #{tag}}
 end
 
 desc "Generate all of the documentation files."
@@ -180,6 +187,7 @@ Rake::RDocTask.new do |rdoc|
                       "lib/fox16/glshapes.rb",
                       "lib/fox16/input.rb",
                       "lib/fox16/iterators.rb",
+                      "lib/fox16/keys.rb",
                       "lib/fox16/responder2.rb",
                       "lib/fox16/scintilla.rb",
                       "lib/fox16/signal.rb",
@@ -200,6 +208,11 @@ end
 
 desc "Clean"
 task :clean do
+  rm_rf "ext/fox16/Makefile"
+  rm_rf FileList["ext/fox16/*.o"]
+  rm_rf FileList["ext/fox16/*.bundle"]
+  rm_rf "ext/fox16/mkmf.log"
+  rm_rf "ext/fox16/conftest.dSYM"
   ruby "install.rb clean"
 end
 
@@ -210,10 +223,11 @@ def make_impl
 end
 
 task :configure => [:scintilla, :setversions, :generate_kwargs_lib] do
-  unless File.exist?("config.save")
+  unless File.exist?(".config")
 #   ruby "install.rb config -- --with-fxscintilla-include=/usr/include/fxscintilla --with-fxscintilla-lib=/usr/lib"
 #   ruby "install.rb config -- --without-fxscintilla"
-    ruby "install.rb config"
+#   ruby "install.rb config -- --with-fox-include=/opt/local/include/fox-1.6 --with-fox-lib=/opt/local/lib --with-fxscintilla-include=/opt/local/include/fxscintilla --with-fxscintilla-lib=/opt/local/lib"
+    ruby "install.rb config -- --with-fox-include=/usr/local/include/fox-1.6 --with-fox-lib=/usr/local/lib --with-fxscintilla-include=/usr/local/include/fxscintilla --with-fxscintilla-lib=/usr/local/lib"
     make_impl
   end
 end
@@ -253,10 +267,7 @@ task :setversions => [ :create_installer_scripts ] do
   setversions("Makefile")
   setversions("pre-config.rb")
   setversions("ext/fox16/extconf.rb")
-  setversions("FXRuby-ruby1.6-i586-mswin32.iss")
-  setversions("FXRuby-ruby1.8.2-i386-msvcrt.iss")
-  setversions("FXRuby-ruby1.8.4-i386-msvcrt.iss")
-  setversions("FXRuby-ruby1.8.5-i386-msvcrt.iss")
+  setversions("FXRuby-ruby1.8.6-i386-msvcrt.iss")
   setversions("lib/fox16/version.rb")
   setversions("doap.rdf")
   setversions("scripts/make-installers.rb")
@@ -265,10 +276,7 @@ end
 desc "Create INNO Setup Installer Scripts from Template"
 task :create_installer_scripts do
   output_filenames = {
-    "FXRuby-ruby1.6-i586-mswin32.iss.in" => ["1.6", "ruby168", "i586-mswin32"],
-    "FXRuby-ruby1.8.2-i386-msvcrt.iss.in" =>  ["1.8", "ruby182", "i386-msvcrt"],
-    "FXRuby-ruby1.8.4-i386-msvcrt.iss.in" =>  ["1.8", "ruby184", "i386-msvcrt"],
-    "FXRuby-ruby1.8.5-i386-msvcrt.iss.in" =>  ["1.8", "ruby185", "i386-msvcrt"]
+    "FXRuby-ruby1.8.6-i386-msvcrt.iss.in" =>  ["1.8", "ruby186", "i386-msvcrt"]
   }
 
   output_filenames.each do |output_filename, info|
@@ -285,15 +293,15 @@ task :create_installer_scripts do
 end
 
 # These library files aren't ready for distribution yet.
-COOKER_LIBS = %w{acceltable.rb bitmapview.rb canvas.rb html.rb sugar.rb tkcompat.rb}
+COOKER_LIBS = %w{acceltable.rb bitmapview.rb canvas.rb html.rb tkcompat.rb}
 
 # These example programs aren't ready for distribution yet.
-COOKER_EXAMPLES = %w{canvasdemo.rb WhatAQuietStiff.rb examples.rb gdchart.rb gembrowser.rb rapt-gui.rb tablenew.rb}
+COOKER_EXAMPLES = %w{canvasdemo.rb WhatAQuietStiff.rb examples.rb gdchart.rb gembrowser.rb rapt-gui.rb rmagick.rb tablenew.rb}
 
 # Return the Gem specification for the source Gem
 def create_gemspec
   pkg_files = [
-        "ANNOUNCE",
+  "ANNOUNCE",
 	"LICENSE",
 	"README",
 	"index.html",
@@ -337,7 +345,8 @@ def create_gemspec
     s.has_rdoc = true
     s.rdoc_options = [
                     '--main', File.join('rdoc-sources', 'README.rdoc'),
-                    '--exclude', 'ext/fox16'
+                    '--exclude', 'ext/fox16',
+                    '--exclude', %r{acceltable|aliases|bitmapview|canvas|html|kwargs|missingdep|responder|tkcompat}
                    ]
     s.extra_rdoc_files = [
                         'rdoc-sources',
@@ -347,7 +356,7 @@ def create_gemspec
     s.test_suite_file = "tests/TS_All.rb"
 
     s.author = "Lyle Johnson"
-    s.email = "lyle@knology.net"
+    s.email = "lyle.johnson@gmail.com"
     s.homepage = "http://www.fxruby.org"
   end
 end
@@ -370,7 +379,7 @@ end
 # Given the distribution tarball, build the installer for Win32
 desc "Build Win32 installer"
 task :build_win32 do
-  if File.exist? "config.save"
+  if File.exist? ".config"
     ruby "install.rb clean"
   end
   ruby "install.rb config --make-prog=nmake -- --with-fox-include=#{FOX_INSTALL_DIR}\\include --with-fox-lib=#{FOX_INSTALL_DIR}\\lib --with-fxscintilla-include=#{FXSCINTILLA_INSTALL_DIR}\\include --with-fxscintilla-lib=#{FXSCINTILLA_INSTALL_DIR}\\lib"
@@ -382,14 +391,14 @@ desc "Build Win32 installer using INNO Setup"
 task :build_win32_installer => [:build_win32] do
   iss_script_name = nil
   case VERSION
-    when /1.6/
-      iss_script_name = "FXRuby-ruby1.6-i586-mswin32.iss"
     when /1.8.2/
       iss_script_name = "FXRuby-ruby1.8.2-i386-msvcrt.iss"
     when /1.8.4/
       iss_script_name = "FXRuby-ruby1.8.4-i386-msvcrt.iss"
     when /1.8.5/
       iss_script_name = "FXRuby-ruby1.8.5-i386-msvcrt.iss"
+    when /1.8.6/
+      iss_script_name = "FXRuby-ruby1.8.6-i386-msvcrt.iss"
   end
   system(ISCC, iss_script_name)
 end
@@ -397,7 +406,7 @@ end
 desc "Build Win32 binary Gem"
 task :build_win32_gem => [:build_win32] do
   spec = create_gemspec
-  spec.platform = Gem::Platform::WIN32
+  spec.platform = Gem::Platform::CURRENT
   spec.files += ["ext/fox16/fox16.so"]
   Gem::Builder.new(spec).build
 end
@@ -406,10 +415,25 @@ desc "Build Win32 binary installer and Gem"
 task :release_win32 => [:build_win32_installer, :build_win32_gem] do
 end
 
+desc "Build Mac OS X binary Gem"
+task :build_macosx_gem do
+  raise RuntimeError, "remove libFOX*.dylib and recompile before building gem" unless Dir.glob("/usr/local/lib/libFOX*.dylib").empty?
+  spec = create_gemspec
+  spec.platform = Gem::Platform::CURRENT
+  spec.files += ["ext/fox16/fox16.bundle"]
+  Gem::Builder.new(spec).build
+end
+
 task :generate_kwargs_lib do
   ruby 'scripts/generate_kwargs_lib.rb'
 end
 
+Rake::TestTask.new do |t|
+  t.libs << "tests"
+  t.test_files = FileList["tests/TC_*.rb"]
+  t.verbose = true
+end
+
 # Default task is build
 task :default => [:build] do
 end
diff --git a/doc/Makefile b/doc/Makefile
index 00c4df5dae42f3f0b998d64f31b28b53a68354b6..b4fefeb10f6ff9665f99298250479ab01eaa5135 100755
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -4,10 +4,12 @@
 #
 ########################################################################
 
-SAXON = java -jar /Users/lyle/saxon-6.5.3/saxon.jar
+#SAXON = java -jar /Users/lyle/saxon-8.9/saxon8.jar
+SAXON = java -jar /Users/lyle/saxon-6.5.5/saxon.jar
 HTML_STYLESHEET = custom-html.xsl
-FO_STYLESHEET = custom-fo.xsl
-FOP = /Users/lyle/fop-0.20.4/fop.sh
+#FO_STYLESHEET = custom-fo.xsl
+FO_STYLESHEET = /Users/lyle/docbook/docbook5-xsl-1.72.0/fo/docbook.xsl
+FOP = /Users/lyle/fop-0.93/fop
 
 all: html
 
diff --git a/doc/book.xml b/doc/book.xml
index 53522edc821102bdc12b4c912df885180eca128d..e36a5527fe08ac318fa900348ec39e9c65f0be69 100755
--- a/doc/book.xml
+++ b/doc/book.xml
@@ -1,7 +1,7 @@
 <?xml version='1.0'?>
 <!DOCTYPE book
-  PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-  "file:/Users/lyle/docbook/xml/4.4/docbookx.dtd" [
+  PUBLIC "-//OASIS//DTD DocBook V5.0//EN"
+  "file:/Users/lyle/docbook/xml/5.0/dtd/docbook.dtd" [
 <!ENTITY bookinfo.xml SYSTEM "bookinfo.xml">
 <!ENTITY build.xml SYSTEM "build.xml">
 <!ENTITY changes.xml SYSTEM "changes.xml">
@@ -19,11 +19,10 @@
 <!ENTITY library.xml SYSTEM "library.xml">
 <!ENTITY opengl.xml SYSTEM "opengl.xml">
 <!ENTITY scintilla.xml SYSTEM "scintilla.xml">
-<!ENTITY todo.xml SYSTEM "todo.xml">
 <!ENTITY tutorial1.xml SYSTEM "tutorial1.xml">
 <!ENTITY unicode.xml SYSTEM "unicode.xml">
 ]>
-<book id="book" lang="en">
+<book id="book" lang="en" xmlns="http://docbook.org/ns/docbook">
 &bookinfo.xml;
 <part label="I">
 <title>The Basics</title>
@@ -37,7 +36,6 @@
 &examples.xml;
 &events.xml;
 <!--&layout.xml;-->
-&todo.xml;
 &infosources.xml;
 &changes.xml;
 </part>
diff --git a/doc/build.xml b/doc/build.xml
index 0db1915d11ba5f953ab4c825cadb355bc0ab0e9c..7eec0f577675fe5fb6f4be1c77b52c0f9d462e64 100755
--- a/doc/build.xml
+++ b/doc/build.xml
@@ -2,9 +2,11 @@
 <chapter id="build">
   <title>Building from Source Code</title>
 
-  <para>A few words of advice, before getting started:</para>
+  <para>This chapter provides instructions for building and installing FXRuby
+  directly from source, and not using some more direct means (such as
+  installing a gem, or via some package manager).</para>
 
-  <itemizedlist mark="bullet">
+  <itemizedlist>
     <listitem>
       <para>If you're planning to use FXRuby on Windows, with the standard
       <ulink url="http://rubyinstaller.rubyforge.org">Ruby Installer for
@@ -14,12 +16,9 @@
     </listitem>
 
     <listitem>
-      <para>If you're planning to use FXRuby on Mac OS X, you may want to
-      consult <ulink
-      url="http://www.fox-toolkit.net/cgi-bin/wiki.pl?Mac_OS_X">this
-      page</ulink> from the <ulink url="http://www.fox-toolkit.net">FOX
-      Community Wiki</ulink>, in addition to the standard build instructions
-      listed below.</para>
+      <para>If you're already using the <ulink
+      url="http://www.macports.org/">MacPorts</ulink> version of ruby, you may
+      wish to just install the <filename>rb-fxruby</filename> port.</para>
     </listitem>
   </itemizedlist>
 
@@ -30,10 +29,10 @@
     and installed FOX. Next, you'll need to download the FXRuby source code
     tarball and unpack it by typing:</para>
 
-    <screen>$ <command>tar xzf FXRuby-1.6.0.tar.gz</command></screen>
+    <screen>$ <command>tar xzf FXRuby-1.6.13.tar.gz</command></screen>
 
     <para>This will create a new directory called <filename
-    class="directory">FXRuby-1.6.0</filename>. Change to the top-level
+    class="directory">FXRuby-1.6.13</filename>. Change to the top-level
     directory and configure the build by typing:</para>
 
     <screen>$ <command>ruby install.rb config</command></screen>
@@ -46,8 +45,8 @@
     <filename>install.rb</filename> during this step, e.g.</para>
 
     <screen>$ <command>ruby install.rb config -- \
-    --with-fox-include=/home/lyle/fox-1.6.3/include \
-    --with-fox-lib=/home/lyle/fox-1.6.3/src/.libs</command></screen>
+    --with-fox-include=/home/lyle/fox-1.6.32/include \
+    --with-fox-lib=/home/lyle/fox-1.6.32/src/.libs</command></screen>
 
     <para>Once the build has been configured, you can start the build by
     typing:</para>
@@ -68,7 +67,7 @@
     probably fire up <filename>irb</filename> and try to import FXRuby:</para>
 
     <screen>$ <command>irb</command>
-irb(main):001:0&gt; <userinput>require 'fox'</userinput>
+irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
 true
 irb(main):002:0&gt;</screen>
 
@@ -91,16 +90,16 @@ irb(main):002:0&gt;</screen>
     instructions and build files distributed with the standard Ruby source
     code. To review, you should have started by unpacking the source code
     tarball, changing into the top-level source code directory (e.g. <filename
-    class="directory">C:\ruby-1.8.4</filename>) and then typing:</para>
+    class="directory">C:\ruby-1.8.6</filename>) and then typing:</para>
 
-    <screen>C:\ruby-1.8.4&gt;<command>win32\configure</command>
+    <screen>C:\ruby-1.8.6&gt;<command>win32\configure</command>
 type 'nmake' to make ruby for mswin32.
-C:\ruby-1.8.4&gt;<command>nmake</command></screen>
+C:\ruby-1.8.6&gt;<command>nmake</command></screen>
 
     <para>After the compilation finished, you installed Ruby somewhere by
     typing, e.g.,</para>
 
-    <screen>C:\ruby-1.8.4&gt;<command>nmake DESTDIR=C:\ruby install</command></screen>
+    <screen>C:\ruby-1.8.6&gt;<command>nmake DESTDIR=C:\ruby install</command></screen>
 
     <para>Similarly, I'm assuming that you built the FOX library using the
     Developer Studio project files distributed with the standard FOX source
@@ -108,14 +107,14 @@ C:\ruby-1.8.4&gt;<command>nmake</command></screen>
 
     <para>Now you can configure the FXRuby build by typing:</para>
 
-    <screen>C:\FXRuby-1.6.0&gt;<command>ruby install.rb config --make-prog=nmake -- \
-    --with-fox-include=C:\fox-1.6.3\include \
-    --with-fox-lib=C:\fox-1.6.3\lib</command></screen>
+    <screen>C:\FXRuby-1.6.13&gt;<command>ruby install.rb config --make-prog=nmake -- \
+    --with-fox-include=C:\fox-1.6.32\include \
+    --with-fox-lib=C:\fox-1.6.32\lib</command></screen>
 
     <para>Once the build has been configured, you can start the build by
     typing:</para>
 
-    <screen>C:\FXRuby-1.6.0&gt; <command>ruby install.rb setup</command></screen>
+    <screen>C:\FXRuby-1.6.13&gt; <command>ruby install.rb setup</command></screen>
 
     <para>It will take quite awhile to build FXRuby, even on a fast machine,
     so this might be a good time to take a coffee break. Because Visual C++ is
@@ -129,12 +128,12 @@ C:\ruby-1.8.4&gt;<command>nmake</command></screen>
 
     <para>Once it's finished compiling, install FXRuby by typing:</para>
 
-    <screen>C:\FXRuby-1.6.0&gt; <command>ruby install.rb install</command></screen>
+    <screen>C:\FXRuby-1.6.13&gt; <command>ruby install.rb install</command></screen>
 
     <para>As a quick sanity check, to make sure that all is well, you should
     probably fire up <filename>irb</filename> and try to import FXRuby:</para>
 
-    <screen>C:\FXRuby-1.6.0&gt; <command>irb</command>
+    <screen>C:\FXRuby-1.6.13&gt; <command>irb</command>
 irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
 true
 irb(main):002:0&gt;</screen>
@@ -232,34 +231,34 @@ core_wrap.cpp:108596: virtual memory exhausted</screen>
 
     <para>On Linux and other Unix systems that support shared libraries, FOX
     is typically installed as a shared library named
-    <filename>libFOX-1.4.so</filename>. After all of the source files for
+    <filename>libFOX-1.6.so</filename>. After all of the source files for
     FXRuby are compiled, the last step is to link all of the FXRuby object
     files together with the FOX library (and possibly other system libraries)
-    to produce a new shared library, named <filename>fox14.so</filename>, that
+    to produce a new shared library, named <filename>fox16.so</filename>, that
     Ruby can import as an extension module.</para>
 
     <para>There are a few things that can go wrong when you try to import this
     extension into Ruby. A common problem is that the operating system cannot
-    locate the FOX shared library (<filename>libFOX-1.4.so</filename>) when it
+    locate the FOX shared library (<filename>libFOX-1.6.so</filename>) when it
     tries to dynamically load the FXRuby extension module; when this happens,
     the error message will look something like:</para>
 
     <screen>$ <command>irb</command>
-irb(main):001:0&gt; <userinput>require 'fox'</userinput>
-LoadError: libFOX-0.99.so.173: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.6/i586-linux/fox.so
+irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
+LoadError: libFOX-1.6.so: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.8/i686-linux/fox16.so
         from (irb):1:in 'require'
         from (irb):1
     </screen>
 
     <para>One workaround for this problem is to modify the
     <constant>LD_LIBRARY_PATH</constant> environment variable to include the
-    directory where <filename>libFOX.so</filename> is installed. For example,
-    if <filename>libFOX-1.4.so</filename> is installed in <filename
+    directory where <filename>libFOX-1.6.so</filename> is installed. For
+    example, if <filename>libFOX-1.6.so</filename> is installed in <filename
     class="directory">/usr/local/lib</filename>, try setting:</para>
 
     <screen>$ <command>export LD_LIBRARY_PATH=/usr/local/lib</command>
 $ <command>irb</command>
-irb(main):001:0&gt; <userinput>require 'fox'</userinput>
+irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
 </screen>
 
     <para>If this works, you can of course permanently add the
@@ -273,7 +272,7 @@ irb(main):001:0&gt; <userinput>require 'fox'</userinput>
     <orderedlist numeration="arabic" spacing="compact">
       <listitem>
         <para>Edit your <filename>/etc/ld.so.conf</filename> file and add the
-        directory where <filename>libFOX.so</filename> is installed;
+        directory where <filename>libFOX-1.6.so</filename> is installed;
         and,</para>
       </listitem>
 
@@ -294,4 +293,4 @@ irb(main):001:0&gt; <userinput>require 'fox'</userinput>
     <filename>Makefile</filename> and add <option>-lgcc</option> to the
     <constant>LIBS</constant> line.</para>
   </simplesect>
-</chapter>
+</chapter>
\ No newline at end of file
diff --git a/doc/changes.xml b/doc/changes.xml
index d62e6dd71477494a8a07b4429b4e4ef29e2feff9..80c3c078d43c26022765b50e0b2ebfb96652c774 100755
--- a/doc/changes.xml
+++ b/doc/changes.xml
@@ -2,6 +2,440 @@
 <chapter id="changes">
   <title>Change History</title>
 
+  <simplesect>
+    <title>Changes For Version 1.6.18 (December 29, 2008)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Some users were having trouble building FXRuby on 64-bit operating systems
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=23375&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #23375</ulink>). This problem has been corrected.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.17 (December 24, 2008)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>The Ruby interpreter was generating a large number of warning messages about redefined methods
+        in the <filename>kwargs.rb</filename> library
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=19231&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #19231</ulink> and elsewhere). This problem has been corrected.</para>
+      </listitem>
+
+      <listitem>
+        Due to recent changes in Ruby's garbage collection algorithm, FXRuby applications could under some circumstances
+        crash for large numbers of table items
+        (see RubyForge bugs <ulink url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=21983&amp;group_id=300&amp;atid=1223">21983</ulink> and <ulink url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=23188&amp;group_id=300&amp;atid=1223">23188</ulink>).
+        This bug has been fixed.
+      </listitem>
+      
+      <listitem>
+        <para>The documentation for the <classname>FXTable</classname> class referred to the non-existent <methodname>setColumnX</methodname>
+        and <methodname>setRowY</methodname> instance methods
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=21987&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #21987</ulink>). These entries have been removed from the documentation.</para>
+      </listitem>
+
+      <listitem>
+        <para>A number of instance methods for the <classname>FXTable</classname> class could crash an application if they
+        were passed out-of-bounds index arguments
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=21987&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #21987</ulink>). These methods now raise <classname>IndexError</classname> when they're passed out-of-bounds
+        indexes.</para>
+      </listitem>
+
+      <listitem>
+        <para>Due to a change in the URL scheme for the Dilbert web site, the <filename>dilbert.rb</filename> example
+        program was no longer working properly
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=21538&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #21538</ulink>). This has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <methodname>lower</methodname> method for the <classname>FXRangef</classname> was returning
+        <constant>self</constant> instead of an <classname>FXVec3f</classname> instance for the range's low
+        bound
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=22488&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #22488</ulink>). This has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>Made a number of minor fixes for compatibility with Ruby 1.9.1.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.16 (July 3, 2008)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Historically, if you called <methodname>create</methodname> on a
+        window before its parent window was created, your application would
+        crash (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=20702&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #20702</ulink> and elsewhere). Now, the code should raise a
+        <constant>RuntimeError</constant> with a message indicating the
+        problem.</para>
+      </listitem>
+
+      <listitem>
+        <para>The message data that the <classname>FXPicker</classname> widget
+        sends along with its <constant>SEL_CHANGED</constant> and
+        <constant>SEL_COMMAND</constant> messages wasn't being handled
+        properly, and as a result, applications using this widget could crash
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=20780&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #20780</ulink>). This problem has been fixed.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.15 (June 4, 2008)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>FXRuby applications could crash (with a segmentation fault) if
+        <constant>nil</constant> was passed in as the first argument to
+        <methodname>FXDialogBox.new</methodname> or
+        <methodname>FXMainWindow.new</methodname> (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=14642&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #14642</ulink>). These methods now raise an
+        <constant>ArgumentError</constant> if <constant>nil</constant> is
+        passed as the first argument.</para>
+      </listitem>
+
+      <listitem>
+        <para>You should only ever construct one <classname>FXApp</classname>
+        object per application, but there was no protection against doing so
+        in the code (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=16275&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #16275</ulink>). Now, <methodname>FXApp.new</methodname> will
+        raise a <classname>RuntimeException</classname> if an
+        <classname>FXApp</classname> object already exists.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <filename>babelfish.rb</filename> example program, which
+        previously depended on an external web service to perform translation
+        between languages, was broken since that web service no longer exists
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=16962&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #16962</ulink>). The example has now been updated to use Dr. Nic's
+        <ulink url="http://tranexp.rubyforge.org/">Tranexp</ulink> library
+        instead.</para>
+      </listitem>
+
+      <listitem>
+        <para>The value of the <constant>MBOX_SAVE_CANCEL_DONTSAVE</constant>
+        option (for the <classname>FXMessageBox</classname> class) wasn't
+        wrapped properly and was unusable (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=17094&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #17094</ulink>). There was also no constant corresponding to the
+        <constant>MBOX_CLICKED_DONTSAVE</constant> return value. Both of these
+        problems have been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The fields for new <classname>FXHiliteStyle</classname> objects
+        were uninitialized and as a result sometimes gave unpredictable
+        results (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=19637&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #19637</ulink>). This has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The <methodname>columnHeaderFont</methodname> and
+        <methodname>rowHeaderFont</methodname> attributes for
+        <classname>FXTable</classname> weren't implemented properly (see
+        <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=20142&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #20142</ulink>). This has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>Ruby 1.8.7 adds a new <methodname>first</methodname> method to
+        the <classname>Enumerable</classname> module, and this conflicts with
+        the existing <methodname>first</methodname> method defined in the
+        <classname>FXWindow</classname> base class for a number of FXRuby
+        classes which mix in <classname>Enumerable</classname> (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=20418&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #20418</ulink>). This problem has been resolved.</para>
+      </listitem>
+
+      <listitem>
+        <para>Due to a bug in the <filename>extconf.rb</filename> script, the
+        build was failing for Ruby 1.9.0 (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=20426&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #20426</ulink>). This has been fixed.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.14 (March 29, 2008)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Updated the documentation for the <classname>FXImage</classname>
+        class to indicate which methods call <methodname>render</methodname>
+        after they're finished, and which ones do not.</para>
+      </listitem>
+
+      <listitem>
+        <para>Corrected a little typo in the
+        <filename>gembrowser.rb</filename> example program.</para>
+      </listitem>
+
+      <listitem>
+        <para>Updated the <filename>dilbert.rb</filename> example program to
+        use the more popular-and-likely-to-be-installed <ulink
+        url="http://code.whytheluckystiff.net/hpricot/">Hpricot</ulink> HTML
+        parser library instead of <ulink
+        url="http://www.crummy.com/software/RubyfulSoup/">Rubyful
+        Soup</ulink>.</para>
+      </listitem>
+
+      <listitem>
+        <para>Re-added the documentation for the
+        <constant>TOGGLEBUTTON_KEEPSTATE</constant> option, which had
+        mysteriously disappeared (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=2286&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #2286</ulink>).</para>
+      </listitem>
+
+      <listitem>
+        <para>Made a number of minor fixes to support building FXRuby against
+        Ruby 1.9.</para>
+      </listitem>
+
+      <listitem>
+        <para>Added a binary gem for OS X. This works with the Ruby that's
+        included with OS X (Leopard).</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.32 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.13 (November 9, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Calls to the <methodname>extractText</methodname> method for the
+        <classname>FXTable</classname> class were causing various
+        memory-related errors on certain platforms (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=15444group_id=300&amp;atid=1223">RubyForge
+        Bug #15444</ulink>). This problem has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.28 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.12 (October 19, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>The API documentation for <classname>FXMDIClient</classname>
+        referred to the non-existent instance method
+        <methodname>activeChild=</methodname> (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=10259&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #10259</ulink>). This method has been added.</para>
+      </listitem>
+
+      <listitem>
+        <para>The API documentation for <classname>FXMDIClient</classname>
+        also referred to the non-existent instance methods
+        <methodname>getMDIChildFirst</methodname> and
+        <methodname>getMDIChildLast</methodname>. These entries have been
+        removed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The API documentation for <classname>FXMDIChild</classname>
+        referred to non-existent instance methods
+        <methodname>getMDINext</methodname> and
+        <methodname>getMDIPrev</methodname> (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=10436&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #10436</ulink>). The documentation has been corrected.</para>
+      </listitem>
+
+      <listitem>
+        <para>Added the <parameter>:repeat</parameter> parameter for the
+        <methodname>addChore</methodname> and
+        <methodname>addTimeout</methodname> methods. See the documentation for
+        more details, and <filename>gltest.rb</filename> for an example of its
+        use.</para>
+      </listitem>
+
+      <listitem>
+        <para>Corrected a number of minor typos in the API
+        documentation.</para>
+      </listitem>
+
+      <listitem>
+        <para>Corrected a typo in the <filename>imageviewer.rb</filename>
+        example.</para>
+      </listitem>
+
+      <listitem>
+        <para>Modified the <filename>inputs.rb</filename> example program to
+        use <methodname>Pipe.read_nonblock()</methodname> instead of
+        <methodname>Pipe.read()</methodname>.</para>
+      </listitem>
+
+      <listitem>
+        <para>Fixed a bug in the implementation of the
+        <methodname>findText</methodname> method for the
+        <classname>FXText</classname> class, when used with the
+        <constant>SEARCH_REGEX</constant> option.</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.28 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.11 (April 18, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Added <methodname>editable</methodname> as an alias for
+        <methodname>FXTextField#editable?</methodname>.</para>
+      </listitem>
+
+      <listitem>
+        <para>Added <methodname>each_child_recursive</methodname> instance
+        method for the <classname>FXWindow</classname> class. This method
+        performs a depth-first traversal of the widget tree starting at the
+        receiver window.</para>
+      </listitem>
+
+      <listitem>
+        <para>Corrected some errors in the keyword arguments support for the
+        <classname>FXVec2d</classname>, <classname>FXVec2f</classname>,
+        <classname>FXVec3d</classname>, <classname>FVec3f</classname>,
+        <classname>FXVec4d</classname> and <classname>FXVec4f</classname>
+        classes.</para>
+      </listitem>
+
+      <listitem>
+        <para>Corrected an error in the keyword arguments support for the
+        <classname>FXIconDict</classname> class.</para>
+      </listitem>
+
+      <listitem>
+        <para>Modified the gem specification so that the RDoc generated during
+        a gem install is consistent with that generated by other methods (see
+        <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=10035&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #10035</ulink>).</para>
+      </listitem>
+
+      <listitem>
+        <para>Changes to the <filename>iterators</filename> library in version
+        1.6.6 introduced a bug in the <methodname>each</methodname> method for
+        the <classname>FXFoldingList</classname>,
+        <classname>FXTreeList</classname> and
+        <classname>FXTreeListBox</classname> classes (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=10175&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #10175</ulink>). This problem has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>Applied submitted patches for building FXRuby against Ruby 1.9
+        (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=10181&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #10181</ulink>). Please note that building FXRuby against the Ruby
+        1.9 code base is still officially unsupported; however, I'm glad to
+        accept patches that will help make this possible.</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.25 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.9 (April 8, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>A bug was discovered in the keyword arguments library support
+        for the <classname>FXMenuBar</classname> class (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=9927&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #9927</ulink>). This problem has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.25 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.8 (April 5, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>Due to an internal bookkeeping error, applications like the
+        <filename>glviewer.rb</filename> example program which create multiple
+        <classname>FXGLViewer</classname> instances could cause an assertion
+        to fail. When this assertion fails on Windows, the program simply
+        crashes (see <ulink
+        url="http://rubyforge.org/tracker/index.php?func=detail&amp;aid=9775&amp;group_id=300&amp;atid=1223">RubyForge
+        Bug #9775</ulink>). This problem has been fixed.</para>
+      </listitem>
+
+      <listitem>
+        <para>The keyword arguments library, introduced in version 1.6.5, is
+        now included automatically when you load FXRuby; it is no longer
+        necessary to explicitly require it.</para>
+      </listitem>
+
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.25 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
+  <simplesect>
+    <title>Changes For Version 1.6.7 (March 31, 2007)</title>
+
+    <itemizedlist mark="bullet">
+      <listitem>
+        <para>The binary gem for Windows was built with FOX version 1.6.25 and
+        FXScintilla version 1.71.</para>
+      </listitem>
+    </itemizedlist>
+  </simplesect>
+
   <simplesect>
     <title>Changes For Version 1.6.6 (February 10, 2007)</title>
 
diff --git a/doc/clipboardtut.xml b/doc/clipboardtut.xml
index eb32f71dfaa88cad1bb52ef2c32349bc2308b346..92836a0f5ff3dcc5e1306e43213e1563f8486c2a 100755
--- a/doc/clipboardtut.xml
+++ b/doc/clipboardtut.xml
@@ -21,8 +21,7 @@
     doesn't yet provide any clipboard support. This application simply
     presents a list of customers (from some external source).</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 require 'customer'
 
 include Fox
@@ -30,14 +29,14 @@ include Fox
 class ClipMainWindow &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class first
-    super(anApp, "Clipboard Example", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Clipboard Example", :opts => DECOR_ALL, :width => 400, :height => 300)
 
     # Place the list in a sunken frame
-    sunkenFrame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK,
-      0, 0, 0, 0, 0, 0, 0, 0)
+    sunkenFrame = FXVerticalFrame.new(self,
+			LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
     
     # Customer list
-    customerList = FXList.new(sunkenFrame, nil, 0, LIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    customerList = FXList.new(sunkenFrame, :opts => LIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
     $customers.each do |customer|
       customerList.appendItem(customer.name, nil, customer)
     end
@@ -89,8 +88,7 @@ $customers &lt;&lt; Customer.new("Johnny Storm", "123 Maple, Anytown, NC", 12345
     <para>Let's begin by augmenting the GUI to include a row of buttons along
     the bottom of the main window for copying and pasting:</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 require 'customer'
 
 include Fox
@@ -98,7 +96,7 @@ include Fox
 class ClipMainWindow &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class first
-    super(anApp, "Clipboard Example", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Clipboard Example", :opts => DECOR_ALL, :width => 400, :height => 300)
 <emphasis role="bold">
     # Horizontal frame contains buttons
     buttons = FXHorizontalFrame.new(self, LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH)
@@ -108,11 +106,11 @@ class ClipMainWindow &lt; FXMainWindow
     pasteButton = FXButton.new(buttons, "Paste")
 </emphasis>
     # Place the list in a sunken frame
-    sunkenFrame = FXVerticalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK,
-      0, 0, 0, 0, 0, 0, 0, 0)
+    sunkenFrame = FXVerticalFrame.new(self,
+			LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
     
     # Customer list
-    customerList = FXList.new(sunkenFrame, nil, 0, LIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    customerList = FXList.new(sunkenFrame, :opts => LIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y)
     $customers.each do |customer|
       customerList.appendItem(customer.name, nil, customer)
     end
diff --git a/doc/custom-fo.xsl b/doc/custom-fo.xsl
index 563fc05f080c27b33ed8c71453b76302f185f1e0..039868c83ae21c67d3303b20cf6ec232044e9d8e 100755
--- a/doc/custom-fo.xsl
+++ b/doc/custom-fo.xsl
@@ -3,7 +3,7 @@
                 version='1.0'
                 xmlns="http://www.w3.org/TR/xhtml1/transitional"
                 exclude-result-prefixes="#default">
-<xsl:import href="/usr/local/docbook/docbook-xsl-1.61.2/fo/docbook.xsl"/>
+<xsl:import href="/Users/lyle/docbook/docbook5-xsl-1.72.0/fo/docbook.xsl"/>
 <!--xsl:param name="use.extensions" select="1"/-->
 <xsl:param name="fop.extensions" select="1"/>
 <xsl:param name="shade.verbatim" select="1"/>
diff --git a/doc/custom-html.xsl b/doc/custom-html.xsl
index 3cbb41b2b9a2dff53074d59558570ec7a2479f5b..aa8dd7fe57651d3c7a9320b15d8abb15a4c78dfe 100755
--- a/doc/custom-html.xsl
+++ b/doc/custom-html.xsl
@@ -4,7 +4,7 @@
                 xmlns="http://www.w3.org/TR/xhtml1/transitional"
                 exclude-result-prefixes="#default">
 
-<xsl:import href="/Users/lyle/docbook/docbook-xsl-1.68.1/html/chunk.xsl"/>
+<xsl:import href="/Users/lyle/docbook/docbook5-xsl-1.72.0/html/chunk.xsl"/>
 
 <xsl:variable name="root.filename">book</xsl:variable>
 <xsl:param name="html.stylesheet.type">text/css</xsl:param>
diff --git a/doc/dragdroptut.xml b/doc/dragdroptut.xml
index 31a93b530c43b4376ee6bc398f9f2cc664c3f47d..5db5d2f4076d473115898f5bc76c6cf9953ca545 100755
--- a/doc/dragdroptut.xml
+++ b/doc/dragdroptut.xml
@@ -15,18 +15,17 @@
     of a main window widget (a <classname>DropSite</classname> instance) that
     parents an <classname>FXCanvas</classname> widget:</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DropSite &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drop Site", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
   end
 
   def create
@@ -55,26 +54,25 @@ end
     that by adding a handler that clears the canvas to its current background
     color:</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DropSite &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drop Site", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
 <emphasis role="bold">    # Handle expose events on the canvas
-    @canvas.connect(SEL_PAINT) { |sender, sel, event|
-      FXDCWindow.new(@canvas, event) { |dc|
+    @canvas.connect(SEL_PAINT) do |sender, sel, event|
+      FXDCWindow.new(@canvas, event) do |dc|
         dc.foreground = @canvas.backColor
         dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-      }
-    }</emphasis>
+      end
+    end</emphasis>
   end
 
   def create
@@ -95,23 +93,23 @@ end
     from some other window, such as an <classname>FXColorWell</classname>
     widget, and drop it onto the canvas in order to change the canvas'
     background color. In order for a FOX widget to be able to accept drops at
-    all, we need to first call its <methodname>dropEnable()</methodname>
+    all, we need to first call its <methodname>dropEnable</methodname>
     method:</para>
 
     <programlisting format="linespecific">def initialize(anApp)
   # Initialize base class
-  super(anApp, "Drop Site", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+  super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
   
   # Fill main window with canvas
-  @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+  @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
   # Handle expose events on the canvas
-  @canvas.connect(SEL_PAINT) { |sender, sel, event|
-    FXDCWindow.new(@canvas, event) { |dc|
+  @canvas.connect(SEL_PAINT) do |sender, sel, event|
+    FXDCWindow.new(@canvas, event) do |dc|
       dc.foreground = @canvas.backColor
       dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-    }
-  }
+    end
+  end
 
 <emphasis role="bold">  # Enable canvas for drag-and-drop messages
   @canvas.dropEnable
@@ -141,39 +139,39 @@ end
     that the canvas isn't accepting drops of color data yet.</para>
 
     <para>To correct this problem, we need to use the canvas'
-    <methodname>acceptDrop()</methodname> method to indicate whether or not
+    <methodname>acceptDrop</methodname> method to indicate whether or not
     we'll accept certain kinds of drops. You can call
-    <methodname>acceptDrop()</methodname> any time after receiving the initial
+    <methodname>acceptDrop</methodname> any time after receiving the initial
     <constant>SEL_DND_ENTER</constant> message, but it's usually done in
     response to a <constant>SEL_DND_MOTION</constant> message. Let's add a
     handler for <constant>SEL_DND_MOTION</constant> messages from the canvas
-    in DropSite's initialize() method. For now, we'll unconditionally accept
+    in DropSite's <methodname>initialize</methodname> method. For now, we'll unconditionally accept
     drops from any drag source, regardless of what kind of data they're
     offering:</para>
 
     <programlisting format="linespecific">def initialize(anApp)
   # Initialize base class
-  super(anApp, "Drop Site", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+  super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
     
   # Fill main window with canvas
-  @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+  @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
   # Handle expose events on the canvas
-  @canvas.connect(SEL_PAINT) { |sender, sel, event|
-    FXDCWindow.new(@canvas, event) { |dc|
+  @canvas.connect(SEL_PAINT) do |sender, sel, event|
+    FXDCWindow.new(@canvas, event) do |dc|
       dc.foreground = @canvas.backColor
       dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-    }
-  }
+    end
+  end
 
   # Enable canvas for drag-and-drop messages
   @canvas.dropEnable
   
 <emphasis role="bold">  # Handle SEL_DND_MOTION messages from the canvas
-  @canvas.connect(SEL_DND_MOTION) {
+  @canvas.connect(SEL_DND_MOTION) do
     # Accept drops unconditionally (for now)
     @canvas.acceptDrop
-  }
+  end
 </emphasis>end
 </programlisting>
 
@@ -195,7 +193,7 @@ end
 
     <para>Drag types (even the standard ones) must be registered before they
     can be used, and so we'll start by adding a few lines to
-    <classname>DropSite</classname>'s <methodname>create()</methodname> method
+    <classname>DropSite</classname>'s <methodname>create</methodname> method
     to register the drag type for color data:</para>
 
     <programlisting format="linespecific">def create
@@ -211,49 +209,49 @@ end
 </programlisting>
 
     <para>Note that the first time that
-    <methodname>registerDragType()</methodname> is called for a particular
+    <methodname>registerDragType</methodname> is called for a particular
     drag type name (such as <methodname>FXWindow.colorTypeName</methodname>)
     it will generate a unique identifier for that drag type. Subsequent calls
-    to <methodname>registerDragType()</methodname> for the same drag type name
+    to <methodname>registerDragType</methodname> for the same drag type name
     will just return the previously-generated drag type. Now, we want to
     modify our <constant>SEL_DND_MOTION</constant> handler so that it's a
     little more picky about which kinds of drops it will accept:</para>
 
     <programlisting format="linespecific"># Handle SEL_DND_MOTION messages from the canvas
-@canvas.connect(SEL_DND_MOTION) {
+@canvas.connect(SEL_DND_MOTION) do
 <emphasis role="bold">  if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
     @canvas.acceptDrop
   end
-</emphasis>}
+</emphasis>end
 </programlisting>
 
     <para>Here, we call the canvas' <methodname>offeredDNDType?</methodname>
     method to ask if the drag source can provide its data in the requested
     format. Only if <methodname>offeredDNDType?</methodname> returns true will
-    we call <methodname>acceptDrop()</methodname> as before.</para>
+    we call <methodname>acceptDrop</methodname> as before.</para>
 
     <para>The last step is to actually handle the drop, and for that we add a
     handler for the <constant>SEL_DND_DROP</constant> message:</para>
 
     <programlisting format="linespecific"><emphasis role="bold"># Handle SEL_DND_DROP message from the canvas
-@canvas.connect(SEL_DND_DROP) {
+@canvas.connect(SEL_DND_DROP) do
   # Try to obtain the data as color values first
   data = @canvas.getDNDData(FROM_DRAGNDROP, FXWindow.colorType)
   unless data.nil?
     # Update canvas background color
     @canvas.backColor = Fox.fxdecodeColorData(data)
   end
-}</emphasis></programlisting>
+end</emphasis></programlisting>
 
     <para>Assuming that the drag source is able to provide its data in the
-    requested format, the <methodname>getDNDData()</methodname> method will
-    return a String (which for our purposes is just a byte buffer). If you've
+    requested format, the <methodname>getDNDData</methodname> method will
+    return a string (which for our purposes is just a byte buffer). If you've
     defined your own application-specific drag types, this data can of course
     be anything, and we'll see examples of this in a later tutorial. But the
     data for standard drag types like
     <methodname>FXWindow.colorType</methodname> can be decoded using the
     appropriate built-in library functions. In this case, we use the
-    <methodname>fxdecodeColorData()</methodname> method to convert the bytes
+    <methodname>fxdecodeColorData</methodname> method to convert the bytes
     into a color value that we can use.</para>
 
     <para>Now comes the moment of truth. Try running your test program again
@@ -265,46 +263,45 @@ end
     <filename class="directory">examples</filename> directory under the file
     name <filename>dropsite.rb</filename>.</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DropSite &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drop Site", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
     # Handle expose events on the canvas
-    @canvas.connect(SEL_PAINT) { |sender, sel, event|
-      FXDCWindow.new(@canvas, event) { |dc|
+    @canvas.connect(SEL_PAINT) do |sender, sel, event|
+      FXDCWindow.new(@canvas, event) do |dc|
         dc.foreground = @canvas.backColor
         dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-      }
-    }
+      end
+    end
 
     # Enable canvas for drag-and-drop messages
     @canvas.dropEnable
     
     # Handle SEL_DND_MOTION messages from the canvas
-    @canvas.connect(SEL_DND_MOTION) {
+    @canvas.connect(SEL_DND_MOTION) do
       if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
         @canvas.acceptDrop
       end
-    }
+    end
 
     # Handle SEL_DND_DROP message from the canvas
-    @canvas.connect(SEL_DND_DROP) {
+    @canvas.connect(SEL_DND_DROP) do
       # Try to obtain the data as color values first
       data = @canvas.getDNDData(FROM_DRAGNDROP, FXWindow.colorType)
       unless data.nil?
         # Update canvas background color
         @canvas.backColor = Fox.fxdecodeColorData(data)
       end
-    }
+    end
   end
 
   def create
@@ -336,27 +333,26 @@ end
     consisting of a main window widget (a <classname>DragSource</classname>
     instance) that parents an <classname>FXCanvas</classname> widget:</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DragSource &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drag Source", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drag Source", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     @canvas.backColor = "red"
     
     # Handle expose events on the canvas
-    @canvas.connect(SEL_PAINT) { |sender, sel, event|
-      FXDCWindow.new(@canvas, event) { |dc|
+    @canvas.connect(SEL_PAINT) do |sender, sel, event|
+      FXDCWindow.new(@canvas, event) do |dc|
         dc.foreground = @canvas.backColor
         dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-      }
-    }
+      end
+    end
   end
 
   def create
@@ -397,7 +393,7 @@ end
       <listitem>
         <para>The drag type for colors
         (<constant>FXWindow.colorType</constant>) is registered in the
-        <classname>DragSource</classname>'s <methodname>create()</methodname>
+        <classname>DragSource</classname>'s <methodname>create</methodname>
         method.</para>
       </listitem>
     </itemizedlist>
@@ -412,7 +408,7 @@ end
     handler for the <constant>SEL_LEFTBUTTONPRESS</constant> message from the
     canvas:</para>
 
-    <programlisting format="linespecific">@canvas.connect(SEL_LEFTBUTTONPRESS) {
+    <programlisting format="linespecific">@canvas.connect(SEL_LEFTBUTTONPRESS) do
   #
   # Capture (grab) the mouse when the button goes down, so that all future
   # mouse events will be reported to this widget, even if those events occur
@@ -423,13 +419,13 @@ end
   # Advertise which drag types we can offer
   dragTypes = [FXWindow.colorType]
   @canvas.beginDrag(dragTypes)
-}
+end
 </programlisting>
 
     <para>Note that there are usually two things you're going to want to do in
     the <constant>SEL_LEFTBUTTONPRESS</constant> handler for a drag source.
-    The first is to call <methodname>grab()</methodname> on the window that
-    acts as the drag source. Calling <methodname>grab()</methodname>
+    The first is to call <methodname>grab</methodname> on the window that
+    acts as the drag source. Calling <methodname>grab</methodname>
     "captures" the mouse in the sense that subsequent mouse motion events will
     be reported as if they occurred inside the grab window. This is important,
     since in our case we're going to be dragging from this window to some
@@ -438,7 +434,7 @@ end
 
     <para>The second thing you'll want to do in the
     <constant>SEL_LEFTBUTTONPRESS</constant> handler for a drag source is to
-    call <methodname>beginDrag()</methodname>. This not only kicks the
+    call <methodname>beginDrag</methodname>. This not only kicks the
     application into drag-and-drop mode, but also provides a way for you to
     inform the system about the formats of data (i.e. the drag types) that
     this drag source is able to provide. For this example, the drag source is
@@ -448,22 +444,22 @@ end
     it's important to also add a handler for the
     <constant>SEL_LEFTBUTTONRELEASE</constant> message:</para>
 
-    <programlisting format="linespecific">@canvas.connect(SEL_LEFTBUTTONRELEASE) {
+    <programlisting format="linespecific">@canvas.connect(SEL_LEFTBUTTONRELEASE) do
   @canvas.ungrab
   @canvas.endDrag
-}
+end
 </programlisting>
 
     <para>This is pretty much the mirror image of our
     <constant>SEL_LEFTBUTTONPRESS</constant> handler. We call
-    <methodname>ungrab()</methodname> to release the mouse capture, and
-    <methodname>endDrag()</methodname> to clean up the drag-and-drop
+    <methodname>ungrab</methodname> to release the mouse capture, and
+    <methodname>endDrag</methodname> to clean up the drag-and-drop
     state.</para>
 
     <para>The next change is to add a <constant>SEL_MOTION</constant> handler,
     to handle mouse motion events during the drag operation:</para>
 
-    <programlisting format="linespecific">@canvas.connect(SEL_MOTION) { |sender, sel, event|
+    <programlisting format="linespecific">@canvas.connect(SEL_MOTION) do |sender, sel, event|
   if @canvas.dragging?
     @canvas.handleDrag(event.root_x, event.root_y)
     unless @canvas.didAccept == DRAG_REJECT
@@ -472,23 +468,23 @@ end
       @canvas.dragCursor = getApp().getDefaultCursor(DEF_DNDSTOP_CURSOR)
     end
   end
-}
+end
 </programlisting>
 
     <para>The <methodname>dragging?</methodname> method returns true if we're
     in the middle of a drag-and-drop operation for the drag source window,
-    i.e. after the call to <methodname>beginDrag()</methodname> but before the
-    call to <methodname>endDrag()</methodname>. If we're not currently
+    i.e. after the call to <methodname>beginDrag</methodname> but before the
+    call to <methodname>endDrag</methodname>. If we're not currently
     processing a drag operation, we're not really interested in mouse motion
     events for the canvas.</para>
 
     <para>If we <emphasis>are</emphasis> processing a drag operation, however,
-    we need to call <methodname>handleDrag()</methodname> on the drag source
+    we need to call <methodname>handleDrag</methodname> on the drag source
     window. FOX uses this information to send drag-and-drop messages (such as
     <constant>SEL_DND_ENTER</constant>, <constant>SEL_DND_MOTION</constant>
     and <constant>SEL_DND_LEAVE</constant>) to the window that the mouse is
     currently over. Note that the coordinates passed to
-    <methodname>handleDrag()</methodname> are root window coordinates, and not
+    <methodname>handleDrag</methodname> are root window coordinates, and not
     window-local coordinates.</para>
 
     <para>Another good thing to consider doing here is to change the shape of
@@ -530,16 +526,16 @@ end
     <para>The last (and most important) step is to actually complete the data
     transfer. At any time during a drag-and-drop operation, a drop site may
     request a copy of the drag-and-drop data by calling the
-    <methodname>getDNDData()</methodname> method (as described in the previous
+    <methodname>getDNDData</methodname> method (as described in the previous
     section). When this happens, FOX sends a
     <constant>SEL_DND_REQUEST</constant> message to the current drag source
     window, and so we now add a handler for that message:</para>
 
-    <programlisting format="linespecific">@canvas.connect(SEL_DND_REQUEST) { |sender, sel, event|
+    <programlisting format="linespecific">@canvas.connect(SEL_DND_REQUEST) do |sender, sel, event|
   if event.target == FXWindow.colorType
     @canvas.setDNDData(FROM_DRAGNDROP, FXWindow.colorType, Fox.fxencodeColorData(@canvas.backColor))
   end
-}
+end
 </programlisting>
 
     <para>The first important thing to note here is that the
@@ -553,8 +549,8 @@ end
 
     <para>Assuming that the drag type is as expected, the last step is send
     the data to the drop site by calling
-    <methodname>setDNDData()</methodname>. As with the call to
-    <methodname>getDNDData()</methodname> for our previous drop site program,
+    <methodname>setDNDData</methodname>. As with the call to
+    <methodname>getDNDData</methodname> for our previous drop site program,
     you want to be sure to specify the origin of the data
     (<constant>FROM_DRAGNDROP</constant>), the drag type
     (<constant>FXWindow.colorType</constant>) and the data itself as a binary
@@ -569,30 +565,29 @@ end
     <filename class="directory">examples</filename> directory under the file
     name <filename>dragsource.rb</filename>.</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DragSource &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drag Source", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drag Source", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     @canvas.backColor = "red"
     
     # Handle expose events on the canvas
-    @canvas.connect(SEL_PAINT) { |sender, sel, event|
-      FXDCWindow.new(@canvas, event) { |dc|
+    @canvas.connect(SEL_PAINT) do |sender, sel, event|
+      FXDCWindow.new(@canvas, event) do |dc|
         dc.foreground = @canvas.backColor
         dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-      }
-    }
+      end
+    end
 
     # Handle left button press
-    @canvas.connect(SEL_LEFTBUTTONPRESS) {
+    @canvas.connect(SEL_LEFTBUTTONPRESS) do
       #
       # Capture (grab) the mouse when the button goes down, so that all future
       # mouse events will be reported to this widget, even if those events occur
@@ -603,10 +598,10 @@ class DragSource &lt; FXMainWindow
       # Advertise which drag types we can offer
       dragTypes = [FXWindow.colorType]
       @canvas.beginDrag(dragTypes)
-    }
+    end
     
     # Handle mouse motion events
-    @canvas.connect(SEL_MOTION) { |sender, sel, event|
+    @canvas.connect(SEL_MOTION) do |sender, sel, event|
       if @canvas.dragging?
         @canvas.handleDrag(event.root_x, event.root_y)
         unless @canvas.didAccept == DRAG_REJECT
@@ -615,20 +610,20 @@ class DragSource &lt; FXMainWindow
           @canvas.dragCursor = getApp().getDefaultCursor(DEF_DNDSTOP_CURSOR)
         end
       end
-    }
+    end
 
     # Handle left button release
-    @canvas.connect(SEL_LEFTBUTTONRELEASE) {
+    @canvas.connect(SEL_LEFTBUTTONRELEASE) do
       @canvas.ungrab
       @canvas.endDrag
-    }
+    end
     
     # Handle request for DND data
-    @canvas.connect(SEL_DND_REQUEST) { |sender, sel, event|
+    @canvas.connect(SEL_DND_REQUEST) do |sender, sel, event|
       if event.target == FXWindow.colorType
         @canvas.setDNDData(FROM_DRAGNDROP, FXWindow.colorType, Fox.fxencodeColorData(@canvas.backColor))
       end
-    }
+    end
   end
 
   def create
@@ -671,7 +666,7 @@ end
 
     <itemizedlist>
       <listitem>
-        <para>A call to <methodname>dropEnable()</methodname>, to make
+        <para>A call to <methodname>dropEnable</methodname>, to make
         <classname>DragSource</classname>'s canvas drop-enabled;</para>
       </listitem>
 
@@ -702,33 +697,32 @@ end
     <filename class="directory">examples</filename> directory under the file
     name <filename>dragdrop.rb</filename>.</para>
 
-    <programlisting format="linespecific">require 'rubygems'
-require_gem 'fxruby'
+    <programlisting format="linespecific">require 'fox16'
 
 include Fox
 
 class DragDropWindow &lt; FXMainWindow
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drag and Drop", nil, nil, DECOR_ALL, 0, 0, 400, 300)
+    super(anApp, "Drag and Drop", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
-    @canvas = FXCanvas.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y)
+    @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
     @canvas.backColor = "red"
     
     # Enable canvas for drag-and-drop messages
     @canvas.dropEnable
     
     # Handle expose events on the canvas
-    @canvas.connect(SEL_PAINT) { |sender, sel, event|
-      FXDCWindow.new(@canvas, event) { |dc|
+    @canvas.connect(SEL_PAINT) do |sender, sel, event|
+      FXDCWindow.new(@canvas, event) do |dc|
         dc.foreground = @canvas.backColor
         dc.fillRectangle(event.rect.x, event.rect.y, event.rect.w, event.rect.h)
-      }
-    }
+      end
+    end
 
     # Handle left button press
-    @canvas.connect(SEL_LEFTBUTTONPRESS) {
+    @canvas.connect(SEL_LEFTBUTTONPRESS) do
       #
       # Capture (grab) the mouse when the button goes down, so that all future
       # mouse events will be reported to this widget, even if those events occur
@@ -739,10 +733,10 @@ class DragDropWindow &lt; FXMainWindow
       # Advertise which drag types we can offer
       dragTypes = [FXWindow.colorType]
       @canvas.beginDrag(dragTypes)
-    }
+    end
     
     # Handle mouse motion events
-    @canvas.connect(SEL_MOTION) { |sender, sel, event|
+    @canvas.connect(SEL_MOTION) do |sender, sel, event|
       if @canvas.dragging?
         @canvas.handleDrag(event.root_x, event.root_y)
         unless @canvas.didAccept == DRAG_REJECT
@@ -751,37 +745,37 @@ class DragDropWindow &lt; FXMainWindow
           @canvas.dragCursor = getApp().getDefaultCursor(DEF_DNDSTOP_CURSOR)
         end
       end
-    }
+    end
 
     # Handle SEL_DND_MOTION messages from the canvas
-    @canvas.connect(SEL_DND_MOTION) {
+    @canvas.connect(SEL_DND_MOTION) do
       if @canvas.offeredDNDType?(FROM_DRAGNDROP, FXWindow.colorType)
         @canvas.acceptDrop
       end
-    }
+    end
 
     # Handle left button release
-    @canvas.connect(SEL_LEFTBUTTONRELEASE) {
+    @canvas.connect(SEL_LEFTBUTTONRELEASE) do
       @canvas.ungrab
       @canvas.endDrag
-    }
+    end
     
     # Handle SEL_DND_DROP message from the canvas
-    @canvas.connect(SEL_DND_DROP) {
+    @canvas.connect(SEL_DND_DROP) do
       # Try to obtain the data as color values first
       data = @canvas.getDNDData(FROM_DRAGNDROP, FXWindow.colorType)
       unless data.nil?
         # Update canvas background color
         @canvas.backColor = Fox.fxdecodeColorData(data)
       end
-    }
+    end
 
     # Handle request for DND data
-    @canvas.connect(SEL_DND_REQUEST) { |sender, sel, event|
+    @canvas.connect(SEL_DND_REQUEST) do |sender, sel, event|
       if event.target == FXWindow.colorType
         @canvas.setDNDData(FROM_DRAGNDROP, FXWindow.colorType, Fox.fxencodeColorData(@canvas.backColor))
       end
-    }
+    end
   end
 
   def create
diff --git a/doc/gems.xml b/doc/gems.xml
index 4df9d22096a2deb517631fb2c7f40ea303849c61..b9db6166f66a3f6415b117267d5ab6234ea61d4c 100755
--- a/doc/gems.xml
+++ b/doc/gems.xml
@@ -5,9 +5,9 @@
   <simplesect>
     <title>Introduction</title>
 
-    <para>Starting with FXRuby version 1.2, FXRuby uses <ulink
-    url="http://rubygems.rubyforge.org">RubyGems</ulink> as its packaging and
-    distribution method. The code is available both as</para>
+    <para>FXRuby uses <ulink
+    url="http://rubygems.rubyforge.org">RubyGems</ulink> as its preferred
+    packaging and distribution method. The code is available both as</para>
 
     <itemizedlist mark="bullet">
       <listitem>
@@ -28,7 +28,7 @@
     <para>If you've already downloaded the source gem, you can install it by
     typing:</para>
 
-    <screen>$ <command>sudo gem install fxruby-1.6.0.gem</command></screen>
+    <screen>$ <command>sudo gem install fxruby-1.6.13.gem</command></screen>
 
     <para>Note the use of the <command>sudo</command> command to invoke
     superuser privileges, since you'll typically need superuser privileges to
@@ -39,12 +39,12 @@
     under some other directory (for example, in your home directory) you might
     need to pass some additional arguments on the command line, e.g.</para>
 
-    <screen>$ <command>sudo gem install fxruby-1.6.0.gem --force -- --with-fox-include=/home/lyle/include/fox-1.6 --with-fox-lib=/home/lyle/lib</command></screen>
+    <screen>$ <command>sudo gem install fxruby-1.6.13.gem --force -- --with-fox-include=/home/lyle/include/fox-1.6 --with-fox-lib=/home/lyle/lib</command></screen>
 
     <para>If you're installing a source gem on a Windows box, you'd instead
     type something like:</para>
 
-    <screen>C:\&gt; <command>gem install fxruby-1.6.0.gem --force -- --with-fox-include=C:\include\fox-1.6 --with-fox-lib=C:\lib</command></screen>
+    <screen>C:\&gt; <command>gem install fxruby-1.6.13.gem --force -- --with-fox-include=C:\include\fox-1.6 --with-fox-lib=C:\lib</command></screen>
 
     <para>If you're installing a source gem, it can take quite awhile to build
     FXRuby, so this might be a good time to take a coffee break. You won't see
@@ -75,7 +75,7 @@ true</screen>
 
     <para>To install a binary gem for Windows, just type:</para>
 
-    <screen>C:\&gt; <command>gem install fxruby-1.6.0-mswin32.gem</command></screen>
+    <screen>C:\&gt; <command>gem install fxruby-1.6.13-mswin32.gem</command></screen>
 
     <para>As a quick sanity check, to make sure that all is well, you should
     probably fire up <filename>irb</filename> and try to require the FXRuby
@@ -115,8 +115,8 @@ true</screen>
     the error message will look something like:</para>
 
     <screen>$ <command>irb</command>
-irb(main):001:0&gt; <userinput>require 'fox'</userinput>
-LoadError: libFOX-0.99.so.173: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.8/i686-linux/fox.so
+irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
+LoadError: libFOX-1.6.so: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.8/i686-linux/fox16.so
         from (irb):1:in 'require'
         from (irb):1
     </screen>
@@ -145,7 +145,7 @@ irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
     <orderedlist numeration="arabic" spacing="compact">
       <listitem>
         <para>Edit your <filename>/etc/ld.so.conf</filename> file and add the
-        directory where <filename>libFOX.so</filename> is installed;
+        directory where <filename>libFOX-1.6.so</filename> is installed;
         and,</para>
       </listitem>
 
@@ -155,4 +155,4 @@ irb(main):001:0&gt; <userinput>require 'fox16'</userinput>
       </listitem>
     </orderedlist>
   </simplesect>
-</chapter>
+</chapter>
\ No newline at end of file
diff --git a/doc/goals.xml b/doc/goals.xml
index 6bdfb9da1fb6db8a9659c44ff78629f554e502ab..8d79c9e9c8fe02450e92c406d23c69b79ed6336e 100755
--- a/doc/goals.xml
+++ b/doc/goals.xml
@@ -16,7 +16,7 @@
     of its maturity and availability on a number of platforms (including the
     Macintosh). But Tk is also showing its age in many ways and it has failed
     to keep pace with some of the "younger" cross-platform GUI toolkits like
-    FOX, wxWindows, FLTK, Qt and GTK+. Of the latter five, only Qt and GTK+
+    FOX, wxWidgets, FLTK, Qt and GTK+. Of the latter five, only Qt and GTK+
     appeared (at the time) to have usable Ruby interfaces and there are some
     problems associated with these as well; for Qt, it's the restrictive
     license for the Windows platform version, and for GTK+ it's a Windows
@@ -41,11 +41,18 @@
       Ruby Developer's Guide</citetitle> and <citetitle pubwork="book">The Ruby
       Way</citetitle>) feature FXRuby as a Ruby GUI development option.</para>
     </listitem>
+		<listitem><para>FXRuby is used as the GUI for <ulink url="http://freeride.rubyforge.org/wiki/wiki.pl">
+    FreeRIDE</ulink> and a number of other Ruby-based projects.</para></listitem>
   </itemizedlist>
   <para>Most recently, work has focused on keeping FXRuby up-to-date with the
     still evolving FOX library while looking for new ways to make Ruby GUI
-    development fun. For example, FXRuby is under consideration for use as a
-    GUI front-end to the fledgling <ulink url="http://freeride.rubyforge.org/wiki/wiki.pl">
-    FreeRIDE</ulink> project. If you have suggestions about where you'd like to
+    development fun. If you have suggestions about where you'd like to
     see things go, feel free to drop me an e-mail.</para>
+  <simplesect>
+	  <title>About this Document</title>
+	  <para>The contents of this document were written using <ulink url="http://docbook.org/whatis">DocBook</ulink> version 5.0.
+			The HTML version of this document uses the CSS stylesheet originally developed for the
+			HTML version of the book <ulink url="http://svnbook.red-bean.com/">Version Control with Subversion</ulink>,
+			which is licensed under the <ulink url="http://creativecommons.org/licenses/by/2.0/">Creative Commons Attribution License</ulink>.</para>
+	</simplesect>
 </preface>
diff --git a/doc/infosources.xml b/doc/infosources.xml
index 27dcbc1fe307ff911917447abb61a871102083f2..6fb8ec15247e85b86f3a1be0d7961ee3674066ff 100755
--- a/doc/infosources.xml
+++ b/doc/infosources.xml
@@ -67,7 +67,7 @@
         <para>The fxruby-users@rubyforge.org mailing list is a
         higher-volume list for FXRuby-related discussions. To subscribe to
         this list, follow the instructions at <ulink
-        url="http://rubyforge.org/mailman/listinfo/fxruby-announce">http://rubyforge.org/mailman/listinfo/fxruby-announce</ulink></para>
+        url="http://rubyforge.org/mailman/listinfo/fxruby-users">http://rubyforge.org/mailman/listinfo/fxruby-users</ulink></para>
       </listitem>
 
       <listitem>
@@ -85,10 +85,10 @@
       </listitem>
 
       <listitem>
-        <para>The ruby-talk@ruby-lang.org mailing list (or its mirror, the
+        <para>The Ruby-Talk mailing list (or its mirror, the
         comp.lang.ruby newsgroup) is a high-volume list for Ruby-related
         discussions. To subscribe to this list, follow the instructions at
-        <ulink url="http://www.ruby-lang.org/en/ml.html">http://www.ruby-lang.org/en/ml.html</ulink></para>
+        <ulink url="http://www.ruby-lang.org/en/community/mailing-lists/">http://www.ruby-lang.org/en/community/mailing-lists/</ulink></para>
       </listitem>
     </itemizedlist>
   </simplesect>
diff --git a/doc/scintilla.xml b/doc/scintilla.xml
index 324dce05ca25f30370f5b20051c0bad2b749157e..2b515056d11bf6164f0dd2e9bdd26aeb00dd7e7e 100755
--- a/doc/scintilla.xml
+++ b/doc/scintilla.xml
@@ -16,10 +16,10 @@
     <para><ulink
     url="http://savannah.gnu.org/projects/fxscintilla">FXScintilla </ulink> is
     a FOX widget that wraps around the Scintilla component, or, if you wish,
-    the FOX "port" of Scintilla. It is being developed by Gilles Filippini,
+    the FOX "port" of Scintilla. Until recently it was developed by Gilles Filippini,
     and as of this writing the latest release is available for download from
     <ulink
-    url="http://savannah.nongnu.org/download/fxscintilla/fxscintilla-1.63.tar.gz">http://savannah.nongnu.org/download/fxscintilla/fxscintilla-1.63.tar.gz</ulink>.</para>
+    url="http://download.savannah.gnu.org/releases/fxscintilla/fxscintilla-1.71.tar.gz">http://download.savannah.gnu.org/releases/fxscintilla/fxscintilla-1.71.tar.gz</ulink>.</para>
   </simplesect>
 
   <simplesect>
@@ -30,7 +30,7 @@
     applications. That is to say, you do not have to separately download the
     Scintilla source code from the Scintilla home page. When you unpack the
     FXScintilla tarball, you should get a new <filename class="directory">
-    fxscintilla-1.63</filename> directory containing the source code for the
+    fxscintilla-1.71</filename> directory containing the source code for the
     FOX port of the Scintilla widget.</para>
 
     <para>As of the 1.46 release of FXScintilla, the build process has been
@@ -61,13 +61,13 @@
     typing:</para>
 
     <screen>
-$ <command>sudo gem install fxruby-1.2.0.gem --force -- --with-fxscintilla-include=/usr/local/include/fxscintilla --with-fxscintilla-lib=/usr/local/lib</command>
+$ <command>sudo gem install fxruby-1.6.7.gem --force -- --with-fxscintilla-include=/usr/local/include/fxscintilla --with-fxscintilla-lib=/usr/local/lib</command>
 </screen>
 
     <para>or, when compiling with Microsoft Visual C++, by typing:</para>
 
     <screen>
-C:\&gt; <command>gem install fxruby-1.2.0.gem --force -- --with-fox-include=C:\fox-1.2.7\include --with-fox-lib=C:\fox-1.2.7\lib --with-fxscintilla-include=C:\fxscintilla-1.63\include --with-fxscintilla-lib=C:\fxscintilla-1.63\lib</command>
+C:\&gt; <command>gem install fxruby-1.6.7.gem --force -- --with-fox-include=C:\fox-1.6.25\include --with-fox-lib=C:\fox-1.6.25\lib --with-fxscintilla-include=C:\fxscintilla-1.71\include --with-fxscintilla-lib=C:\fxscintilla-1.71\lib</command>
 </screen>
 
     <para>Past this point, the build and installation process for either
diff --git a/doc/style.css b/doc/style.css
index 97f9605441e29726f7d02a8935df6f8d37ccd3f8..a584e5d2ff6593c575ec5a539966a0d28f7f790f 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -1,3 +1,247 @@
-pre.programlisting { background-color: #E0E0E0; }
-pre.screen { background-color: #E0E0E0; }
+/************************************************************************/
+/* Custom style-sheet stuffs for the Subversion book in HTML form.      */
+/************************************************************************/
 
+/*
+ * Copyright (c) 2003-2007
+ * Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato.  
+ * 
+ * This work is licensed under the Creative Commons Attribution License.
+ * To view a copy of this license, visit
+ * http://creativecommons.org/licenses/by/2.0/ or send a letter to
+ * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305,
+ * USA.
+ */
+
+body
+{
+    background: white;
+    margin: 0.5in;
+    font-family: arial,helvetica,sans-serif;
+}
+
+p, li, ul, ol, dd, dt
+{
+    font-style: normal;
+    font-weight: normal;
+    color: black;
+}
+
+tt, pre
+{
+    font-family: courier new,courier,fixed;
+}
+
+a
+{
+    color: blue;
+    text-decoration: underline;
+}    
+
+a:hover 
+{
+    background: rgb(75%,75%,100%);
+    color: blue;
+    text-decoration: underline;
+}
+
+a:visited 
+{
+    color: purple;
+    text-decoration: underline;
+}
+
+img
+{
+    border: none;
+}
+
+h1.title
+{
+    font-size: 250%;
+    font-style: normal;
+    font-weight: bold;
+    color: black;
+}
+
+h2.subtitle
+{
+    font-size: 150%;
+    font-style: italic;
+    color: black;
+}
+
+h2.title
+{
+    font-size: 150%;
+    font-style: normal;
+    font-weight: bold;
+    color: black;
+}
+
+h3.title
+{
+    font-size: 125%;
+    font-style: normal;
+    font-weight: bold;
+    color: black;
+}
+
+h4.title
+{
+    font-size: 100%;
+    font-style: normal;
+    font-weight: bold;
+    color: black;
+}
+
+.toc b
+{
+    font-size: 125%;
+    font-style: normal;
+    font-weight: bold;
+    color: black;
+}
+
+.command, .screen, .programlisting, .structname
+{
+    font-family: courier new,courier,fixed;
+    font-style: normal;
+    font-weight: normal;
+}
+
+.filename
+{
+    font-family: arial,helvetica,sans-serif;
+    font-style: italic;
+}
+
+.figure, .example, .table
+{
+    margin: 0.125in 0.25in;
+}
+
+.table table
+{
+    border-width: 1px;
+    border-style: solid;
+    border-color: black;
+    border-spacing: 0;
+    background: rgb(240,240,240);
+}
+
+.table td
+{
+    border: none;
+    border-right: 1px black solid;
+    border-bottom: 1px black solid;
+    padding: 2px;
+}
+
+.table th
+{
+    background: rgb(180,180,180);
+    border: none;
+    border-right: 1px black solid;
+    border-bottom: 1px black solid;
+    padding: 2px;
+}
+
+.table p.title, .figure p.title, .example p.title
+{
+    text-align: left !important;
+    font-size: 100% !important;
+}
+
+.author, .pubdate
+{
+    margin: 0;
+    font-size: 100%;
+    font-style: italic;
+    font-weight: normal;
+    color: black;
+}
+
+.preface div.author, .preface .pubdate
+{
+    font-size: 80%;
+}
+
+.sidebar 
+{
+    border-top: dotted 1px black;
+    border-left: dotted 1px black;
+    border-right: solid 2px black;
+    border-bottom: solid 2px black;
+    background: rgb(240,220,170);
+    padding: 0 0.12in;
+    margin: 0.25in;
+}
+
+.note .programlisting, .note .screen, 
+.tip .programlisting, .tip .screen, 
+.warning .programlisting, .warning .screen, 
+.sidebar .programlisting, .sidebar .screen
+{
+    border: none;
+    background: none;
+}
+
+.sidebar p.title
+{
+    text-align: center;
+    font-size: 125%;
+}
+
+.note
+{
+    border: black solid 1px;
+    background: url(./images/note.png) no-repeat rgb(252,246,220);
+    margin: 0.125in 0;
+    padding: 0 55px;
+}
+
+.tip
+{
+    border: black solid 1px;
+    background: url(./images/tip.png) no-repeat rgb(224,244,255);
+    margin: 0.125in 0;
+    padding: 0 55px;
+}
+
+.warning
+{
+    border: black solid 1px;
+    background: url(./images/warning.png) no-repeat rgb(255,210,210);
+    margin: 0.125in 0;
+    padding: 0 55px;
+}
+
+.note .title, .tip .title, .warning .title
+{
+    display: none;
+}
+
+.programlisting, .screen
+{
+    font-size: 90%;
+    color: black;
+    margin: 1em 0.25in;
+    padding: 0.5em;
+    background: rgb(240,240,240);
+    border-top: black dotted 1px;
+    border-left: black dotted 1px;
+    border-right: black solid 2px;
+    border-bottom: black solid 2px;
+}
+
+.navheader, .navfooter
+{
+    border: black solid 1px;
+    background: rgb(180,180,200);
+}
+
+.navheader hr, .navfooter hr
+{
+    display: none;
+}
diff --git a/examples/WhatAQuietStiff.rb b/examples/WhatAQuietStiff.rb
index 1d5f3802bc35e5bc8cdcac5cd41f18d19ed321ef..35b504cc983e02e55fdd38e2272d3f592dda9f6f 100755
--- a/examples/WhatAQuietStiff.rb
+++ b/examples/WhatAQuietStiff.rb
@@ -11,7 +11,6 @@
 #
 
 require 'fox16'
-require 'fox16/kwargs'
 require 'open-uri'
 
 begin
diff --git a/examples/babelfish.rb b/examples/babelfish.rb
index 79527f76c7f8b302f8a3bfbe5d0a042c9062e7cb..81b4d2b4471eb8249b975a13366c495d1b58d74f 100755
--- a/examples/babelfish.rb
+++ b/examples/babelfish.rb
@@ -1,57 +1,41 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
-require 'soap/rpc/driver'
+require 'tranexp'
 
 include Fox
 
 TRANSLATIONS = {
-  "English to French" => "en_fr",
-  "English to German" => "en_de",
-  "English to Italian" => "en_it",
-  "English to Japanese" => "en_jp",
-  "English to Korean" => "en_kr",
-  "English to Portugese" => "en_pt",
-  "English to Spanish" => "en_es",
-  "French to English" => "fr_en",
-  "German to English" => "de_en",
-  "Italian to English" => "it_en",
-  "Japanese to English" => "jp_en",
-  "Korean to English" => "kr_en",
-  "Portugese to English" => "pt_en",
-  "Spanish to English" => "es_en",
-  "Russian to English" => "ru_en",
-  "German to French" => "de_fr",
-  "French to German" => "fr_de"
+  "x" => "y"
 }
 
 class Babelfish < FXMainWindow
 
   def initialize(app)
     # Invoke base class initialize first
-    super(app, "Babelfish", nil, nil, DECOR_ALL,
-      0, 0, 600, 400, 0, 0)
-
-    # Initialize the SOAP driver
-    @drv = SOAP::RPC::Driver.new('http://services.xmethods.net/perl/soaplite.cgi', 'urn:xmethodsBabelFish')
-    @drv.add_rpc_method_with_soapaction('BabelFish',
-      'urn:xmethodsBabelFish#BabelFish', 'translationmode', 'sourcedata')
+    super(app, "Babelfish", :opts => DECOR_ALL, :width => 600, :height => 400)
 
+    @translator = Tranexp::Http.new
+    
     # Controls area along the bottom
     controlsFrame = FXHorizontalFrame.new(self,
       LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X)
     FXLabel.new(controlsFrame, "Translate from:")
-    @transModeCombo = FXComboBox.new(controlsFrame, 15, :opts => COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK)
-    @transModeCombo.numVisible = 6
-    TRANSLATIONS.keys.each do |key|
-      @transModeCombo.appendItem(key, TRANSLATIONS[key])
+    @fromCombo = FXComboBox.new(controlsFrame, 15, :opts => COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK)
+    @fromCombo.numVisible = 6
+    FXLabel.new(controlsFrame, " to:")
+    @toCombo = FXComboBox.new(controlsFrame, 15, :opts => COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK)
+    @toCombo.numVisible = 6
+    Tranexp::Codes.constants.each do |lang|
+      @fromCombo.appendItem(lang)
+      @toCombo.appendItem(lang)
     end
-    btn = FXButton.new(controlsFrame, "Translate", :opts => BUTTON_NORMAL|LAYOUT_SIDE_RIGHT)
+    btn = FXButton.new(controlsFrame, "Translate", :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
     btn.connect(SEL_COMMAND) do
-      transMode = @transModeCombo.getItemData(@transModeCombo.currentItem)
+      from = @fromCombo.getItemText(@fromCombo.currentItem)
+      to = @toCombo.getItemText(@toCombo.currentItem)
       getApp().beginWaitCursor() do
-        @translatedText.text = @drv.BabelFish(transMode, @sourceText.text)
+        @translatedText.text = @translator.translate(@sourceText.text, from, to)
       end
     end
 
@@ -80,15 +64,9 @@ class Babelfish < FXMainWindow
 end
 
 if __FILE__ == $0
-  # Make application
-  application = FXApp.new("Babelfish", "FoxTest")
-
-  # Make window
-  window = Babelfish.new(application)
-
-  # Create it
-  application.create
-
-  # Run
-  application.run
+  FXApp.new("Babelfish", "FoxTest") do |app|
+    Babelfish.new(app)
+    app.create
+    app.run
+  end
 end
diff --git a/examples/bounce.rb b/examples/bounce.rb
index 44cab454f58d9d187b1246933efeb114b7c69e00..f93cf95757eaa19f188d68077cb11c191f354d0a 100755
--- a/examples/bounce.rb
+++ b/examples/bounce.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/button.rb b/examples/button.rb
index 149d6acec01f0b077404e193cf3fda71f2e5e1ed..0da7e8815d4a17e95423c4bfb998a019ed29d49d 100755
--- a/examples/button.rb
+++ b/examples/button.rb
@@ -1,7 +1,6 @@
 #/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/charts.rb b/examples/charts.rb
new file mode 100644
index 0000000000000000000000000000000000000000..dfb42d40cebe7d59744ce70897a3048346d83b93
--- /dev/null
+++ b/examples/charts.rb
@@ -0,0 +1,35 @@
+require 'fox16'
+require 'google_chart'
+require 'open-uri'
+
+include Fox
+
+class ChartsWindow < FXMainWindow
+  def initialize(app)
+    super(app, "Google Charts Demo", :width => 650, :height => 250)
+    FXImageFrame.new(self, nil, :opts => LAYOUT_FILL) do |f|
+      f.image = FXPNGImage.new(app, open(bar_chart.to_escaped_url, "rb").read)
+    end
+  end
+  
+  def bar_chart
+    GoogleChart::BarChart.new('600x200', 'My Chart', :vertical) do |bc|
+      bc.data 'Trend 1', [5,4,3,1,3,5], '0000ff'
+      bc.data 'Trend 2', [1,2,3,4,5,6], 'ff0000'
+      bc.data 'Trend 3', [6,5,4,4,5,6], '00ff00'
+    end
+  end
+
+  def create
+    super
+    show(PLACEMENT_SCREEN)
+  end
+end
+
+if __FILE__ == $0
+  FXApp.new do |app|
+    ChartsWindow.new(app)
+    app.create
+    app.run
+  end
+end
\ No newline at end of file
diff --git a/examples/custom_table_item.rb b/examples/custom_table_item.rb
new file mode 100644
index 0000000000000000000000000000000000000000..acbf7cbec85d9a0df2986d886263227afcc57889
--- /dev/null
+++ b/examples/custom_table_item.rb
@@ -0,0 +1,170 @@
+require 'fox16'
+
+include Fox
+
+class CustomTableItem < FXTableItem
+	def drawContent(table, dc, x, y, w, h)
+	  puts "in drawContent()"
+		hg = table.horizontalGridShown?
+		vg = table.verticalGridShown?
+		ml = table.marginLeft + (vg ? 1 : 0)
+		mt = table.marginTop + (hg ? 1 : 0)
+		mr = table.marginRight
+		mb = table.marginBottom
+		font = dc.font
+		lbl = text
+		icn = icon
+
+		# Text width and height
+		beg, tw, th = 0, 0, 0
+		begin
+			_end = beg;
+			_end += 1 while _end < lbl.length && lbl[_end].chr != '\n' 
+			t = font.getTextWidth(lbl[beg..._end])
+			tw = t if t > tw
+			th += font.fontHeight
+			beg = _end + 1
+		end while _end < lbl.length
+
+		# Icon size
+		iw, ih = 0, 0
+		unless icn.nil?
+			iw = icn.width
+			ih = icn.height
+		end
+
+		# Icon-text spacing
+		s = 0
+		s = 4 if (iw > 0 && tw > 0)
+
+		# Fix x coordinate
+		if justify & LEFT == 1
+		  case iconPosition
+			when BEFORE
+			  ix = x + ml
+        tx = ix + iw + s
+			when AFTER
+			  tx = x + ml
+        ix = tx + tw + s
+			else
+			  ix = x + ml
+			  tx = x + ml
+			end
+		elsif justify & RIGHT == 1
+			case iconPosition
+		  when BEFORE
+				tx = x + w - mr - tw
+				ix = tx - iw - s
+			when AFTER
+				ix = x + w - mr - iw
+				tx = ix - tw - s
+			else
+			  ix = x + w - mr - iw
+			  tx = x + w - mr - tw
+			end
+		else
+		  case iconPosition
+			when BEFORE
+				ix = x + (ml + w - mr)/2 - (tw + iw + s)/2
+        tx = ix + iw + s
+			when AFTER
+				tx = x + (ml + w - mr)/2 - (tw + iw + s)/2
+        ix = tx + tw + s
+			else
+			  ix = x + (ml + w - mr)/2 - iw/2
+        tx = x + (ml + w - mr)/2 -tw/2
+      end
+		end
+
+		# Fix y coordinate
+		if justify & TOP == 1
+		  case iconPosition
+			when ABOVE
+			  iy = y + mt
+        ty = iy + ih
+			when BELOW
+			  ty = y + mt
+        iy = ty + th
+			else
+			  iy = y + mt
+			  ty = y + mt
+			end
+		elsif justify & BOTTOM == 1
+		  case iconPosition
+			when ABOVE
+			  ty = y + h - mb - th
+        iy = ty - ih
+			when BELOW
+			  iy = y + h - mb - ih
+        ty = iy - th
+			else
+			  iy = y + h - mb - ih
+			  ty = y + h - mb - th
+			end
+		else
+		  case iconPosition
+			when ABOVE
+				iy = y + (mt + h - mb)/2 - (th + ih)/2
+				ty = iy + ih
+			when BELOW
+				ty = y + (mt + h - mb)/2 - (th + ih)/2
+				iy = ty + th
+			else
+			  iy = y + (mt + h - mb)/2 - ih/2
+        ty = y + (mt + h - mb)/2 - th/2
+      end
+		end
+
+		# Paint icon
+		dc.drawIcon(icn, ix, iy) unless icn.nil?
+			
+		# Text color
+		if selected?
+			dc.foreground = table.selTextColor
+		else
+			dc.foreground = table.textColor
+		end
+		puts "dc.foreground = (#{FXREDVAL(dc.foreground)}, #{FXGREENVAL(dc.foreground)}, #{FXBLUEVAL(dc.foreground)})"
+
+		# Draw text
+		yy = ty + font.fontAscent
+		beg = 0
+		begin
+			_end = beg
+			_end += 1 while _end < lbl.length && lbl[_end].chr != '\n' 
+			if justify & LEFT == 1
+			  xx = tx
+			elsif justify & RIGHT == 1
+        xx = tx + tw - font.getTextWidth(lbl[beg..._end])
+			else
+        xx = tx + (tw - font.getTextWidth(lbl[beg..._end]))/2
+      end
+			dc.drawText(xx, yy, lbl[beg..._end])
+			yy += font.fontHeight
+			beg = _end + 1
+		end while _end < lbl.length
+	end
+end
+
+class CustomTable < FXTable
+	def createItem *parameters
+		CustomTableItem.new *parameters
+	end
+end
+
+app = FXApp.new
+main = FXMainWindow.new app, 'Test'
+
+table = CustomTable.new main
+table.setTableSize 2, 2
+table.visibleRows = 2
+table.visibleColumns = 2
+
+table.setItemText 0, 0, 'one'
+table.setItemText 0, 1, 'two'
+table.setItemText 1, 0, 'three'
+table.setItemText 1, 1, 'four'
+
+app.create
+main.show PLACEMENT_SCREEN
+app.run
diff --git a/examples/datatarget.rb b/examples/datatarget.rb
index b49f5094d4ff39db3be5eab278b7d07c5291dc3b..816ce42a53fe8386567d45db6a6d69fa9201e18e 100755
--- a/examples/datatarget.rb
+++ b/examples/datatarget.rb
@@ -2,7 +2,6 @@
 
 require 'fox16'
 require 'fox16/colors'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/dialog.rb b/examples/dialog.rb
index 33e841e70fe0825e0acf20a4cafc66e8db40ec64..c352c0d345b54aa4675247b6bf88bb1e184653f8 100755
--- a/examples/dialog.rb
+++ b/examples/dialog.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/dilbert.rb b/examples/dilbert.rb
index aafd5ac3ba4f4e13b9b1041b2377bedd14fbb717..955c6be81723ddec36eb1ea762537f100a7f6f94 100755
--- a/examples/dilbert.rb
+++ b/examples/dilbert.rb
@@ -1,16 +1,15 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 require 'open-uri'
 begin
-  require 'rubyful_soup'
+  require 'hpricot'
 rescue LoadError
   require 'fox16/missingdep'
   MSG = <<EOM
-  Sorry, this example depends on the RubyfulSoup extension. Please
-  check the Ruby Application Archives for an appropriate
-  download site.
+  Sorry, this example depends on the Hpricot extension. Please
+  see http://code.whytheluckystiff.net/hpricot/ for instructions
+  on how to install Hpricot.
 EOM
   missingDependency(MSG)
 end
@@ -41,9 +40,8 @@ class DailyDilbert < FXMainWindow
   end
   
   def image_data
-    src = open("http://www.dilbert.com/").read
-    soup = BeautifulSoup.new(src)
-    url = soup.find('img', { :attrs => { 'alt' => /Today's Comic/ } })
+    doc = Hpricot(open("http://www.dilbert.com/"))
+    url = doc.search("img").find { |e| e['src'] =~ /\/dyn\/str_strip\/.*\.gif/ }
     open("http://www.dilbert.com" + url['src'], "rb").read
   end
   
diff --git a/examples/dirlist.rb b/examples/dirlist.rb
index d8871df87365048ef633b733052c86f95bfb56be..3c7f38f5bb35cfe70c253f13ae8f39cdafb4bc31 100755
--- a/examples/dirlist.rb
+++ b/examples/dirlist.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/dragdrop.rb b/examples/dragdrop.rb
index fb664b74501e91dc2b2d35ba2ef7530da19ef561..08f0d60bbd1c7286600eb34b4bc68d7d4c79b2d7 100755
--- a/examples/dragdrop.rb
+++ b/examples/dragdrop.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/dragsource.rb b/examples/dragsource.rb
index a1c54aa197548129bc7c2696de6e36f1df771eb4..f7406b0139748a88ea1b07a89af4d7e67a2ca58e 100755
--- a/examples/dragsource.rb
+++ b/examples/dragsource.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/dropsite.rb b/examples/dropsite.rb
index 070ca0dbefd0a5be871c3a3abd5d824e64853724..fd2ba48898c640b3cd5c197a56fb92164fd38bfd 100755
--- a/examples/dropsite.rb
+++ b/examples/dropsite.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
@@ -7,7 +6,7 @@ class DropSite < FXMainWindow
   
   def initialize(anApp)
     # Initialize base class
-    super(anApp, "Drop Site",:opts => DECOR_ALL, :width => 400, :height => 300)
+    super(anApp, "Drop Site", :opts => DECOR_ALL, :width => 400, :height => 300)
     
     # Fill main window with canvas
     @canvas = FXCanvas.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
diff --git a/examples/foursplit.rb b/examples/foursplit.rb
index 80fbd73f7ad70299817948b2639901d5bcb91b65..3761c055c386442ce7be3814a48fe0ed7effce17 100755
--- a/examples/foursplit.rb
+++ b/examples/foursplit.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/gdchart.rb b/examples/gdchart.rb
index 1be7a1b2c936de314093044140cca414ad8481fd..5375826ebab629c2c456bb9ac5c0df8026bc2da1 100755
--- a/examples/gdchart.rb
+++ b/examples/gdchart.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 require 'tempfile'
 begin
   require 'GDChart'
diff --git a/examples/gembrowser.rb b/examples/gembrowser.rb
index 14a61f40826c445c1da230751e998fc921f89033..04d9fefaf90729cdd11a12cce243450ea7af3350 100755
--- a/examples/gembrowser.rb
+++ b/examples/gembrowser.rb
@@ -180,7 +180,7 @@ class GemBrowserWindow < FXMainWindow
     super(anApp, "Gem Browser", nil, nil, DECOR_ALL)
 
     # Menu bar
-    menubar = FXMenubar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
+    menubar = FXMenuBar.new(self, LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
 
     # File menu
     filemenu = FXMenuPane.new(self)
diff --git a/examples/gltest.rb b/examples/gltest.rb
index d36ff5d6e6746563a40666e1101f6886ccb6a7cf..7333c900b6d039436bdabfdcdaf518c077bb063d 100755
--- a/examples/gltest.rb
+++ b/examples/gltest.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 begin
   require 'opengl'
 rescue LoadError
@@ -22,26 +21,6 @@ class GLTestWindow < FXMainWindow
   # How often our timer will fire (in milliseconds)
   TIMER_INTERVAL = 100
 
-  # Rotate the boxes when a timer message is received
-  def onTimeout(sender, sel, ptr)
-    @angle += 2.0
-    if @angle > 360.0
-      @angle -= 360.0
-    end
-    drawScene()
-    @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
-  end
-
-  # Rotate the boxes when a chore message is received
-  def onChore(sender, sel, ptr)
-    @angle += 2.0
-    if @angle > 360.0
-      @angle -= 360.0
-    end
-    drawScene()
-    @chore = getApp().addChore(method(:onChore))
-  end
-
   # Draws a simple box using the given corners
   def drawBox(xmin, ymin, zmin, xmax, ymax, zmax)
     GL.Begin(GL::TRIANGLE_STRIP)
@@ -251,7 +230,13 @@ class GLTestWindow < FXMainWindow
     spinTimerBtn.padTop, spinTimerBtn.padBottom = 5, 5
     spinTimerBtn.connect(SEL_COMMAND) do
       @spinning = true
-      @timer = getApp().addTimeout(TIMER_INTERVAL, method(:onTimeout))
+      @timer = getApp().addTimeout(TIMER_INTERVAL, :repeat => true) do
+        @angle += 2.0
+        if @angle > 360.0
+          @angle -= 360.0
+        end
+        drawScene()
+      end
     end
     spinTimerBtn.connect(SEL_UPDATE) do |sender, sel, ptr|
       @spinning ? sender.disable : sender.enable
@@ -266,7 +251,13 @@ class GLTestWindow < FXMainWindow
     spinChoreBtn.padTop, spinChoreBtn.padBottom = 5, 5
     spinChoreBtn.connect(SEL_COMMAND) do
       @spinning = true
-      @chore = getApp().addChore(method(:onChore))
+      @chore = getApp().addChore(:repeat => true) do
+        @angle += 2.0
+        if @angle > 360.0
+          @angle -= 360.0
+        end
+        drawScene()
+      end
     end
     spinChoreBtn.connect(SEL_UPDATE) do |sender, sel, ptr|
       @spinning ? sender.disable : sender.enable
diff --git a/examples/glviewer.rb b/examples/glviewer.rb
index c2f0ebf08e075823ca4545db0cae2770d141e7c3..6a4c28acf68063905009b3624a1512e2ebba54bb 100755
--- a/examples/glviewer.rb
+++ b/examples/glviewer.rb
@@ -2,7 +2,6 @@
 
 require 'fox16'
 require 'fox16/responder'
-require 'fox16/kwargs'
 begin
   require 'fox16/glshapes'
 rescue LoadError
diff --git a/examples/groupbox.rb b/examples/groupbox.rb
index b25beb35193f315457a6c7af4fd6e6e42bb8e944..f988521e6c11cefd0cdcb87b5665f8613c87c362 100755
--- a/examples/groupbox.rb
+++ b/examples/groupbox.rb
@@ -22,7 +22,7 @@ class GroupWindow < FXMainWindow
 
   def initialize(app)
     # Call the base class version of initialize
-    super(app, "Group Box Test", nil, nil, DECOR_ALL, 0, 0, 0, 0)
+    super(app, "Group Box Test", :opts => DECOR_ALL)
 
     # Some icons we'll use here and there
     doc = getIcon("minidoc.png")
@@ -102,8 +102,7 @@ class GroupWindow < FXMainWindow
     FXMenuTitle.new(menubar, "&Help", nil, helpmenu, LAYOUT_RIGHT)
   
     @popupmenu = FXMenuPane.new(self)
-      poptext = FXTextField.new(@popupmenu, 10, nil, 0,
-        FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP, 0, 0, 0, 0)
+      poptext = FXTextField.new(@popupmenu, 10, :opts => FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP)
       poptext.setText("Popup with text")
     
     # Status bar
@@ -129,8 +128,7 @@ class GroupWindow < FXMainWindow
     testlabel.setFont(FXFont.new(getApp(), "helvetica", 24, FONTWEIGHT_BOLD,
                                  FONTSLANT_ITALIC, FONTENCODING_DEFAULT))
     FXButton.new(group1, "Small &Button", nil, nil, 0, FRAME_RAISED|FRAME_THICK)
-    FXButton.new(group1, "Big Fat Wide Button\nComprising\nthree lines", nil,
-      nil, 0, FRAME_RAISED|FRAME_THICK)
+    FXButton.new(group1, "Big Fat Wide Button\nComprising\nthree lines", :opts => FRAME_RAISED|FRAME_THICK)
     FXToggleButton.new(group1,
       "C&losed\tTooltip for closed\tHelp for closed",
       "O&pen\nState\tTooltip for open\tHelp for open",
@@ -138,94 +136,66 @@ class GroupWindow < FXMainWindow
       ICON_BEFORE_TEXT|JUSTIFY_LEFT|FRAME_RAISED|FRAME_THICK)
   
     pop = FXPopup.new(self)
-    
-    FXOption.new(pop, "First\tTip #1\tHelp first", nil, nil, 0,
-      JUSTIFY_HZ_APART|ICON_AFTER_TEXT).connect(SEL_COMMAND) {
-        FXMessageBox.information(self, MBOX_OK, "Option Menu", "Chose option 1")
-    }
-    FXOption.new(pop, "Second\tTip #2\tHelp second", nil, nil, 0,
-      JUSTIFY_HZ_APART|ICON_AFTER_TEXT).connect(SEL_COMMAND) {
-        FXMessageBox.information(self, MBOX_OK, "Option Menu", "Chose option 2")
-    }
-    FXOption.new(pop, "Third\tTip #3\tHelp third", nil, nil, 0,
-      JUSTIFY_HZ_APART|ICON_AFTER_TEXT).connect(SEL_COMMAND) {
-        FXMessageBox.information(self, MBOX_OK, "Option Menu", "Chose option 3")
-    }
-    FXOption.new(pop, "Fourth\tTip #4\tHelp fourth", nil, nil, 0,
-      JUSTIFY_HZ_APART|ICON_AFTER_TEXT).connect(SEL_COMMAND) {
-        FXMessageBox.information(self, MBOX_OK, "Option Menu", "Chose option 4")
-    }
+    numbers =%w{first second third fourth}
+    0.upto(3) do |idx|
+      FXOption.new(pop, "#{numbers[idx].capitalize}\tTip #{idx+1}\tHelp #{numbers[idx]}", :opts => JUSTIFY_HZ_APART|ICON_AFTER_TEXT).connect(SEL_COMMAND) {
+          FXMessageBox.information(self, MBOX_OK, "Option Menu", "Chose option #{idx+1}")
+      }
+    end
     
     FXOptionMenu.new(group1, pop,
       LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|JUSTIFY_HZ_APART|ICON_AFTER_TEXT)
   
     FXLabel.new(group1, "Te&kstje", nil, LAYOUT_TOP|JUSTIFY_LEFT)
     FXButton.new(group1,
-      "Add an `&&' by doubling\tTooltip\tHelp text for status", nil,
-      nil, 0,LAYOUT_TOP|FRAME_RAISED|FRAME_THICK)
-    FXButton.new(group1, "Te&kstje", nil, nil, 0,
-      LAYOUT_TOP|FRAME_RAISED|FRAME_THICK).connect(SEL_COMMAND) {
+      "Add an `&&' by doubling\tTooltip\tHelp text for status", :opts => LAYOUT_TOP|FRAME_RAISED|FRAME_THICK)
+    FXButton.new(group1, "Te&kstje", :opts => LAYOUT_TOP|FRAME_RAISED|FRAME_THICK).connect(SEL_COMMAND) {
       x, y, buttons = getRoot().getCursorPosition()
       @popupmenu.popup(nil, x, y)
     }
     
-    FXMenuButton.new(group1, "&Menu", nil, filemenu,
-      (MENUBUTTON_ATTACH_BOTH|MENUBUTTON_DOWN|JUSTIFY_HZ_APART|LAYOUT_TOP|
-       FRAME_RAISED|FRAME_THICK|ICON_AFTER_TEXT))
-    FXMenuButton.new(group1, "&Menu", nil, filemenu,
-      MENUBUTTON_UP|LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|ICON_AFTER_TEXT)
+    FXMenuButton.new(group1, "&Menu", :opts => MENUBUTTON_ATTACH_BOTH|MENUBUTTON_DOWN|JUSTIFY_HZ_APART|LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|ICON_AFTER_TEXT)
+    FXMenuButton.new(group1, "&Menu", nil, filemenu, MENUBUTTON_UP|LAYOUT_TOP|FRAME_RAISED|FRAME_THICK|ICON_AFTER_TEXT)
   
     coolpop = FXPopup.new(self, POPUP_HORIZONTAL)
-    FXButton.new(coolpop, "A\tTipA", nil, nil, 0,
-      FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 30, 30)
-    FXButton.new(coolpop, "B\tTipB", nil, nil, 0,
-      FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 30, 30)
-    FXButton.new(coolpop, "C\tTipC", nil, nil, 0,
-      FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 30, 30)
-    FXButton.new(coolpop, "D\tTipD", nil, nil, 0,
-      FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 30, 30)
+    FXButton.new(coolpop, "A\tTipA",
+      :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 30, :height => 30)
+    FXButton.new(coolpop, "B\tTipB",
+      :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 30, :height => 30)
+    FXButton.new(coolpop, "C\tTipC",
+      :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 30, :height => 30)
+    FXButton.new(coolpop, "D\tTipD",
+      :opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, :width => 30, :height => 30)
     FXMenuButton.new(group1, "&S\tSideways", nil, coolpop,
       (MENUBUTTON_ATTACH_BOTH|MENUBUTTON_LEFT|MENUBUTTON_NOARROWS|LAYOUT_TOP|
-       FRAME_RAISED|FRAME_THICK|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT), 0, 0, 30, 30)
+       FRAME_RAISED|FRAME_THICK|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT), :width => 30, :height => 30)
     
     matrix = FXMatrix.new(group1, 3,
       FRAME_RAISED|LAYOUT_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
-    FXButton.new(matrix, "A", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FILL_ROW)
-    FXButton.new(matrix, "&Wide button", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
-    FXButton.new(matrix, "A", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
+    FXButton.new(matrix, "A", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FILL_ROW)
+    FXButton.new(matrix, "&Wide button", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
+    FXButton.new(matrix, "A", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X)
     
-    FXButton.new(matrix, "BBBB", nil, nil, 0, (FRAME_RAISED|FRAME_THICK|
-      LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FILL_ROW|LAYOUT_FILL_COLUMN))
-    FXButton.new(matrix, "B", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
-    FXButton.new(matrix, "BB", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
+    FXButton.new(matrix, "BBBB", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FILL_ROW|LAYOUT_FILL_COLUMN)
+    FXButton.new(matrix, "B", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
+    FXButton.new(matrix, "BB", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_COLUMN)
     
-    FXButton.new(matrix, "C", nil, nil, 0,
-      FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|LAYOUT_FILL_ROW)
-    FXButton.new(matrix, "&wide", nil, nil, 0, FRAME_RAISED|FRAME_THICK)
-    FXButton.new(matrix, "CC", nil, nil, 0, FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT)
+    FXButton.new(matrix, "C", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_CENTER_X|LAYOUT_FILL_ROW)
+    FXButton.new(matrix, "&wide", :opts => FRAME_RAISED|FRAME_THICK)
+    FXButton.new(matrix, "CC", :opts => FRAME_RAISED|FRAME_THICK|LAYOUT_RIGHT)
     
     FXLabel.new(group2, "No Arrow")
-    FXSlider.new(group2, nil, 0,
-      LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL,
-      0, 0, 200, 30)
+    FXSlider.new(group2, :opts => LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL, :width => 200, :height => 30)
     
     FXLabel.new(group2, "Up Arrow")
-    FXSlider.new(group2, nil, 0, (LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|
-      SLIDER_HORIZONTAL|SLIDER_ARROW_UP), 0, 0, 200, 30)
+    FXSlider.new(group2, :opts => LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL|SLIDER_ARROW_UP, :width => 200, :height => 30)
     
     FXLabel.new(group2, "Down Arrow")
-    FXSlider.new(group2, nil, 0, (LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|
-      SLIDER_HORIZONTAL|SLIDER_ARROW_DOWN), 0, 0, 200, 30)
+    FXSlider.new(group2, :opts => LAYOUT_TOP|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL|SLIDER_ARROW_DOWN, :width => 200, :height => 30)
     
     FXLabel.new(group2, "Inside Bar")
-    slider = FXSlider.new(group2, nil, 0, (LAYOUT_TOP|LAYOUT_FILL_X|
-      LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL|SLIDER_INSIDE_BAR), 0, 0, 200, 20)  
+    slider = FXSlider.new(group2, :opts => LAYOUT_TOP|LAYOUT_FILL_X|LAYOUT_FIX_HEIGHT|SLIDER_HORIZONTAL|SLIDER_INSIDE_BAR, :width => 200, :height => 20)  
     slider.range = 0..3
     
     frame = FXHorizontalFrame.new(group2, LAYOUT_FILL_X|LAYOUT_FILL_Y)
@@ -252,8 +222,7 @@ class GroupWindow < FXMainWindow
       LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK|ARROW_RIGHT)
   
     vframe2 = FXVerticalFrame.new(frame, LAYOUT_FILL_X|LAYOUT_FILL_Y)
-    FXArrowButton.new(vframe2, nil, 0, (LAYOUT_FILL_X|LAYOUT_FILL_Y|
-      FRAME_RAISED|FRAME_THICK|ARROW_UP|ARROW_TOOLBAR))
+    FXArrowButton.new(vframe2, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK|ARROW_UP|ARROW_TOOLBAR)
     FXArrowButton.new(vframe2, nil, 0, (LAYOUT_FILL_X|LAYOUT_FILL_Y|
       FRAME_RAISED|FRAME_THICK|ARROW_DOWN|ARROW_TOOLBAR))
     FXArrowButton.new(vframe2, nil, 0, (LAYOUT_FILL_X|LAYOUT_FILL_Y|
diff --git a/examples/header.rb b/examples/header.rb
index aaf64f227b85aca622ecc21a86552cad42c1f783..7f448072d95151bcec245fb2b9f8645891e0973e 100755
--- a/examples/header.rb
+++ b/examples/header.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/iconlist.rb b/examples/iconlist.rb
index 6dc8622ceb11cf88424d0255049afe5457305c1f..399ba95b6f8b485a25489080c22c475705daf5a0 100755
--- a/examples/iconlist.rb
+++ b/examples/iconlist.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/image.rb b/examples/image.rb
index a6a38e8024b2e85c281aa0aab0f26e180d1114d6..44010364fcd85d6024d549f3cad554248467aa77 100755
--- a/examples/image.rb
+++ b/examples/image.rb
@@ -2,7 +2,6 @@
 
 require 'fox16'
 require 'fox16/colors'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/imageviewer.rb b/examples/imageviewer.rb
index 3a062d365f1fc12286460d858bbedaa1664c315b..27d23196680b4e14f47547ccb7f248164a9589ea 100755
--- a/examples/imageviewer.rb
+++ b/examples/imageviewer.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
@@ -87,7 +86,7 @@ class ImageWindow < FXMainWindow
     # Make file list
     fileframe = FXHorizontalFrame.new(@filebox,
       FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y,
-      :padLeft => 0, :padRight => 0, :padTop => 0, :padBottom => 0. :hSpacing => 0, :vSpacing => 0)
+      :padLeft => 0, :padRight => 0, :padTop => 0, :padBottom => 0, :hSpacing => 0, :vSpacing => 0)
     @filelist = FXFileList.new(fileframe,
       :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|ICONLIST_MINI_ICONS|ICONLIST_AUTOSIZE)
     @filelist.connect(SEL_DOUBLECLICKED, method(:onCmdFileList))
diff --git a/examples/inputs.rb b/examples/inputs.rb
index e00dde617496ede06186510985ea3f0d35fb64f3..76576256f21be3ab7e313e27cdc41f87ce03f9a9 100755
--- a/examples/inputs.rb
+++ b/examples/inputs.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
@@ -55,7 +54,7 @@ class InputHandlerWindow < FXMainWindow
     getApp().addInput(@pipe, INPUT_READ|INPUT_EXCEPT) do |sender, sel, ptr|
       case FXSELTYPE(sel)
       when SEL_IO_READ
-        text = @pipe.read
+        text = @pipe.read_nonblock(256)
         if text && text.length > 0
           @cmdOutput.appendText(text)
         else
diff --git a/examples/mditest.rb b/examples/mditest.rb
index e311104662f30125e3a02724fd7b743fec8db680..0899a78f4b84653a28f766ff0eff54fee0d3730f 100755
--- a/examples/mditest.rb
+++ b/examples/mditest.rb
@@ -2,7 +2,6 @@
 
 require 'fox16'
 require 'fox16/colors'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/pig.rb b/examples/pig.rb
index 784238db109df8feb5b7ad29b3eebeaddee36d0b..2eadc9bafec7d1e007342c755f229401cf1095e1 100755
--- a/examples/pig.rb
+++ b/examples/pig.rb
@@ -5,7 +5,6 @@
 #
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/raabrowser.rb b/examples/raabrowser.rb
index 7997a6c65179d09007c3887bbddd7eb9f4e84898..ec3ba2a1670f44dc9367fc222d8e8fd99882e928 100755
--- a/examples/raabrowser.rb
+++ b/examples/raabrowser.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 require 'cgi'
 require 'soap/wsdlDriver'
 
diff --git a/examples/ratio.rb b/examples/ratio.rb
index be0eb464860bbe5fa6935debb887f88869d21f63..6bca0b39a960a891afd333180a6b942fea2f30c2 100644
--- a/examples/ratio.rb
+++ b/examples/ratio.rb
@@ -6,7 +6,6 @@
 
 require 'fox16'
 require 'fox16/colors'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/rmagick.rb b/examples/rmagick.rb
new file mode 100755
index 0000000000000000000000000000000000000000..7632d2a9d8a08dbbd6aef06c50ed3ddb1b87f4fa
--- /dev/null
+++ b/examples/rmagick.rb
@@ -0,0 +1,44 @@
+require 'fox16'
+require 'RMagick'
+
+include Fox
+
+class RMagickExample < FXMainWindow
+  
+  def initialize(app)
+    super(app, "RMagick Example", :width => 800, :height => 600)
+    
+    # Construct an ImageList
+    dippy = Magick::ImageList.new(File.join("icons", "dippy.png"))
+    
+    # Manipulate the image
+    text = Magick::Draw.new
+    text.annotate(dippy, 0, 0, 0, 60, "Dippy Duck") do
+      self.gravity = Magick::SouthGravity
+      self.pointsize = 24
+      self.stroke = 'transparent'
+      self.fill = '#0000A9'
+      self.font_weight = Magick::BoldWeight
+    end
+        
+    # Extract image data and use it to construct FXPNGImage
+    dippy_image = FXPNGImage.new(app, dippy.to_blob)
+    
+    # Display it inside an FXImageFrame
+    FXImageFrame.new(self, dippy_image, :opts => LAYOUT_FILL)
+  end
+  
+  def create
+    super
+    show(PLACEMENT_SCREEN)
+  end
+  
+end
+
+if __FILE__ == $0
+  FXApp.new("RMagick Example", "FXRuby") do |app|
+    RMagickExample.new(app)
+    app.create
+    app.run
+  end
+end
\ No newline at end of file
diff --git a/examples/rulerview.rb b/examples/rulerview.rb
index b636d27cb45abbf02e515e0a98024d20fe69325d..187d6743b2fc17697a459ab468145ad838ce7a74 100644
--- a/examples/rulerview.rb
+++ b/examples/rulerview.rb
@@ -1,5 +1,4 @@
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/scribble.rb b/examples/scribble.rb
index 52e431fa983038ea2d2fdf4bb994f93479161336..343e605d753cbc296f099bbc18ac08e1a50b2e50 100755
--- a/examples/scribble.rb
+++ b/examples/scribble.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/shutter.rb b/examples/shutter.rb
index ff9af72341ed971a85399958779ad9e022556466..aefbac40aab420d6a8e7ff92662c8fbfd2c73ed1 100755
--- a/examples/shutter.rb
+++ b/examples/shutter.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/splitter.rb b/examples/splitter.rb
index 10015d6d6073533bb51074a511d1f725822dc79f..f067e521a20dd883319a332043b6d488867314e0 100755
--- a/examples/splitter.rb
+++ b/examples/splitter.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/styledtext.rb b/examples/styledtext.rb
index 9c7ee539e739f4dc5293614517de35eea6a020c8..a0808b839c351045e0686b291048cf1a74fad8a7 100755
--- a/examples/styledtext.rb
+++ b/examples/styledtext.rb
@@ -40,24 +40,14 @@ class StyledTextWindow < FXMainWindow
       TEXT_READONLY|TEXT_WORDWRAP|LAYOUT_FILL_X|LAYOUT_FILL_Y)
     
     # Construct some hilite styles
-    hs1 = FXHiliteStyle.new
+    hs1 = FXHiliteStyle.from_text(text)
     hs1.normalForeColor = FXColor::Red
     hs1.normalBackColor = FXColor::Blue
-    hs1.selectForeColor = text.selTextColor
-    hs1.selectBackColor = text.selBackColor
-    hs1.hiliteForeColor = text.hiliteTextColor
-    hs1.hiliteBackColor = text.hiliteBackColor
-    hs1.activeBackColor = text.activeBackColor
-    hs1.style = 0
+    hs1.style = FXText::STYLE_BOLD
 
-    hs2 = FXHiliteStyle.new
+    hs2 = FXHiliteStyle.from_text(text)
     hs2.normalForeColor = FXColor::Blue
     hs2.normalBackColor = FXColor::Yellow
-    hs2.selectForeColor = text.selTextColor
-    hs2.selectBackColor = text.selBackColor
-    hs2.hiliteForeColor = text.hiliteTextColor
-    hs2.hiliteBackColor = text.hiliteBackColor
-    hs2.activeBackColor = text.activeBackColor
     hs2.style = FXText::STYLE_UNDERLINE
     
     # Enable the style buffer for this text widget
diff --git a/examples/tabbook.rb b/examples/tabbook.rb
index 20517fcef10037dbe77a4a3e414d14bb948e66c8..ea6bbe324053b79f6d601ce0d21c09a9048eff6c 100755
--- a/examples/tabbook.rb
+++ b/examples/tabbook.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 
 include Fox
 
diff --git a/examples/table.rb b/examples/table.rb
index 78cc30c503361f2946f28281583c0eecb7df8c10..c98f1da472290fadc58611a29a5039b24007fa1d 100755
--- a/examples/table.rb
+++ b/examples/table.rb
@@ -1,7 +1,6 @@
 #!/usr/bin/env ruby
 
 require 'fox16'
-require 'fox16/kwargs'
 require 'date'
 
 include Fox
diff --git a/ext/fox16/FXRbApp.cpp b/ext/fox16/FXRbApp.cpp
index e819ba6f1812a1c9ae55df1f6b7eed4ee19175e4..ba78205879915cf6deb7576a760276ac52c08020 100755
--- a/ext/fox16/FXRbApp.cpp
+++ b/ext/fox16/FXRbApp.cpp
@@ -21,14 +21,16 @@
  ***********************************************************************/
 
 /***********************************************************************
- * $Id: FXRbApp.cpp 2190 2005-08-24 07:58:47Z lyle $
+ * $Id: FXRbApp.cpp 2902 2008-12-11 14:09:20Z lyle $
  ***********************************************************************/
 
 #include "FXRbCommon.h"
 
+#ifndef RUBY_1_9
 extern "C" {
 #include "rubysig.h" /* For CHECK_INTS */
 }
+#endif
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h> /* For struct timeval */
@@ -95,9 +97,14 @@ long FXRbApp::onChoreThreads(FXObject*,FXSelector,void*){
   wait.tv_usec=100*sleepTime;
 
   // Confirm that this thread can be interrupted, then go to sleep
+#ifndef RUBY_1_9
   CHECK_INTS;
   if(!rb_thread_critical)
     rb_thread_wait_for(wait);
+#else
+  // if(!rb_thread_critical) rb_thread_wait_for(wait);
+  rb_thread_wait_for(wait);
+#endif /* RUBY_1_9 */
 
   // Re-register this chore for next time
   addChore(this,ID_CHORE_THREADS);
diff --git a/ext/fox16/FXRbDataTarget.cpp b/ext/fox16/FXRbDataTarget.cpp
index 0880313e066b531ca76a14e5cb14e5e004cd85a2..d388c9b595a4e97287b444a107cb0aed5fc1d3eb 100755
--- a/ext/fox16/FXRbDataTarget.cpp
+++ b/ext/fox16/FXRbDataTarget.cpp
@@ -21,7 +21,7 @@
  ***********************************************************************/
 
 /***********************************************************************
- * $Id: FXRbDataTarget.cpp 2190 2005-08-24 07:58:47Z lyle $
+ * $Id: FXRbDataTarget.cpp 2713 2007-11-14 15:27:36Z lyle $
  ***********************************************************************/
 
 #include "FXRbCommon.h"
@@ -57,7 +57,7 @@ void FXRbDataTarget::setValue(VALUE value){
       connect(doubleValue);
       break;
     case T_STRING:
-      stringValue=STR2CSTR(value);
+      stringValue=StringValuePtr(value);
       connect(stringValue);
       break;
     case T_TRUE:
diff --git a/ext/fox16/FXRuby.cpp b/ext/fox16/FXRuby.cpp
index 81f4d720cb080c457f5172f681e33e32af0e5465..650418c142193ddef858e9db07058f2dac53d8e7 100755
--- a/ext/fox16/FXRuby.cpp
+++ b/ext/fox16/FXRuby.cpp
@@ -21,7 +21,7 @@
  ***********************************************************************/
 
 /***********************************************************************
- * $Id: FXRuby.cpp 2608 2007-02-09 20:34:16Z lyle $
+ * $Id: FXRuby.cpp 2933 2008-12-29 20:19:33Z lyle $
  ***********************************************************************/
 
 #ifdef _MSC_VER
@@ -30,16 +30,18 @@
 
 #include "FXRbCommon.h"
 
+#ifndef RUBY_1_9
 #include "version.h"
 
 #if RUBY_VERSION_CODE < 167
 #define RB_RESCUE2_BROKEN_PROTOTYPE 1
 #endif
 
-/* The prototype for st_foreach() changed at Ruby version 1.8.2 */
+// The prototype for st_foreach() changed at Ruby version 1.8.2
 #if RUBY_VERSION_CODE < 182
 #define ST_BROKEN_PROTOTYPES 1
 #endif
+#endif /* RUBY_1_9 */
 
 #include "impl.h"
 
@@ -51,15 +53,19 @@
 #include <signal.h>	// for definitions of SIGINT, etc.
 #endif
 
+#ifndef RUBY_1_9
 extern "C" {
 #include "rubyio.h"	// for GetOpenFile(), etc.
 }
+#else
+#include "ruby/io.h"
+#endif
 
 // Symbol table functions from Ruby. If we included "st.h" directly
 // we'd be dealing with broken prototypes anyways, so just duplicate
 // the needed declarations here with the correct prototypes.
 
-#ifdef ST_BROKEN_PROTOTYPES
+#if defined(ST_BROKEN_PROTOTYPES)
 
 extern "C" {
 
@@ -78,11 +84,19 @@ void st_foreach(st_table *table, int (*func)(st_data_t, st_data_t, st_data_t), s
 
 #else
 
+#ifdef RUBY_1_9
+
+#include "ruby/st.h"
+
+#else
+
 extern "C" {
 #include "st.h"
 }
 
-#endif
+#endif /* RUBY_1_9 */
+
+#endif /* ST_BROKEN_PROTOTYPES */
 
 // Opaque type declaration from SWIG runtime
 struct swig_type_info;
@@ -136,13 +150,11 @@ VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
     FXASSERT(ty!=0);
     VALUE obj;
     FXRubyObjDesc *desc;
-    int result;
     if(FXMALLOC(&desc,FXRubyObjDesc,1)){
       obj=SWIG_Ruby_NewPointerObj(ptr,ty,1);
       desc->obj=obj;
       desc->borrowed=true;
-      result=st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t>(desc));
-      FXASSERT(result==0);
+      st_insert(FXRuby_Objects,reinterpret_cast<st_data_t>(ptr),reinterpret_cast<st_data_t>(desc));
       return obj;
       }
     else{
@@ -189,9 +201,15 @@ FXbool FXRbCatchExceptions=FALSE;
 
 // Returns an FXInputHandle for this Ruby file object
 FXInputHandle FXRbGetReadFileHandle(VALUE obj) {
+#ifdef RUBY_1_9
+  rb_io_t *fptr;
+  GetOpenFile(obj, fptr);
+  FILE *fpr=fptr->stdio_file;
+#else
   OpenFile *fptr;
   GetOpenFile(obj, fptr);
   FILE *fpr=GetReadFile(fptr);
+#endif /* RUBY_1_9 */
 #ifdef WIN32
 #ifdef __CYGWIN__
   return (FXInputHandle) get_osfhandle(fileno(fpr));
@@ -206,9 +224,15 @@ FXInputHandle FXRbGetReadFileHandle(VALUE obj) {
 
 // Returns an FXInputHandle for this Ruby file object
 FXInputHandle FXRbGetWriteFileHandle(VALUE obj) {
+#ifdef RUBY_1_9
+  rb_io_t *fptr;
+  GetOpenFile(obj, fptr);
+  FILE *fpw=fptr->stdio_file;
+#else
   OpenFile *fptr;
   GetOpenFile(obj, fptr);
   FILE *fpw=GetWriteFile(fptr);
+#endif /* RUBY_1_9 */
 #ifdef WIN32
 #ifdef __CYGWIN__
   return (FXInputHandle) get_osfhandle(fileno(fpw));
@@ -226,7 +250,7 @@ void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
   FXASSERT(!NIL_P(rubyObj));
   FXASSERT(foxObj!=0);
   FXRubyObjDesc* desc;
-  FXTRACE((1,"FXRbRegisterRubyObj(rubyObj=%d,foxObj=0x%08x)\n",rubyObj,foxObj));
+  FXTRACE((1,"FXRbRegisterRubyObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(rubyObj),foxObj));
   if(FXMALLOC(&desc,FXRubyObjDesc,1)){
     desc->obj=rubyObj;
     desc->borrowed=false;
@@ -527,6 +551,9 @@ static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector s
   else if(sender->isMemberOf(FXMETACLASS(FXArrowButton))){
     if(type==SEL_COMMAND) return to_ruby(static_cast<FXuint>(reinterpret_cast<FXuval>(ptr)));
     }
+  else if(sender->isMemberOf(FXMETACLASS(FXPicker))){
+    if(type==SEL_COMMAND || type==SEL_CHANGED) return to_ruby(reinterpret_cast<FXPoint*>(ptr));
+    }
   else if(sender->isMemberOf(FXMETACLASS(FXButton))){
     if(type==SEL_CLICKED ||
        type==SEL_DOUBLECLICKED ||
@@ -560,9 +587,7 @@ static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector s
        type==SEL_CLICKED ||
        type==SEL_DOUBLECLICKED ||
        type==SEL_TRIPLECLICKED) {
-	       fprintf(stderr,"ptr=0x%08x\n",ptr);
 	       VALUE v=to_ruby(static_cast<FXColor>(reinterpret_cast<unsigned long>(ptr)));
-	       fprintf(stderr,"v=%d\n",v);
 	       return v;
     }
     }
@@ -654,7 +679,7 @@ static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector s
             type==SEL_SELECTED ||
             type==SEL_DESELECTED){
       VALUE ary=rb_ary_new();
-      FXGLObject** objlist=reinterpret_cast<FXGLObject**>(ptr);
+      // FXGLObject** objlist=reinterpret_cast<FXGLObject**>(ptr);
       // FIXME: objlist is a NULL-terminated array of pointers to FXGLObject
       return ary;
       }
@@ -736,9 +761,6 @@ static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector s
   else if(sender->isMemberOf(FXMETACLASS(FXOptionMenu))){
     if(type==SEL_COMMAND) return to_ruby(static_cast<FXint>(reinterpret_cast<FXival>(ptr)));
     }
-  else if(sender->isMemberOf(FXMETACLASS(FXPicker))){
-    if(type==SEL_COMMAND || type==SEL_CHANGED) return to_ruby(reinterpret_cast<FXPoint*>(ptr));
-    }
   else if(sender->isMemberOf(FXMETACLASS(FXRadioButton))){
     if(type==SEL_COMMAND) return to_ruby(static_cast<FXuchar>(reinterpret_cast<FXuval>(ptr)));
     }
@@ -901,7 +923,6 @@ static VALUE FXRbConvertMessageData(FXObject* sender,FXObject* recv,FXSelector s
  * the appropriate C++ objects. That's what this function is for.
  */
 void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
-  FXEvent* ev;
   void *ptr;
   static FXint intValue;
   static FXint intRange[2];
@@ -985,7 +1006,7 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
     case SEL_QUERY_HELP:
       return NULL;
     case SEL_VERIFY:
-      return reinterpret_cast<void*>(STR2CSTR(value));
+      return reinterpret_cast<void*>(StringValuePtr(value));
     case SEL_CLICKED:
     case SEL_DOUBLECLICKED:
     case SEL_TRIPLECLICKED:
@@ -1004,10 +1025,7 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
       /* Ignore */
       break;
     }
-  if(type==SEL_DRAGGED){
-    SWIG_Ruby_ConvertPtr(value,&ptr,FXRbTypeQuery("FXEvent *"),1);
-    return ptr;
-    }
+
   if(type==SEL_COMMAND){
     // Handle FXText-specific messages
     if(obj->isMemberOf(FXMETACLASS(FXText))){
@@ -1025,7 +1043,7 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
     if(obj->isMemberOf(FXMETACLASS(FXTextField))){
       switch(id){
         case FXTextField::ID_INSERT_STRING:
-          return reinterpret_cast<void*>(STR2CSTR(value));;
+          return reinterpret_cast<void*>(StringValuePtr(value));;
         default:
           break;
         }
@@ -1094,14 +1112,14 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
                   obj->isMemberOf(FXMETACLASS(FXDirList)) ||
                   obj->isMemberOf(FXMETACLASS(FXDriveBox)) ||
                   obj->isMemberOf(FXMETACLASS(FXFileList))){
-            return reinterpret_cast<void*>(STR2CSTR(value));
+            return reinterpret_cast<void*>(StringValuePtr(value));
             }
           else if(obj->isMemberOf(FXMETACLASS(FXMenuCheck))){
             return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
             }
           else if(obj->isMemberOf(FXMETACLASS(FXMenuRadio))){
             return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
-	    }
+				    }
           else if(obj->isMemberOf(FXMETACLASS(FXMenuCommand))){
             return reinterpret_cast<void*>(static_cast<FXuval>(RTEST(value) ? 1 : 0));
             }
@@ -1122,7 +1140,7 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
           realValue=NUM2DBL(value);
           return reinterpret_cast<void*>(&realValue);
         case FXWindow::ID_SETSTRINGVALUE:
-          stringValue=FXString(STR2CSTR(value));
+          stringValue=FXString(StringValuePtr(value));
           return reinterpret_cast<void*>(&stringValue);
         case FXWindow::ID_SETINTRANGE:
           intRange[0]=NUM2INT(rb_ary_entry(value,0));
@@ -1144,6 +1162,20 @@ void* FXRbGetExpectedData(VALUE recv,FXSelector key,VALUE value){
         }
       }
     }
+
+  if(type==SEL_CHANGED){
+	  if(obj->isMemberOf(FXMETACLASS(FXPicker))){
+			SWIG_Ruby_ConvertPtr(value,&ptr,FXRbTypeQuery("FXPoint *"),1);
+			return ptr;
+	    }
+		return 0;
+    }
+	
+	if(type==SEL_DRAGGED){
+	    SWIG_Ruby_ConvertPtr(value,&ptr,FXRbTypeQuery("FXEvent *"),1);
+	    return ptr;
+	    }
+
   // Pass through as-is
   return reinterpret_cast<void*>(value);
   }
@@ -1159,7 +1191,7 @@ static ID id_assocs;
  * message.
  */
 ID FXRbLookupHandler(FXObject* recv,FXSelector key){
-  FXTRACE((100,"FXRbLookupHandler(recv=0x%08x(%s),FXSEL(%d,%d))\n",recv,recv->getClassName(),FXSELTYPE(key),FXSELID(key)));
+  FXTRACE((100,"FXRbLookupHandler(recv=%p(%s),FXSEL(%d,%d))\n",recv,recv->getClassName(),FXSELTYPE(key),FXSELID(key)));
   ID id=0;
   VALUE rubyObj=to_ruby(recv);
   FXASSERT((recv==0 && rubyObj==Qnil) || (recv!=0 && rubyObj!=Qnil));
@@ -1167,7 +1199,7 @@ ID FXRbLookupHandler(FXObject* recv,FXSelector key){
     VALUE assocs=rb_ivar_get(rubyObj,id_assocs);
     VALUE entry;
     FXSelector keylo,keyhi;
-    for(long i=0;i<RARRAY(assocs)->len;i++){
+    for(long i=0;i<RARRAY_LEN(assocs);i++){
       entry=rb_ary_entry(assocs,i);
       keylo=NUM2UINT(rb_ary_entry(entry,0));
       keyhi=NUM2UINT(rb_ary_entry(entry,1));
@@ -1205,14 +1237,14 @@ static ID id_backtrace;
 static VALUE handle_rescue(VALUE args,VALUE error){
   VALUE info=rb_gv_get("$!");
   VALUE errat=rb_funcall(info,id_backtrace,0);
-  VALUE mesg=RARRAY(errat)->ptr[0];
+  VALUE mesg=RARRAY_PTR(errat)[0];
   fprintf(stderr,"%s: %s (%s)\n",
-    STR2CSTR(mesg),
-    STR2CSTR(rb_obj_as_string(info)),
+    StringValuePtr(mesg),
+    RSTRING_PTR(rb_obj_as_string(info)),
     rb_class2name(CLASS_OF(info)));
-  for(int i=1;i<RARRAY(errat)->len;i++){
-    if(TYPE(RARRAY(errat)->ptr[i])==T_STRING){
-      fprintf(stderr,"\tfrom %s\n",STR2CSTR(RARRAY(errat)->ptr[i]));
+  for(int i=1;i<RARRAY_LEN(errat);i++){
+    if(TYPE(RARRAY_PTR(errat)[i])==T_STRING){
+      fprintf(stderr,"\tfrom %s\n",StringValuePtr(RARRAY_PTR(errat)[i]));
       }
     }
   return Qnil;
@@ -1230,7 +1262,7 @@ long FXRbHandleMessage(FXObject* recv,ID func,FXObject* sender,FXSelector key,vo
   hArgs.nargs=3;
   VALUE retval;
 
-  FXTRACE((100,"FXRbHandleMessage(recv=0x%08x(%s),FXSEL(%s,%d)\n",recv,recv->getClassName(),FXDebugTarget::messageTypeName[FXSELTYPE(key)],FXSELID(key)));
+  FXTRACE((100,"FXRbHandleMessage(recv=%p(%s),FXSEL(%s,%d)\n",recv,recv->getClassName(),FXDebugTarget::messageTypeName[FXSELTYPE(key)],FXSELID(key)));
 
   if(FXRbCatchExceptions){
 #ifdef RB_RESCUE2_BROKEN_PROTOTYPE
@@ -1380,11 +1412,11 @@ FXGLObject** FXRbCallGLObjectArrayMethod(FXGLViewer* recv,ID func,FXint x,FXint
   VALUE result=rb_funcall(obj,func,4,INT2NUM(x),INT2NUM(y),INT2NUM(w),INT2NUM(h));
   if(!NIL_P(result)){
     Check_Type(result,T_ARRAY);
-    if(FXMALLOC(&objects,FXGLObject*,RARRAY(result)->len+1)){
-      for(long i=0; i<RARRAY(result)->len; i++){
+    if(FXMALLOC(&objects,FXGLObject*,RARRAY_LEN(result)+1)){
+      for(long i=0; i<RARRAY_LEN(result); i++){
 	objects[i]=reinterpret_cast<FXGLObject*>(DATA_PTR(rb_ary_entry(result,i)));
         }
-      objects[RARRAY(result)->len]=0;
+      objects[RARRAY_LEN(result)]=0;
       }
     }
   return objects; // caller must free this
@@ -1439,8 +1471,13 @@ FXFileAssoc* FXRbCallFileAssocMethod(const FXFileDict* recv,ID func,const char*
 FXIcon* FXRbCallIconMethod(const FXTableItem* recv,ID func){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
-  VALUE result=rb_funcall(obj,func,0,NULL);
-  return NIL_P(result) ? 0 : reinterpret_cast<FXIcon*>(DATA_PTR(result));
+	if(!NIL_P(obj)){
+	  VALUE result=rb_funcall(obj,func,0,NULL);
+	  return NIL_P(result) ? 0 : reinterpret_cast<FXIcon*>(DATA_PTR(result));
+		}
+	else{
+		return 0;
+		}
   }
 
 //----------------------------------------------------------------------
@@ -1469,7 +1506,7 @@ FXString FXRbCallStringMethod(const FXObject* recv, ID func){
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   VALUE result=rb_funcall(obj,func,0,NULL);
-  return FXString(STR2CSTR(result));
+  return FXString(StringValuePtr(result));
   }
 
 //----------------------------------------------------------------------
@@ -1479,7 +1516,7 @@ const FXchar* FXRbCallCStringMethod(const FXObject* recv, ID func, const FXchar*
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   VALUE result=rb_funcall(obj,func,2,to_ruby(message),to_ruby(hint));
-  return NIL_P(result) ? 0 : STR2CSTR(result);
+  return NIL_P(result) ? 0 : StringValuePtr(result);
   }
 
 // Call functions with const FXchar* return value
@@ -1487,7 +1524,7 @@ const FXchar* FXRbCallCStringMethod(const FXObject* recv, ID func, const FXchar*
   VALUE obj=FXRbGetRubyObj(recv,false);
   FXASSERT(!NIL_P(obj));
   VALUE result=rb_funcall(obj,func,3,to_ruby(context),to_ruby(message),to_ruby(hint));
-  return NIL_P(result) ? 0 : STR2CSTR(result);
+  return NIL_P(result) ? 0 : StringValuePtr(result);
   }
 //----------------------------------------------------------------------
 
@@ -1674,145 +1711,144 @@ FXbool FXRbGLViewer::sortProc(FXfloat*& buffer,FXint& used,FXint& size){
 
 //----------------------------------------------------------------------
 
-// Copied from the Ruby 1.6.6 sources (signal.c)
+// Copied from the Ruby 1.8.6 sources (signal.c)
 static struct signals {
-  const char* signm;
-  FXint signo;
-  } siglist[]={
+    const char *signm;
+    int  signo;
+} siglist [] = {
+    {"EXIT", 0},
 #ifdef SIGHUP
-    { "HUP", SIGHUP },
-#endif
-#ifdef SIGINT
-    { "INT", SIGINT },
+    {"HUP", SIGHUP},
 #endif
+    {"INT", SIGINT},
 #ifdef SIGQUIT
-    { "QUIT", SIGQUIT },
+    {"QUIT", SIGQUIT},
 #endif
 #ifdef SIGILL
-    { "ILL", SIGILL },
+    {"ILL", SIGILL},
 #endif
 #ifdef SIGTRAP
-    { "TRAP", SIGTRAP },
+    {"TRAP", SIGTRAP},
 #endif
 #ifdef SIGIOT
-    { "IOT", SIGIOT },
+    {"IOT", SIGIOT},
 #endif
 #ifdef SIGABRT
-    { "ABRT", SIGABRT },
+    {"ABRT", SIGABRT},
 #endif
 #ifdef SIGEMT
-    { "EMT", SIGEMT },
+    {"EMT", SIGEMT},
 #endif
 #ifdef SIGFPE
-    { "FPE", SIGFPE },
+    {"FPE", SIGFPE},
 #endif
 #ifdef SIGKILL
-    { "KILL", SIGKILL },
+    {"KILL", SIGKILL},
 #endif
 #ifdef SIGBUS
-    { "BUS", SIGBUS },
+    {"BUS", SIGBUS},
 #endif
 #ifdef SIGSEGV
-    { "SEGV", SIGSEGV },
+    {"SEGV", SIGSEGV},
 #endif
 #ifdef SIGSYS
-    { "SYS", SIGSYS },
+    {"SYS", SIGSYS},
 #endif
 #ifdef SIGPIPE
-    { "PIPE", SIGPIPE },
+    {"PIPE", SIGPIPE},
 #endif
 #ifdef SIGALRM
-    { "ALRM", SIGALRM },
+    {"ALRM", SIGALRM},
 #endif
 #ifdef SIGTERM
-    { "TERM", SIGTERM },
+    {"TERM", SIGTERM},
 #endif
 #ifdef SIGURG
-    { "URG", SIGURG },
+    {"URG", SIGURG},
 #endif
 #ifdef SIGSTOP
-    { "STOP", SIGSTOP },
+    {"STOP", SIGSTOP},
 #endif
 #ifdef SIGTSTP
-    { "TSTP", SIGTSTP },
+    {"TSTP", SIGTSTP},
 #endif
 #ifdef SIGCONT
-    { "CONT", SIGCONT },
+    {"CONT", SIGCONT},
 #endif
 #ifdef SIGCHLD
-    { "CHLD", SIGCHLD },
+    {"CHLD", SIGCHLD},
 #endif
 #ifdef SIGCLD
-    { "CLD", SIGCLD },
+    {"CLD", SIGCLD},
 #else
 # ifdef SIGCHLD
-    { "CLD", SIGCHLD, },
+    {"CLD", SIGCHLD},
 # endif
 #endif
 #ifdef SIGTTIN
-    { "TTIN", SIGTTIN },
+    {"TTIN", SIGTTIN},
 #endif
 #ifdef SIGTTOU
-    { "TTOU", SIGTTOU },
+    {"TTOU", SIGTTOU},
 #endif
 #ifdef SIGIO
-    { "IO", SIGIO },
+    {"IO", SIGIO},
 #endif
 #ifdef SIGXCPU
-    { "XCPU", SIGXCPU },
+    {"XCPU", SIGXCPU},
 #endif
 #ifdef SIGXFSZ
-    { "XFSZ", SIGXFSZ },
+    {"XFSZ", SIGXFSZ},
 #endif
 #ifdef SIGVTALRM
-    { "VTALRM", SIGVTALRM },
+    {"VTALRM", SIGVTALRM},
 #endif
 #ifdef SIGPROF
-    { "PROF", SIGPROF },
+    {"PROF", SIGPROF},
 #endif
 #ifdef SIGWINCH
-    { "WINCH", SIGWINCH },
+    {"WINCH", SIGWINCH},
 #endif
 #ifdef SIGUSR1
-    { "USR1", SIGUSR1 },
+    {"USR1", SIGUSR1},
 #endif
 #ifdef SIGUSR2
-    { "USR2", SIGUSR2 },
+    {"USR2", SIGUSR2},
 #endif
 #ifdef SIGLOST
-    { "LOST", SIGLOST },
+    {"LOST", SIGLOST},
 #endif
 #ifdef SIGMSG
-    { "MSG", SIGMSG },
+    {"MSG", SIGMSG},
 #endif
 #ifdef SIGPWR
-    { "PWR", SIGPWR },
+    {"PWR", SIGPWR},
 #endif
 #ifdef SIGPOLL
-    { "POLL", SIGPOLL },
+    {"POLL", SIGPOLL},
 #endif
 #ifdef SIGDANGER
-    { "DANGER", SIGDANGER },
+    {"DANGER", SIGDANGER},
 #endif
 #ifdef SIGMIGRATE
-    { "MIGRATE", SIGMIGRATE },
+    {"MIGRATE", SIGMIGRATE},
 #endif
 #ifdef SIGPRE
-    { "PRE", SIGPRE },
+    {"PRE", SIGPRE},
 #endif
 #ifdef SIGGRANT
-    { "GRANT", SIGGRANT },
+    {"GRANT", SIGGRANT},
 #endif
 #ifdef SIGRETRACT
-    { "RETRACT", SIGRETRACT },
+    {"RETRACT", SIGRETRACT},
 #endif
 #ifdef SIGSOUND
-    { "SOUND", SIGSOUND },
+    {"SOUND", SIGSOUND},
 #endif
 #ifdef SIGINFO
-    { "INFO", SIGINFO },
+    {"INFO", SIGINFO},
 #endif
-    { NULL, 0 },
+    {NULL, 0}
 };
 
 FXint FXRbSignalNameToNumber(const char* s){
@@ -1849,28 +1885,28 @@ static st_table * appSensitiveDCs;
 
 void FXRbRegisterAppSensitiveObject(FXObject* obj){
   FXASSERT(obj!=0);
-  FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(obj=0x%08x(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
+  FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(obj=%p(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
   st_insert(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),(st_data_t)0);
   FXASSERT(st_lookup(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),reinterpret_cast<st_data_t *>(0))!=0);
   }
 
 void FXRbRegisterAppSensitiveObject(FXDC* dc){
   FXASSERT(dc!=0);
-  FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(dc=0x%08x)\n",__FILE__,__LINE__,dc));
+  FXTRACE((100,"%s:%d: FXRbRegisterAppSensitiveObject(dc=%p)\n",__FILE__,__LINE__,dc));
   st_insert(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),(st_data_t)0);
   FXASSERT(st_lookup(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),reinterpret_cast<st_data_t *>(0))!=0);
   }
 
 void FXRbUnregisterAppSensitiveObject(FXObject* obj){
   FXASSERT(obj!=0);
-  FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(obj=0x%08x(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
+  FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(obj=%p(%s))\n",__FILE__,__LINE__,obj,obj->getClassName()));
   st_delete(appSensitiveObjs,reinterpret_cast<st_data_t *>(&obj),reinterpret_cast<st_data_t *>(0));
   FXASSERT(st_lookup(appSensitiveObjs,reinterpret_cast<st_data_t>(obj),reinterpret_cast<st_data_t *>(0))==0);
   }
 
 void FXRbUnregisterAppSensitiveObject(FXDC* dc){
   FXASSERT(dc!=0);
-  FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(dc=0x%08x)\n",__FILE__,__LINE__,dc));
+  FXTRACE((100,"%s:%d: FXRbUnregisterAppSensitiveObject(dc=%p)\n",__FILE__,__LINE__,dc));
   st_delete(appSensitiveDCs,reinterpret_cast<st_data_t *>(&dc),reinterpret_cast<st_data_t *>(0));
   FXASSERT(st_lookup(appSensitiveDCs,reinterpret_cast<st_data_t>(dc),reinterpret_cast<st_data_t *>(0))==0);
   }
@@ -2011,6 +2047,8 @@ extern "C" void Init_fox16(void) {
   REQUIRE("fox16/glgroup");
   REQUIRE("fox16/execute_nonmodal");
   REQUIRE("fox16/version");
+  REQUIRE("fox16/kwargs");
+  REQUIRE("fox16/exceptions_for_fxerror");
   
   id_assocs=rb_intern("@assocs");
   id_backtrace=rb_intern("backtrace");
diff --git a/ext/fox16/extconf.rb.in b/ext/fox16/extconf.rb.in
index f0b9462ad3bbe5dc81fec655a3960865360a164c..631704557d022fe62a6a3e85d677b8f36a640f2f 100755
--- a/ext/fox16/extconf.rb.in
+++ b/ext/fox16/extconf.rb.in
@@ -1,12 +1,13 @@
 #!/bin/env ruby
 
-require 'ftools'
+require 'fileutils'
 require 'mkmf'
 
 def find_installed_fox_version
   stddirs = ["/usr/include/fox-1.6",
              "/usr/local/include/fox-1.6",
-             "/sw/include/fox-1.6"]
+             "/sw/include/fox-1.6",
+	     "/opt/local/include/fox-1.6"]
   usrdirs = []
   ARGV.each do |arg|
     if arg =~ /--with-fox-include/
@@ -19,7 +20,7 @@ def find_installed_fox_version
   
   incdirs.each do |incdir|
     filename = File.join(incdir, "fxver.h")
-    if FileTest.exists?(filename)
+    if FileTest.exist?(filename)
       idircflag = "-I" + incdir
       $CPPFLAGS += " " + idircflag unless $CPPFLAGS.split.include?(idircflag)
       return
@@ -35,7 +36,8 @@ $autodetected_fxscintilla = false
 def find_installed_fxscintilla_version
   stddirs = ["/usr/include/fxscintilla",
              "/usr/local/include/fxscintilla",
-             "/sw/include/fxscintilla"]
+             "/sw/include/fxscintilla",
+	     "/opt/local/include/fxscintilla"]
   usrdirs = []
   ARGV.each do |arg|
     if arg =~ /--with-fxscintilla-include/
@@ -48,7 +50,7 @@ def find_installed_fxscintilla_version
   
   incdirs.each do |incdir|
     filename = File.join(incdir, "FXScintilla.h")
-    if FileTest.exists?(filename)
+    if FileTest.exist?(filename)
       $autodetected_fxscintilla = true
       idircflag = "-I" + incdir
       $CPPFLAGS += " " + idircflag unless $CPPFLAGS.split.include?(idircflag)
@@ -85,11 +87,11 @@ def do_cygwin_setup
   $libs = append_library($libs, "FOX-1.6")
   $CFLAGS = $CFLAGS + " -fpermissive -DWIN32 -Iinclude"
   if is_fxscintilla_build?
-    File.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exists?('scintilla_wrap.cpp.bak')
+    FileUtils.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exist?('scintilla_wrap.cpp.bak')
     $CFLAGS = $CFLAGS + " -DWITH_FXSCINTILLA -DHAVE_FOX_1_6"
     $libs = append_library($libs, "fxscintilla")
   else
-    File.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exists?('scintilla_wrap.cpp')
+    FileUtils.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exist?('scintilla_wrap.cpp')
   end
 end
 
@@ -109,11 +111,11 @@ def do_mswin32_setup
   $CFLAGS = $CFLAGS + " /DWIN32 /DUNICODE /GR /GX /Iinclude"
   $LOCAL_LIBS = $LOCAL_LIBS + "FOX-1.6.lib"
   if is_fxscintilla_build?
-    File.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exists?('scintilla_wrap.cpp.bak')
+    FileUtils.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exist?('scintilla_wrap.cpp.bak')
     $CFLAGS = $CFLAGS + " /DWITH_FXSCINTILLA /DHAVE_FOX_1_6"
     $libs = append_library($libs, "fxscintilla")
   else
-    File.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exists?('scintilla_wrap.cpp')
+    FileUtils.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exist?('scintilla_wrap.cpp')
   end
 end
 
@@ -131,13 +133,40 @@ def do_unix_setup
   find_library("GL", "glXCreateContext", "/usr/X11R6/lib")
   find_library("GLU", "gluNewQuadric", "/usr/X11R6/lib")
   $libs = append_library($libs, "FOX-1.6")
+  $libs = append_library($libs, "Xrandr")
   $CFLAGS = $CFLAGS + " -O0 -Iinclude"
   if is_fxscintilla_build?
-    File.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exists?('scintilla_wrap.cpp.bak')
+    FileUtils.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exist?('scintilla_wrap.cpp.bak')
     $CFLAGS = $CFLAGS + " -DWITH_FXSCINTILLA -DHAVE_FOX_1_6"
     $libs = append_library($libs, "fxscintilla")
   else
-    File.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exists?('scintilla_wrap.cpp')
+    FileUtils.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exist?('scintilla_wrap.cpp')
+  end
+end
+
+def do_darwin_setup
+  $libs = append_library($libs, "stdc++")
+  have_header("sys/time.h")
+  have_header("signal.h")
+  have_library("png", "png_create_read_struct")
+  have_library("z", "deflate")
+  have_library("jpeg", "jpeg_mem_init")
+  have_library("tiff", "TIFFSetErrorHandler")
+  find_library("Xext", "XShmQueryVersion", "/usr/X11R6/lib")
+  find_library("X11", "XFindContext", "/usr/X11R6/lib")
+  find_library("GL", "glXCreateContext", "/usr/X11R6/lib")
+  find_library("GLU", "gluNewQuadric", "/usr/X11R6/lib")
+  $libs = append_library($libs, "FOX-1.6")
+  $libs = append_library($libs, "Xrandr")
+  $libs = append_library($libs, "Xcursor")
+  $libs = append_library($libs, "png")
+  $CFLAGS = $CFLAGS + " -O0 -Iinclude"
+  if is_fxscintilla_build?
+    FileUtils.move('scintilla_wrap.cpp.bak', 'scintilla_wrap.cpp') if FileTest.exist?('scintilla_wrap.cpp.bak')
+    $CFLAGS = $CFLAGS + " -DWITH_FXSCINTILLA -DHAVE_FOX_1_6"
+    $libs = append_library($libs, "fxscintilla")
+  else
+    FileUtils.move('scintilla_wrap.cpp', 'scintilla_wrap.cpp.bak') if FileTest.exist?('scintilla_wrap.cpp')
   end
 end
 
@@ -168,9 +197,14 @@ if RUBY_PLATFORM =~ /cygwin/ || RUBY_PLATFORM =~ /mingw/
   do_cygwin_setup
 elsif RUBY_PLATFORM =~ /mswin32/
   do_mswin32_setup
+elsif RUBY_PLATFORM =~ /darwin/
+  do_darwin_setup
 else
   do_unix_setup
 end
 
+# Check for Ruby 1.9
+$CFLAGS += " -DRUBY_1_9" if RUBY_VERSION =~ /1\.9\./
+
 # Last step: build the makefile
 create_makefile("fox16")
diff --git a/ext/fox16/include/FXRbApp.h b/ext/fox16/include/FXRbApp.h
index 559d81ba8c6f901a0c9a4d2cb8dd910fe32083d9..6ae00c652182af913113d975553780b3075b75d6 100755
--- a/ext/fox16/include/FXRbApp.h
+++ b/ext/fox16/include/FXRbApp.h
@@ -21,7 +21,7 @@
  ***********************************************************************/
 
 /***********************************************************************
- * $Id: FXRbApp.h 2335 2006-01-28 02:33:03Z lyle $
+ * $Id: FXRbApp.h 2927 2008-12-29 19:16:57Z lyle $
  ***********************************************************************/
 
 #ifndef FXRBAPP_H
@@ -41,15 +41,16 @@ inline void cls ## _create(cls *self){ \
 static void cls ## _init(cls* self,VALUE ary,bool connect){ \
   int i; \
   char **argv; \
-  int argc=1+RARRAY(ary)->len; \
+  int argc=1+RARRAY_LEN(ary); \
   if(FXMALLOC(&argv,char*,argc+1)){ \
-    argv[0]="foo"; \
+    argv[0]=const_cast<char *>("foo"); \
     for(i=1;i<argc;i++){ \
-      argv[i]=STR2CSTR(RSTRING(rb_ary_entry(ary,i-1))); \
+      VALUE e=rb_ary_entry(ary,i-1); \
+      argv[i]=StringValuePtr(e); \
       } \
     argv[argc]=0; \
     self->cls::init(argc,argv,connect); \
-    while(RARRAY(ary)->len!=0){ \
+    while(RARRAY_LEN(ary)!=0){ \
       rb_ary_pop(ary); \
       } \
     for(i=1;i<argc;i++){ \
@@ -97,9 +98,10 @@ inline void cls ## _exit(cls *self,FXint code){ \
       rb_ary_push(ary,rb_str_new2(argv[i])); \
       } \
     FXRbCallVoidMethod(this,rb_intern("init"),ary,connect); \
-    argc=RARRAY(ary)->len+1; \
+    argc=RARRAY_LEN(ary)+1; \
     for(i=1; i<argc; i++){ \
-      argv[i]=STR2CSTR(rb_ary_entry(ary,i-1)); \
+      VALUE e=rb_ary_entry(ary,i-1); \
+      argv[i]=StringValuePtr(e); \
       } \
     } \
   void cls::exit(FXint code){ \
diff --git a/ext/fox16/include/FXRbDC.h b/ext/fox16/include/FXRbDC.h
index 8a2ac1aa1b7c763647ad65229d4fd90ff7ca7cea..33cf85aed6e4dd8d88e90dcb611782a7007fb5f0 100755
--- a/ext/fox16/include/FXRbDC.h
+++ b/ext/fox16/include/FXRbDC.h
@@ -21,7 +21,7 @@
  ***********************************************************************/
 
 /***********************************************************************
- * $Id: FXRbDC.h 2372 2006-04-20 00:38:08Z lyle $
+ * $Id: FXRbDC.h 2823 2008-03-28 02:04:22Z lyle $
  ***********************************************************************/
 
 #ifndef FXRBDC_H
diff --git a/ext/fox16/markfuncs.cpp b/ext/fox16/markfuncs.cpp
index 1b62c89280dfc396181078a6641fde9f1639067c..bea3a48784b38086fd867abc76282fcb22a9790e 100755
--- a/ext/fox16/markfuncs.cpp
+++ b/ext/fox16/markfuncs.cpp
@@ -1,5 +1,5 @@
 /***********************************************************************
- * $Id: markfuncs.cpp 2479 2006-09-08 23:20:52Z lyle $
+ * $Id: markfuncs.cpp 2928 2008-12-29 19:16:57Z lyle $
  ***********************************************************************/
 
 #include "FXRbCommon.h"
@@ -49,7 +49,7 @@ void FXRbAccelTable::markfunc(FXAccelTable* accelTable){
 
 // Mark dependencies for the GC
 void FXRbObject::markfunc(FXObject* obj){
-  FXTRACE((100,"%s::markfunc(0x%08x)\n",obj?obj->getClassName():"FXRbObject",obj));
+  FXTRACE((100,"%s::markfunc(%p)\n",obj?obj->getClassName():"FXRbObject",obj));
   }
 
 
@@ -1568,29 +1568,29 @@ void FXRbTGAImage::markfunc(FXTGAImage* self){
 
 
 void FXRbBitmapFrame::markfunc(FXBitmapFrame* self){
-  FXTRACE((100,"start FXRbBitmapFrame::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"start FXRbBitmapFrame::markfunc(%p)\n",self));
   FXRbFrame::markfunc(self);
   if(self!=0){
     FXRbGcMark(self->getBitmap());
     }
-  FXTRACE((100,"end FXRbBitmapFrame::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"end FXRbBitmapFrame::markfunc(%p)\n",self));
   }
 
 
 void FXRbImageFrame::markfunc(FXImageFrame* self){
-  FXTRACE((100,"start FXRbImageFrame::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"start FXRbImageFrame::markfunc(%p)\n",self));
   FXRbFrame::markfunc(self);
   if(self!=0){
     FXRbGcMark(self->getImage());
     }
-  FXTRACE((100,"end FXRbImageFrame::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"end FXRbImageFrame::markfunc(%p)\n",self));
   }
 
 
 void FXRbGradientBar::markfunc(FXGradientBar* self){
-  FXTRACE((100,"start FXRbGradientBar::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"start FXRbGradientBar::markfunc(%p)\n",self));
   FXRbFrame::markfunc(self);
-  FXTRACE((100,"end FXRbGradientBar::markfunc(0x%08x)\n",self));
+  FXTRACE((100,"end FXRbGradientBar::markfunc(%p)\n",self));
   }
 
 #ifdef WITH_FXSCINTILLA
diff --git a/ext/fox16/unregisterOwnedObjects.cpp b/ext/fox16/unregisterOwnedObjects.cpp
index 8c1457985fb082bd235101ca1ab0e629890a3a3f..ca50c0ae1de31ffa4b08edadc99369eb0d1f1129 100644
--- a/ext/fox16/unregisterOwnedObjects.cpp
+++ b/ext/fox16/unregisterOwnedObjects.cpp
@@ -1,5 +1,5 @@
 /***********************************************************************
- * $Id: unregisterOwnedObjects.cpp 2305 2005-12-09 14:38:22Z lyle $
+ * $Id: unregisterOwnedObjects.cpp 2911 2008-12-11 14:09:45Z lyle $
  ***********************************************************************/
 
 /**
@@ -88,7 +88,7 @@ void FXRbScrollWindow::unregisterOwnedObjects(FXScrollWindow *self)
 
 void FXRbTable::unregisterOwnedObjects(FXTable *self)
 {
-    FXint i,r,c;
+    FXint r,c;
     FXRbScrollArea::unregisterOwnedObjects(self);
     FXRbHeader::unregisterOwnedObjects(self->getRowHeader());
     FXRbHeader::unregisterOwnedObjects(self->getColumnHeader());
diff --git a/install.rb b/install.rb
index 274ab6e555adaca8d2050bdbd51b2eba2c6bceb2..424a5f37c6fe3a7cac54b0f85688c1cce7da9cdf 100755
--- a/install.rb
+++ b/install.rb
@@ -1,1095 +1,1582 @@
 #
-# This file is automatically generated. DO NOT MODIFY!
+# setup.rb
 #
-# install.rb
+# Copyright (c) 2000-2005 Minero Aoki
 #
-#   Copyright (c) 2000-2003 Minero Aoki <aamine@loveruby.net>
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU LGPL, Lesser General Public License version 2.1.
 #
-#   This program is free software.
-#   You can distribute/modify this program under the terms of
-#   the GNU Lesser General Public License version 2.
-#
-
-### begin compat.rb
 
-module Enumerable
-  methods = instance_methods()
-
-  unless methods.include?('map')
+unless Enumerable.method_defined?(:map)   # Ruby 1.4.6
+  module Enumerable
     alias map collect
   end
+end
 
-  unless methods.include?('select')
-    alias select find_all
-  end
-
-  unless methods.include?('reject')
-    def reject
-      result = []
-      each do |i|
-        result.push i unless yield(i)
-      end
-      result
-    end
-  end
-
-  unless methods.include?('inject')
-    def inject( result )
-      each do |i|
-        result = yield(result, i)
-      end
-      result
-    end
+unless File.respond_to?(:read)   # Ruby 1.6
+  def File.read(fname)
+    open(fname) {|f|
+      return f.read
+    }
   end
+end
 
-  unless methods.include?('any?')
-    def any?
-      each do |i|
-        return true if yield(i)
-      end
-      false
+unless Errno.const_defined?(:ENOTEMPTY)   # Windows?
+  module Errno
+    class ENOTEMPTY
+      # We do not raise this exception, implementation is not needed.
     end
   end
 end
 
-def File.read_all( fname )
-  File.open(fname, 'rb') {|f| return f.read }
-end
-
-def File.write( fname, str )
-  File.open(fname, 'wb') {|f| f.write str }
+def File.binread(fname)
+  open(fname, 'rb') {|f|
+    return f.read
+  }
 end
 
-### end compat.rb
-### begin config.rb
-
-if i = ARGV.index(/\A--rbconfig=/)
-  file = $'
-  ARGV.delete_at(i)
-  require file
-else
-  require 'rbconfig'
+# for corrupted Windows' stat(2)
+def File.dir?(path)
+  File.directory?((path[-1,1] == '/') ? path : path + '/')
 end
 
 
 class ConfigTable
 
-  c = ::Config::CONFIG
+  include Enumerable
 
-  rubypath = c['bindir'] + '/' + c['ruby_install_name']
+  def initialize(rbconfig)
+    @rbconfig = rbconfig
+    @items = []
+    @table = {}
+    # options
+    @install_prefix = nil
+    @config_opt = nil
+    @verbose = true
+    @no_harm = false
+  end
 
-  major = c['MAJOR'].to_i
-  minor = c['MINOR'].to_i
-  teeny = c['TEENY'].to_i
-  version = "#{major}.#{minor}"
+  attr_accessor :install_prefix
+  attr_accessor :config_opt
 
-  # ruby ver. >= 1.4.4?
-  newpath_p = ((major >= 2) or
-               ((major == 1) and
-                ((minor >= 5) or
-                 ((minor == 4) and (teeny >= 4)))))
-  
-  re = Regexp.new('\A' + Regexp.quote(c['prefix']))
-  subprefix = lambda {|path|
-      re === path and path.sub(re, '$prefix')
-  }
+  attr_writer :verbose
 
-  if c['rubylibdir']
-    # V < 1.6.3
-    stdruby    = subprefix.call(c['rubylibdir'])
-    siteruby   = subprefix.call(c['sitedir'])
-    versite    = subprefix.call(c['sitelibdir'])
-    sodir      = subprefix.call(c['sitearchdir'])
-  elsif newpath_p
-    # 1.4.4 <= V <= 1.6.3
-    stdruby    = "$prefix/lib/ruby/#{version}"
-    siteruby   = subprefix.call(c['sitedir'])
-    versite    = siteruby + '/' + version
-    sodir      = "$site-ruby/#{c['arch']}"
-  else
-    # V < 1.4.4
-    stdruby    = "$prefix/lib/ruby/#{version}"
-    siteruby   = "$prefix/lib/ruby/#{version}/site_ruby"
-    versite    = siteruby
-    sodir      = "$site-ruby/#{c['arch']}"
-  end
-
-  DESCRIPTER = [
-    [ 'prefix',    [ c['prefix'],
-                     'path',
-                     'path prefix of target environment' ] ],
-    [ 'std-ruby',  [ stdruby,
-                     'path',
-                     'the directory for standard ruby libraries' ] ],
-    [ 'site-ruby-common', [ siteruby,
-                     'path',
-                     'the directory for version-independent non-standard ruby libraries' ] ],
-    [ 'site-ruby', [ versite,
-                     'path',
-                     'the directory for non-standard ruby libraries' ] ],
-    [ 'bin-dir',   [ '$prefix/bin',
-                     'path',
-                     'the directory for commands' ] ],
-    [ 'rb-dir',    [ '$site-ruby',
-                     'path',
-                     'the directory for ruby scripts' ] ],
-    [ 'so-dir',    [ sodir,
-                     'path',
-                     'the directory for ruby extentions' ] ],
-    [ 'data-dir',  [ '$prefix/share',
-                     'path',
-                     'the directory for shared data' ] ],
-    [ 'ruby-path', [ rubypath,
-                     'path',
-                     'path to set to #! line' ] ],
-    [ 'ruby-prog', [ rubypath,
-                     'name',
-                     'the ruby program using for installation' ] ],
-    [ 'make-prog', [ 'make',
-                     'name',
-                     'the make program to compile ruby extentions' ] ],
-    [ 'without-ext', [ 'no',
-                       'yes/no',
-                       'does not compile/install ruby extentions' ] ]
-  ]
+  def verbose?
+    @verbose
+  end
 
-  SAVE_FILE = 'config.save'
+  attr_writer :no_harm
 
-  def ConfigTable.each_name( &block )
-    keys().each(&block)
+  def no_harm?
+    @no_harm
   end
 
-  def ConfigTable.keys
-    DESCRIPTER.map {|k,*dummy| k }
+  def [](key)
+    lookup(key).resolve(self)
   end
 
-  def ConfigTable.each_definition( &block )
-    DESCRIPTER.each(&block)
+  def []=(key, val)
+    lookup(key).set val
   end
 
-  def ConfigTable.get_entry( name )
-    name, ent = DESCRIPTER.assoc(name)
-    ent
+  def names
+    @items.map {|i| i.name }
   end
 
-  def ConfigTable.get_entry!( name )
-    get_entry(name) or raise ArgumentError, "no such config: #{name}"
+  def each(&block)
+    @items.each(&block)
   end
 
-  def ConfigTable.add_entry( name, vals )
-    ConfigTable::DESCRIPTER.push [name,vals]
+  def key?(name)
+    @table.key?(name)
   end
 
-  def ConfigTable.remove_entry( name )
-    get_entry name or raise ArgumentError, "no such config: #{name}"
-    DESCRIPTER.delete_if {|n,arr| n == name }
+  def lookup(name)
+    @table[name] or setup_rb_error "no such config item: #{name}"
   end
 
-  def ConfigTable.config_key?( name )
-    get_entry(name) ? true : false
+  def add(item)
+    @items.push item
+    @table[item.name] = item
   end
 
-  def ConfigTable.bool_config?( name )
-    ent = get_entry(name) or return false
-    ent[1] == 'yes/no'
+  def remove(name)
+    item = lookup(name)
+    @items.delete_if {|i| i.name == name }
+    @table.delete_if {|name, i| i.name == name }
+    item
   end
 
-  def ConfigTable.value_config?( name )
-    ent = get_entry(name) or return false
-    ent[1] != 'yes/no'
+  def load_script(path, inst = nil)
+    if File.file?(path)
+      MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path
+    end
   end
 
-  def ConfigTable.path_config?( name )
-    ent = get_entry(name) or return false
-    ent[1] == 'path'
+  def savefile
+    '.config'
   end
 
-
-  class << self
-    alias newobj new
-
-    def new
-      c = newobj()
-      c.__send__ :init
-      c
-    end
-
-    def load
-      c = newobj()
-      raise InstallError, "#{File.basename $0} config first"\
-                                      unless FileTest.file?(SAVE_FILE)
-      File.foreach(SAVE_FILE) do |line|
-        k, v = line.split(/=/, 2)
-        c.instance_eval {
-            @table[k] = v.strip
-        }
+  def load_savefile
+    begin
+      File.foreach(savefile()) do |line|
+        k, v = *line.split(/=/, 2)
+        self[k] = v.strip
       end
-      c
+    rescue Errno::ENOENT
+      setup_rb_error $!.message + "\n#{File.basename($0)} config first"
     end
   end
 
-  def initialize
-    @table = {}
+  def save
+    @items.each {|i| i.value }
+    File.open(savefile(), 'w') {|f|
+      @items.each do |i|
+        f.printf "%s=%s\n", i.name, i.value if i.value? and i.value
+      end
+    }
   end
 
-  def init
-    DESCRIPTER.each do |k, (default, vname, desc, default2)|
-      @table[k] = default
+  def load_standard_entries
+    standard_entries(@rbconfig).each do |ent|
+      add ent
     end
   end
-  private :init
 
-  def save
-    File.open(SAVE_FILE, 'w') {|f|
-        @table.each do |k, v|
-          f.printf "%s=%s\n", k, v if v
-        end
+  def standard_entries(rbconfig)
+    c = rbconfig
+
+    rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT'])
+
+    major = c['MAJOR'].to_i
+    minor = c['MINOR'].to_i
+    teeny = c['TEENY'].to_i
+    version = "#{major}.#{minor}"
+
+    # ruby ver. >= 1.4.4?
+    newpath_p = ((major >= 2) or
+                 ((major == 1) and
+                  ((minor >= 5) or
+                   ((minor == 4) and (teeny >= 4)))))
+
+    if c['rubylibdir']
+      # V > 1.6.3
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = c['rubylibdir']
+      librubyverarch  = c['archdir']
+      siteruby        = c['sitedir']
+      siterubyver     = c['sitelibdir']
+      siterubyverarch = c['sitearchdir']
+    elsif newpath_p
+      # 1.4.4 <= V <= 1.6.3
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
+      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+      siteruby        = c['sitedir']
+      siterubyver     = "$siteruby/#{version}"
+      siterubyverarch = "$siterubyver/#{c['arch']}"
+    else
+      # V < 1.4.4
+      libruby         = "#{c['prefix']}/lib/ruby"
+      librubyver      = "#{c['prefix']}/lib/ruby/#{version}"
+      librubyverarch  = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}"
+      siteruby        = "#{c['prefix']}/lib/ruby/#{version}/site_ruby"
+      siterubyver     = siteruby
+      siterubyverarch = "$siterubyver/#{c['arch']}"
+    end
+    parameterize = lambda {|path|
+      path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')
     }
-  end
 
-  def []=( k, v )
-    ConfigTable.config_key? k or raise InstallError, "unknown config option #{k}"
-    if ConfigTable.path_config? k
-      @table[k] = (v[0,1] != '$') ? File.expand_path(v) : v
+    if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+      makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
     else
-      @table[k] = v
+      makeprog = 'make'
+    end
+
+    [
+      ExecItem.new('installdirs', 'std/site/home',
+                   'std: install under libruby; site: install under site_ruby; home: install under $HOME')\
+          {|val, table|
+            case val
+            when 'std'
+              table['rbdir'] = '$librubyver'
+              table['sodir'] = '$librubyverarch'
+            when 'site'
+              table['rbdir'] = '$siterubyver'
+              table['sodir'] = '$siterubyverarch'
+            when 'home'
+              setup_rb_error '$HOME was not set' unless ENV['HOME']
+              table['prefix'] = ENV['HOME']
+              table['rbdir'] = '$libdir/ruby'
+              table['sodir'] = '$libdir/ruby'
+            end
+          },
+      PathItem.new('prefix', 'path', c['prefix'],
+                   'path prefix of target environment'),
+      PathItem.new('bindir', 'path', parameterize.call(c['bindir']),
+                   'the directory for commands'),
+      PathItem.new('libdir', 'path', parameterize.call(c['libdir']),
+                   'the directory for libraries'),
+      PathItem.new('datadir', 'path', parameterize.call(c['datadir']),
+                   'the directory for shared data'),
+      PathItem.new('mandir', 'path', parameterize.call(c['mandir']),
+                   'the directory for man pages'),
+      PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']),
+                   'the directory for system configuration files'),
+      PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']),
+                   'the directory for local state data'),
+      PathItem.new('libruby', 'path', libruby,
+                   'the directory for ruby libraries'),
+      PathItem.new('librubyver', 'path', librubyver,
+                   'the directory for standard ruby libraries'),
+      PathItem.new('librubyverarch', 'path', librubyverarch,
+                   'the directory for standard ruby extensions'),
+      PathItem.new('siteruby', 'path', siteruby,
+          'the directory for version-independent aux ruby libraries'),
+      PathItem.new('siterubyver', 'path', siterubyver,
+                   'the directory for aux ruby libraries'),
+      PathItem.new('siterubyverarch', 'path', siterubyverarch,
+                   'the directory for aux ruby binaries'),
+      PathItem.new('rbdir', 'path', '$siterubyver',
+                   'the directory for ruby scripts'),
+      PathItem.new('sodir', 'path', '$siterubyverarch',
+                   'the directory for ruby extentions'),
+      PathItem.new('rubypath', 'path', rubypath,
+                   'the path to set to #! line'),
+      ProgramItem.new('rubyprog', 'name', rubypath,
+                      'the ruby program using for installation'),
+      ProgramItem.new('makeprog', 'name', makeprog,
+                      'the make program to compile ruby extentions'),
+      SelectItem.new('shebang', 'all/ruby/never', 'ruby',
+                     'shebang line (#!) editing mode'),
+      BoolItem.new('without-ext', 'yes/no', 'no',
+                   'does not compile/install ruby extentions')
+    ]
+  end
+  private :standard_entries
+
+  def load_multipackage_entries
+    multipackage_entries().each do |ent|
+      add ent
+    end
+  end
+
+  def multipackage_entries
+    [
+      PackageSelectionItem.new('with', 'name,name...', '', 'ALL',
+                               'package names that you want to install'),
+      PackageSelectionItem.new('without', 'name,name...', '', 'NONE',
+                               'package names that you do not want to install')
+    ]
+  end
+  private :multipackage_entries
+
+  ALIASES = {
+    'std-ruby'         => 'librubyver',
+    'stdruby'          => 'librubyver',
+    'rubylibdir'       => 'librubyver',
+    'archdir'          => 'librubyverarch',
+    'site-ruby-common' => 'siteruby',     # For backward compatibility
+    'site-ruby'        => 'siterubyver',  # For backward compatibility
+    'bin-dir'          => 'bindir',
+    'bin-dir'          => 'bindir',
+    'rb-dir'           => 'rbdir',
+    'so-dir'           => 'sodir',
+    'data-dir'         => 'datadir',
+    'ruby-path'        => 'rubypath',
+    'ruby-prog'        => 'rubyprog',
+    'ruby'             => 'rubyprog',
+    'make-prog'        => 'makeprog',
+    'make'             => 'makeprog'
+  }
+
+  def fixup
+    ALIASES.each do |ali, name|
+      @table[ali] = @table[name]
     end
+    @items.freeze
+    @table.freeze
+    @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/
   end
-    
-  def []( key )
-    @table[key] or return nil
-    @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
+
+  def parse_opt(opt)
+    m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}"
+    m.to_a[1,2]
   end
 
-  def set_raw( key, val )
-    @table[key] = val
+  def dllext
+    @rbconfig['DLEXT']
   end
 
-  def get_raw( key )
-    @table[key]
+  def value_config?(name)
+    lookup(name).value?
   end
 
-end
+  class Item
+    def initialize(name, template, default, desc)
+      @name = name.freeze
+      @template = template
+      @value = default
+      @default = default
+      @description = desc
+    end
 
+    attr_reader :name
+    attr_reader :description
 
-module MetaConfigAPI
+    attr_accessor :default
+    alias help_default default
 
-  def eval_file_ifexist( fname )
-    instance_eval File.read_all(fname), fname, 1 if FileTest.file?(fname)
-  end
+    def help_opt
+      "--#{@name}=#{@template}"
+    end
 
-  def config_names
-    ConfigTable.keys
-  end
+    def value?
+      true
+    end
 
-  def config?( name )
-    ConfigTable.config_key? name
-  end
+    def value
+      @value
+    end
+
+    def resolve(table)
+      @value.gsub(%r<\$([^/]+)>) { table[$1] }
+    end
+
+    def set(val)
+      @value = check(val)
+    end
+
+    private
 
-  def bool_config?( name )
-    ConfigTable.bool_config? name
+    def check(val)
+      setup_rb_error "config: --#{name} requires argument" unless val
+      val
+    end
   end
 
-  def value_config?( name )
-    ConfigTable.value_config? name
+  class BoolItem < Item
+    def config_type
+      'bool'
+    end
+
+    def help_opt
+      "--#{@name}"
+    end
+
+    private
+
+    def check(val)
+      return 'yes' unless val
+      case val
+      when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes'
+      when /\An(o)?\z/i, /\Af(alse)\z/i  then 'no'
+      else
+        setup_rb_error "config: --#{@name} accepts only yes/no for argument"
+      end
+    end
   end
 
-  def path_config?( name )
-    ConfigTable.path_config? name
+  class PathItem < Item
+    def config_type
+      'path'
+    end
+
+    private
+
+    def check(path)
+      setup_rb_error "config: --#{@name} requires argument"  unless path
+      path[0,1] == '$' ? path : File.expand_path(path)
+    end
   end
 
-  def add_config( name, argname, default, desc )
-    ConfigTable.add_entry name,[default,argname,desc]
+  class ProgramItem < Item
+    def config_type
+      'program'
+    end
   end
 
-  def add_path_config( name, default, desc )
-    add_config name, 'path', default, desc
+  class SelectItem < Item
+    def initialize(name, selection, default, desc)
+      super
+      @ok = selection.split('/')
+    end
+
+    def config_type
+      'select'
+    end
+
+    private
+
+    def check(val)
+      unless @ok.include?(val.strip)
+        setup_rb_error "config: use --#{@name}=#{@template} (#{val})"
+      end
+      val.strip
+    end
   end
 
-  def add_bool_config( name, default, desc )
-    add_config name, 'yes/no', default ? 'yes' : 'no', desc
+  class ExecItem < Item
+    def initialize(name, selection, desc, &block)
+      super name, selection, nil, desc
+      @ok = selection.split('/')
+      @action = block
+    end
+
+    def config_type
+      'exec'
+    end
+
+    def value?
+      false
+    end
+
+    def resolve(table)
+      setup_rb_error "$#{name()} wrongly used as option value"
+    end
+
+    undef set
+
+    def evaluate(val, table)
+      v = val.strip.downcase
+      unless @ok.include?(v)
+        setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})"
+      end
+      @action.call v, table
+    end
   end
 
-  def set_config_default( name, default )
-    if bool_config? name
-      ConfigTable.get_entry!(name)[0] = default ? 'yes' : 'no'
-    else
-      ConfigTable.get_entry!(name)[0] = default
+  class PackageSelectionItem < Item
+    def initialize(name, template, default, help_default, desc)
+      super name, template, default, desc
+      @help_default = help_default
+    end
+
+    attr_reader :help_default
+
+    def config_type
+      'package'
+    end
+
+    private
+
+    def check(val)
+      unless File.dir?("packages/#{val}")
+        setup_rb_error "config: no such package: #{val}"
+      end
+      val
     end
   end
 
-  def remove_config( name )
-    ent = ConfigTable.get_entry(name)
-    ConfigTable.remove_entry name
-    ent
+  class MetaConfigEnvironment
+    def initialize(config, installer)
+      @config = config
+      @installer = installer
+    end
+
+    def config_names
+      @config.names
+    end
+
+    def config?(name)
+      @config.key?(name)
+    end
+
+    def bool_config?(name)
+      @config.lookup(name).config_type == 'bool'
+    end
+
+    def path_config?(name)
+      @config.lookup(name).config_type == 'path'
+    end
+
+    def value_config?(name)
+      @config.lookup(name).config_type != 'exec'
+    end
+
+    def add_config(item)
+      @config.add item
+    end
+
+    def add_bool_config(name, default, desc)
+      @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc)
+    end
+
+    def add_path_config(name, default, desc)
+      @config.add PathItem.new(name, 'path', default, desc)
+    end
+
+    def set_config_default(name, default)
+      @config.lookup(name).default = default
+    end
+
+    def remove_config(name)
+      @config.remove(name)
+    end
+
+    # For only multipackage
+    def packages
+      raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer
+      @installer.packages
+    end
+
+    # For only multipackage
+    def declare_packages(list)
+      raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer
+      @installer.packages = list
+    end
   end
 
-end
+end   # class ConfigTable
 
-### end config.rb
-### begin fileop.rb
 
+# This module requires: #verbose?, #no_harm?
 module FileOperations
 
-  def mkdir_p( dname, prefix = nil )
-    dname = prefix + dname if prefix
-    $stderr.puts "mkdir -p #{dname}" if verbose?
+  def mkdir_p(dirname, prefix = nil)
+    dirname = prefix + File.expand_path(dirname) if prefix
+    $stderr.puts "mkdir -p #{dirname}" if verbose?
     return if no_harm?
 
-    # does not check '/'... it's too abnormal case
-    dirs = dname.split(%r<(?=/)>)
-    if /\A[a-z]:\z/i === dirs[0]
+    # Does not check '/', it's too abnormal.
+    dirs = File.expand_path(dirname).split(%r<(?=/)>)
+    if /\A[a-z]:\z/i =~ dirs[0]
       disk = dirs.shift
       dirs[0] = disk + dirs[0]
     end
     dirs.each_index do |idx|
       path = dirs[0..idx].join('')
-      Dir.mkdir path unless dir? path
+      Dir.mkdir path unless File.dir?(path)
     end
   end
 
-  def rm_f( fname )
-    $stderr.puts "rm -f #{fname}" if verbose?
+  def rm_f(path)
+    $stderr.puts "rm -f #{path}" if verbose?
     return if no_harm?
-
-    if File.exist? fname or File.symlink? fname
-      File.chmod 0777, fname
-      File.unlink fname
-    end
+    force_remove_file path
   end
 
-  def rm_rf( dn )
-    $stderr.puts "rm -rf #{dn}" if verbose?
+  def rm_rf(path)
+    $stderr.puts "rm -rf #{path}" if verbose?
     return if no_harm?
+    remove_tree path
+  end
+
+  def remove_tree(path)
+    if File.symlink?(path)
+      remove_file path
+    elsif File.dir?(path)
+      remove_tree0 path
+    else
+      force_remove_file path
+    end
+  end
 
-    Dir.chdir dn
-    Dir.foreach('.') do |fn|
-      next if fn == '.'
-      next if fn == '..'
-      if dir? fn
-        verbose_off {
-            rm_rf fn
-        }
+  def remove_tree0(path)
+    Dir.foreach(path) do |ent|
+      next if ent == '.'
+      next if ent == '..'
+      entpath = "#{path}/#{ent}"
+      if File.symlink?(entpath)
+        remove_file entpath
+      elsif File.dir?(entpath)
+        remove_tree0 entpath
       else
-        verbose_off {
-            rm_f fn
-        }
+        force_remove_file entpath
       end
     end
-    Dir.chdir '..'
-    Dir.rmdir dn
+    begin
+      Dir.rmdir path
+    rescue Errno::ENOTEMPTY
+      # directory may not be empty
+    end
   end
 
-  def mv( src, dest )
-    rm_f dest
+  def move_file(src, dest)
+    force_remove_file dest
     begin
-      File.link src, dest
+      File.rename src, dest
     rescue
-      File.write dest, File.read_all(src)
+      File.open(dest, 'wb') {|f|
+        f.write File.binread(src)
+      }
       File.chmod File.stat(src).mode, dest
+      File.unlink src
+    end
+  end
+
+  def force_remove_file(path)
+    begin
+      remove_file path
+    rescue
     end
-    rm_f src
   end
 
-  def install( from, dest, mode, prefix = nil )
+  def remove_file(path)
+    File.chmod 0777, path
+    File.unlink path
+  end
+
+  def install(from, dest, mode, prefix = nil)
     $stderr.puts "install #{from} #{dest}" if verbose?
     return if no_harm?
 
-    realdest = prefix + dest if prefix
-    if dir? realdest
-      realdest += '/' + File.basename(from)
-    end
-    str = File.read_all(from)
-    if diff? str, realdest
+    realdest = prefix ? prefix + File.expand_path(dest) : dest
+    realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+    str = File.binread(from)
+    if diff?(str, realdest)
       verbose_off {
-          rm_f realdest if File.exist? realdest
+        rm_f realdest if File.exist?(realdest)
+      }
+      File.open(realdest, 'wb') {|f|
+        f.write str
       }
-      File.write realdest, str
       File.chmod mode, realdest
 
-#     File.open(objdir + '/InstalledFiles', 'a') {|f| f.puts realdest }
+      File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+        if prefix
+          f.puts realdest.sub(prefix, '')
+        else
+          f.puts realdest
+        end
+      }
     end
   end
 
-  def diff?( orig, targ )
-    return true unless File.exist? targ
-    orig != File.read_all(targ)
+  def diff?(new_content, path)
+    return true unless File.exist?(path)
+    new_content != File.binread(path)
   end
 
-  def command( str )
-    $stderr.puts str if verbose?
-    system str or raise RuntimeError, "'system #{str}' failed"
+  def command(*args)
+    $stderr.puts args.join(' ') if verbose?
+    system(*args) or raise RuntimeError,
+        "system(#{args.map{|a| a.inspect }.join(' ')}) failed"
   end
 
-  def ruby( str )
-    command config('ruby-prog') + ' ' + str
+  def ruby(*args)
+    command config('rubyprog'), *args
+  end
+  
+  def make(task = nil)
+    command(*[config('makeprog'), task].compact)
   end
 
-  def dir?( dname )
-    # for corrupted windows stat()
-    File.directory?((dname[-1,1] == '/') ? dname : dname + '/')
+  def extdir?(dir)
+    File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb")
   end
 
-  def all_files_in( dname )
-    Dir.open(dname) {|d|
-        return d.select {|n| FileTest.file? "#{dname}/#{n}" }
+  def files_of(dir)
+    Dir.open(dir) {|d|
+      return d.select {|ent| File.file?("#{dir}/#{ent}") }
     }
   end
 
-  REJECT_DIRS = %w(
-    CVS SCCS RCS CVS.adm .svn
-  )
+  DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn )
 
-  def all_dirs_in( dname )
-    Dir.open(dname) {|d|
-        return d.select {|n| dir? "#{dname}/#{n}" } - %w(. ..) - REJECT_DIRS
+  def directories_of(dir)
+    Dir.open(dir) {|d|
+      return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT
     }
   end
 
 end
 
-### end fileop.rb
-### begin base.rb
-
-class InstallError < StandardError; end
-
 
-class Installer
-
-  Version   = '3.1.4'
-  Copyright = 'Copyright (c) 2000-2003 Minero Aoki'
-
-
-  @toplevel = nil
-
-  def self.declare_toplevel_installer( inst )
-    raise ArgumentError, 'two toplevel installers declared' if @toplevel
-    @toplevel = inst
-  end
-
-  def self.toplevel_installer
-    @toplevel
-  end
-
-
-  FILETYPES = %w( bin lib ext data )
-
-  include FileOperations
-
-  def initialize( config, opt, srcroot, objroot )
-    @config = config
-    @options = opt
-    @srcdir = File.expand_path(srcroot)
-    @objdir = File.expand_path(objroot)
-    @currdir = '.'
-  end
-
-  def inspect
-    "#<#{self.class} #{__id__}>"
-  end
-
-  #
-  # configs/options
-  #
+# This module requires: #srcdir_root, #objdir_root, #relpath
+module HookScriptAPI
 
-  def get_config( key )
+  def get_config(key)
     @config[key]
   end
 
   alias config get_config
 
-  def set_config( key, val )
+  # obsolete: use metaconfig to change configuration
+  def set_config(key, val)
     @config[key] = val
   end
 
-  def no_harm?
-    @options['no-harm']
-  end
-
-  def verbose?
-    @options['verbose']
-  end
-
-  def verbose_off
-    save, @options['verbose'] = @options['verbose'], false
-    yield
-    @options['verbose'] = save
-  end
-
   #
-  # srcdir/objdir
+  # srcdir/objdir (works only in the package directory)
   #
 
-  attr_reader :srcdir
-  alias srcdir_root srcdir
-  alias package_root srcdir
-
   def curr_srcdir
-    "#{@srcdir}/#{@currdir}"
+    "#{srcdir_root()}/#{relpath()}"
   end
 
-  attr_reader :objdir
-  alias objdir_root objdir
-
   def curr_objdir
-    "#{@objdir}/#{@currdir}"
+    "#{objdir_root()}/#{relpath()}"
   end
 
-  def srcfile( path )
-    curr_srcdir + '/' + path
+  def srcfile(path)
+    "#{curr_srcdir()}/#{path}"
   end
 
-  def srcexist?( path )
-    File.exist? srcfile(path)
+  def srcexist?(path)
+    File.exist?(srcfile(path))
   end
 
-  def srcdirectory?( path )
-    dir? srcfile(path)
+  def srcdirectory?(path)
+    File.dir?(srcfile(path))
   end
   
-  def srcfile?( path )
-    FileTest.file? srcfile(path)
+  def srcfile?(path)
+    File.file?(srcfile(path))
   end
 
-  def srcentries( path = '.' )
-    Dir.open(curr_srcdir + '/' + path) {|d|
-        return d.to_a - %w(. ..) - hookfilenames
+  def srcentries(path = '.')
+    Dir.open("#{curr_srcdir()}/#{path}") {|d|
+      return d.to_a - %w(. ..)
     }
   end
 
-  def srcfiles( path = '.' )
+  def srcfiles(path = '.')
     srcentries(path).select {|fname|
-        FileTest.file? File.join(curr_srcdir, path, fname)
+      File.file?(File.join(curr_srcdir(), path, fname))
     }
   end
 
-  def srcdirectories( path = '.' )
+  def srcdirectories(path = '.')
     srcentries(path).select {|fname|
-        dir? File.join(curr_srcdir, path, fname)
+      File.dir?(File.join(curr_srcdir(), path, fname))
     }
   end
 
-  def dive_into( rel )
-    return unless dir?("#{@srcdir}/#{rel}")
+end
 
-    dir = File.basename(rel)
-    Dir.mkdir dir unless dir?(dir)
-    prevdir = Dir.pwd
-    Dir.chdir dir
-    $stderr.puts '---> ' + rel if verbose?
-    @currdir = rel
-    yield
-    Dir.chdir prevdir
-    $stderr.puts '<--- ' + rel if verbose?
-    @currdir = File.dirname(rel)
-  end
 
-  #
-  # TASK config
-  #
+class ToplevelInstaller
 
-  def exec_config
-    exec_task_traverse 'config'
-  end
+  Version   = '3.4.1'
+  Copyright = 'Copyright (c) 2000-2005 Minero Aoki'
 
-  def config_dir_bin( rel )
-  end
+  TASKS = [
+    [ 'all',      'do config, setup, then install' ],
+    [ 'config',   'saves your configurations' ],
+    [ 'show',     'shows current configuration' ],
+    [ 'setup',    'compiles ruby extentions and others' ],
+    [ 'install',  'installs files' ],
+    [ 'test',     'run all tests in test/' ],
+    [ 'clean',    "does `make clean' for each extention" ],
+    [ 'distclean',"does `make distclean' for each extention" ]
+  ]
 
-  def config_dir_lib( rel )
+  def ToplevelInstaller.invoke
+    config = ConfigTable.new(load_rbconfig())
+    config.load_standard_entries
+    config.load_multipackage_entries if multipackage?
+    config.fixup
+    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
+    klass.new(File.dirname($0), config).invoke
   end
 
-  def config_dir_ext( rel )
-    extconf if extdir? curr_srcdir
+  def ToplevelInstaller.multipackage?
+    File.dir?(File.dirname($0) + '/packages')
   end
 
-  def extconf
-    opt = @options['config-opt'].join(' ')
-    command "#{config('ruby-prog')} #{curr_srcdir}/extconf.rb #{opt}"
+  def ToplevelInstaller.load_rbconfig
+    if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg }
+      ARGV.delete(arg)
+      load File.expand_path(arg.split(/=/, 2)[1])
+      $".push 'rbconfig.rb'
+    else
+      require 'rbconfig'
+    end
+    ::Config::CONFIG
   end
 
-  def config_dir_data( rel )
+  def initialize(ardir_root, config)
+    @ardir = File.expand_path(ardir_root)
+    @config = config
+    # cache
+    @valid_task_re = nil
   end
 
-  #
-  # TASK setup
-  #
-
-  def exec_setup
-    exec_task_traverse 'setup'
+  def config(key)
+    @config[key]
   end
 
-  def setup_dir_bin( relpath )
-    all_files_in(curr_srcdir()).each do |fname|
-      add_rubypath "#{curr_srcdir}/#{fname}"
-    end
+  def inspect
+    "#<#{self.class} #{__id__()}>"
   end
 
-  SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
-
-  def add_rubypath( path )
-    $stderr.puts %Q<set #! line to "\#!#{config('ruby-path')}" for #{path} ...> if verbose?
-    return if no_harm?
-
-    tmpfile = File.basename(path) + '.tmp'
-    begin
-      File.open(path) {|r|
-      File.open(tmpfile, 'w') {|w|
-          first = r.gets
-          return unless SHEBANG_RE === first   # reject '/usr/bin/env ruby'
-
-          w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
-          w.write r.read
-      } }
-      mv tmpfile, File.basename(path)
-    ensure
-      rm_f tmpfile if File.exist? tmpfile
+  def invoke
+    run_metaconfigs
+    case task = parsearg_global()
+    when nil, 'all'
+      parsearg_config
+      init_installers
+      exec_config
+      exec_setup
+      exec_install
+    else
+      case task
+      when 'config', 'test'
+        ;
+      when 'clean', 'distclean'
+        @config.load_savefile if File.exist?(@config.savefile)
+      else
+        @config.load_savefile
+      end
+      __send__ "parsearg_#{task}"
+      init_installers
+      __send__ "exec_#{task}"
     end
   end
-
-  def setup_dir_lib( relpath )
-  end
-
-  def setup_dir_ext( relpath )
-    make if extdir?(curr_srcdir)
+  
+  def run_metaconfigs
+    @config.load_script "#{@ardir}/metaconfig"
   end
 
-  def setup_dir_data( relpath )
+  def init_installers
+    @installer = Installer.new(@config, @ardir, File.expand_path('.'))
   end
 
   #
-  # TASK install
+  # Hook Script API bases
   #
 
-  def exec_install
-    exec_task_traverse 'install'
-  end
-
-  def install_dir_bin( rel )
-    install_files target_filenames(), config('bin-dir') + '/' + rel, 0755
+  def srcdir_root
+    @ardir
   end
 
-  def install_dir_lib( rel )
-    install_files target_filenames(), config('rb-dir') + '/' + rel, 0644
+  def objdir_root
+    '.'
   end
 
-  def install_dir_ext( rel )
-    install_dir_ext_main File.dirname(rel) if extdir?(curr_srcdir)
+  def relpath
+    '.'
   end
 
-  def install_dir_ext_main( rel )
-    install_files allext('.'), config('so-dir') + '/' + rel, 0555
+  #
+  # Option Parsing
+  #
+
+  def parsearg_global
+    while arg = ARGV.shift
+      case arg
+      when /\A\w+\z/
+        setup_rb_error "invalid task: #{arg}" unless valid_task?(arg)
+        return arg
+      when '-q', '--quiet'
+        @config.verbose = false
+      when '--verbose'
+        @config.verbose = true
+      when '--help'
+        print_usage $stdout
+        exit 0
+      when '--version'
+        puts "#{File.basename($0)} version #{Version}"
+        exit 0
+      when '--copyright'
+        puts Copyright
+        exit 0
+      else
+        setup_rb_error "unknown global option '#{arg}'"
+      end
+    end
+    nil
   end
 
-  def install_dir_data( rel )
-    install_files target_filenames(), config('data-dir') + '/' + rel, 0644
+  def valid_task?(t)
+    valid_task_re() =~ t
   end
 
-  def install_files( list, dest, mode )
-    mkdir_p dest, @options['install-prefix']
-    list.each do |fname|
-      install fname, dest, mode, @options['install-prefix']
+  def valid_task_re
+    @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/
+  end
+
+  def parsearg_no_options
+    unless ARGV.empty?
+      task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1)
+      setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}"
     end
   end
 
-  def target_filenames
-    if FileTest.file? "#{curr_srcdir()}/MANIFEST"
-      mapdir(target_filenames_MANIFEST())
-    else
-      mapdir(target_filenames_AUTO())
+  alias parsearg_show       parsearg_no_options
+  alias parsearg_setup      parsearg_no_options
+  alias parsearg_test       parsearg_no_options
+  alias parsearg_clean      parsearg_no_options
+  alias parsearg_distclean  parsearg_no_options
+
+  def parsearg_config
+    evalopt = []
+    set = []
+    @config.config_opt = []
+    while i = ARGV.shift
+      if /\A--?\z/ =~ i
+        @config.config_opt = ARGV.dup
+        break
+      end
+      name, value = *@config.parse_opt(i)
+      if @config.value_config?(name)
+        @config[name] = value
+      else
+        evalopt.push [name, value]
+      end
+      set.push name
+    end
+    evalopt.each do |name, value|
+      @config.lookup(name).evaluate value, @config
+    end
+    # Check if configuration is valid
+    set.each do |n|
+      @config[n] if @config.value_config?(n)
     end
   end
 
-  def mapdir( filelist )
-    filelist.map {|fname|
-        if File.exist? fname   # current objdir == '.'
-          fname
-        else
-          File.join(curr_srcdir(), fname)
-        end
-    }
+  def parsearg_install
+    @config.no_harm = false
+    @config.install_prefix = ''
+    while a = ARGV.shift
+      case a
+      when '--no-harm'
+        @config.no_harm = true
+      when /\A--prefix=/
+        path = a.split(/=/, 2)[1]
+        path = File.expand_path(path) unless path[0,1] == '/'
+        @config.install_prefix = path
+      else
+        setup_rb_error "install: unknown option #{a}"
+      end
+    end
   end
 
-  def target_filenames_MANIFEST
-    File.read_all("#{curr_srcdir()}/MANIFEST").split
+  def print_usage(out)
+    out.puts 'Typical Installation Procedure:'
+    out.puts "  $ ruby #{File.basename $0} config"
+    out.puts "  $ ruby #{File.basename $0} setup"
+    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
+    out.puts
+    out.puts 'Detailed Usage:'
+    out.puts "  ruby #{File.basename $0} <global option>"
+    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+
+    fmt = "  %-24s %s\n"
+    out.puts
+    out.puts 'Global options:'
+    out.printf fmt, '-q,--quiet',   'suppress message outputs'
+    out.printf fmt, '   --verbose', 'output messages verbosely'
+    out.printf fmt, '   --help',    'print this message'
+    out.printf fmt, '   --version', 'print version and quit'
+    out.printf fmt, '   --copyright',  'print copyright and quit'
+    out.puts
+    out.puts 'Tasks:'
+    TASKS.each do |name, desc|
+      out.printf fmt, name, desc
+    end
+
+    fmt = "  %-24s %s [%s]\n"
+    out.puts
+    out.puts 'Options for CONFIG or ALL:'
+    @config.each do |item|
+      out.printf fmt, item.help_opt, item.description, item.help_default
+    end
+    out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's"
+    out.puts
+    out.puts 'Options for INSTALL:'
+    out.printf fmt, '--no-harm', 'only display what to do if given', 'off'
+    out.printf fmt, '--prefix=path',  'install path prefix', ''
+    out.puts
   end
-  
-  # picked up many entries from cvs-1.11.1/src/ignore.c
-  REJECT_PATTERNS = %w( 
-      core RCSLOG tags TAGS .make.state
-      .nse_depinfo #* .#* cvslog.* ,* .del-* *.a *.olb *.o *.obj
-      *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$
-
-      *.org *.in .*
-  ).map {|pattern|
-      Regexp.compile('\A' + pattern.gsub(/[\.\$]/) {|s| '\\' + s }.gsub(/\*/, '.*') + '\z')
-  }
 
-  def target_filenames_AUTO
-    (existfiles() - hookfiles()).reject {|fname|
-        REJECT_PATTERNS.any? {|re| re === fname }
-    }
+  #
+  # Task Handlers
+  #
+
+  def exec_config
+    @installer.exec_config
+    @config.save   # must be final
   end
 
-  def existfiles
-    all_files_in(curr_srcdir()) | all_files_in(curr_objdir())
+  def exec_setup
+    @installer.exec_setup
   end
 
-  def hookfiles
-    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
-        %w( config setup install clean ).map {|t| sprintf(fmt, t) }
-    }.flatten
+  def exec_install
+    @installer.exec_install
   end
 
-  def allext( dir )
-    _allext(dir) or raise InstallError,
-        "no extention exists: Have you done 'ruby #{$0} setup' ?"
+  def exec_test
+    @installer.exec_test
   end
 
-  DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
+  def exec_show
+    @config.each do |i|
+      printf "%-20s %s\n", i.name, i.value if i.value?
+    end
+  end
 
-  def _allext( dir )
-    Dir.open(dir) {|d|
-        return d.select {|fname| DLEXT === fname }
-    }
+  def exec_clean
+    @installer.exec_clean
   end
 
-  #
-  # TASK clean
-  #
+  def exec_distclean
+    @installer.exec_distclean
+  end
 
-  def exec_clean
-    exec_task_traverse 'clean'
-    rm_f 'config.save'
-    rm_f 'InstalledFiles'
+end   # class ToplevelInstaller
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+  include FileOperations
+
+  def initialize(ardir_root, config)
+    super
+    @packages = directories_of("#{@ardir}/packages")
+    raise 'no package exists' if @packages.empty?
+    @root_installer = Installer.new(@config, @ardir, File.expand_path('.'))
   end
 
-  def clean_dir_bin( rel )
+  def run_metaconfigs
+    @config.load_script "#{@ardir}/metaconfig", self
+    @packages.each do |name|
+      @config.load_script "#{@ardir}/packages/#{name}/metaconfig"
+    end
   end
 
-  def clean_dir_lib( rel )
+  attr_reader :packages
+
+  def packages=(list)
+    raise 'package list is empty' if list.empty?
+    list.each do |name|
+      raise "directory packages/#{name} does not exist"\
+              unless File.dir?("#{@ardir}/packages/#{name}")
+    end
+    @packages = list
   end
 
-  def clean_dir_ext( rel )
-    make 'clean' if FileTest.file?('Makefile')
+  def init_installers
+    @installers = {}
+    @packages.each do |pack|
+      @installers[pack] = Installer.new(@config,
+                                       "#{@ardir}/packages/#{pack}",
+                                       "packages/#{pack}")
+    end
+    with    = extract_selection(config('with'))
+    without = extract_selection(config('without'))
+    @selected = @installers.keys.select {|name|
+                  (with.empty? or with.include?(name)) \
+                      and not without.include?(name)
+                }
+  end
+
+  def extract_selection(list)
+    a = list.split(/,/)
+    a.each do |name|
+      setup_rb_error "no such package: #{name}"  unless @installers.key?(name)
+    end
+    a
   end
 
-  def clean_dir_data( rel )
+  def print_usage(f)
+    super
+    f.puts 'Inluded packages:'
+    f.puts '  ' + @packages.sort.join(' ')
+    f.puts
   end
 
   #
-  # TASK distclean
+  # Task Handlers
   #
 
-  def exec_distclean
-    exec_task_traverse 'distclean'
-    rm_f 'config.save'
-    rm_f 'InstalledFiles'
+  def exec_config
+    run_hook 'pre-config'
+    each_selected_installers {|inst| inst.exec_config }
+    run_hook 'post-config'
+    @config.save   # must be final
+  end
+
+  def exec_setup
+    run_hook 'pre-setup'
+    each_selected_installers {|inst| inst.exec_setup }
+    run_hook 'post-setup'
   end
 
-  def distclean_dir_bin( rel )
+  def exec_install
+    run_hook 'pre-install'
+    each_selected_installers {|inst| inst.exec_install }
+    run_hook 'post-install'
   end
 
-  def distclean_dir_lib( rel )
+  def exec_test
+    run_hook 'pre-test'
+    each_selected_installers {|inst| inst.exec_test }
+    run_hook 'post-test'
   end
 
-  def distclean_dir_ext( rel )
-    make 'distclean' if FileTest.file?('Makefile')
+  def exec_clean
+    rm_f @config.savefile
+    run_hook 'pre-clean'
+    each_selected_installers {|inst| inst.exec_clean }
+    run_hook 'post-clean'
+  end
+
+  def exec_distclean
+    rm_f @config.savefile
+    run_hook 'pre-distclean'
+    each_selected_installers {|inst| inst.exec_distclean }
+    run_hook 'post-distclean'
   end
 
   #
   # lib
   #
-  
-  def make( task = '' )
-    command config('make-prog') + ' ' + task
-  end
 
-  def exec_task_traverse( task )
-    run_hook 'pre-' + task
-    FILETYPES.each do |type|
-      if config('without-ext') == 'yes' and type == 'ext'
-        $stderr.puts 'skipping ext/* by user option' if verbose?
-        next
-      end
-      traverse task, type, task + '_dir_' + type
+  def each_selected_installers
+    Dir.mkdir 'packages' unless File.dir?('packages')
+    @selected.each do |pack|
+      $stderr.puts "Processing the package `#{pack}' ..." if verbose?
+      Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+      Dir.chdir "packages/#{pack}"
+      yield @installers[pack]
+      Dir.chdir '../..'
     end
-    run_hook 'post-' + task
   end
 
-  def traverse( task, rel, mid )
-    dive_into(rel) {
-        run_hook 'pre-' + task
-        __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
-        all_dirs_in(curr_srcdir()).each do |d|
-          traverse task, rel + '/' + d, mid
-        end
-        run_hook 'post-' + task
-    }
+  def run_hook(id)
+    @root_installer.run_hook id
   end
 
-  def run_hook( name )
-    try_run_hook curr_srcdir + '/' + name           or
-    try_run_hook curr_srcdir + '/' + name + '.rb'
+  # module FileOperations requires this
+  def verbose?
+    @config.verbose?
   end
 
-  def try_run_hook( fname )
-    return false unless FileTest.file?(fname)
+  # module FileOperations requires this
+  def no_harm?
+    @config.no_harm?
+  end
 
-    env = self.dup
-    begin
-      env.instance_eval File.read_all(fname), fname, 1
-    rescue
-      raise InstallError, "hook #{fname} failed:\n" + $!.message
-    end
-    true
+end   # class ToplevelInstallerMulti
+
+
+class Installer
+
+  FILETYPES = %w( bin lib ext data conf man )
+
+  include FileOperations
+  include HookScriptAPI
+
+  def initialize(config, srcroot, objroot)
+    @config = config
+    @srcdir = File.expand_path(srcroot)
+    @objdir = File.expand_path(objroot)
+    @currdir = '.'
   end
 
-  def extdir?( dir )
-    File.exist? dir + '/MANIFEST'
+  def inspect
+    "#<#{self.class} #{File.basename(@srcdir)}>"
   end
 
-end
+  def noop(rel)
+  end
 
-### end base.rb
-### begin toplevel.rb
+  #
+  # Hook Script API base methods
+  #
 
-class ToplevelInstaller < Installer
+  def srcdir_root
+    @srcdir
+  end
 
-  def self.invoke
-    new(File.dirname($0)).invoke
+  def objdir_root
+    @objdir
   end
 
+  def relpath
+    @currdir
+  end
 
-  TASKS = [
-    [ 'config',   'saves your configurations' ],
-    [ 'show',     'shows current configuration' ],
-    [ 'setup',    'compiles extention or else' ],
-    [ 'install',  'installs files' ],
-    [ 'clean',    "does `make clean' for each extention" ],
-    [ 'distclean',"does `make distclean' for each extention" ]
-  ]
+  #
+  # Config Access
+  #
 
+  # module FileOperations requires this
+  def verbose?
+    @config.verbose?
+  end
 
-  def initialize( root )
-    super nil, {'verbose' => true}, root, '.'
-    Installer.declare_toplevel_installer self
+  # module FileOperations requires this
+  def no_harm?
+    @config.no_harm?
   end
 
+  def verbose_off
+    begin
+      save, @config.verbose = @config.verbose?, false
+      yield
+    ensure
+      @config.verbose = save
+    end
+  end
 
-  def invoke
-    run_metaconfigs
+  #
+  # TASK config
+  #
 
-    case task = parsearg_global()
-    when 'config'
-      @config = ConfigTable.new
-    else
-      @config = ConfigTable.load
-    end
-    parsearg_TASK task
+  def exec_config
+    exec_task_traverse 'config'
+  end
+
+  alias config_dir_bin noop
+  alias config_dir_lib noop
 
-    exectask task
+  def config_dir_ext(rel)
+    extconf if extdir?(curr_srcdir())
   end
 
-  include MetaConfigAPI
+  alias config_dir_data noop
+  alias config_dir_conf noop
+  alias config_dir_man noop
 
-  def run_metaconfigs
-    eval_file_ifexist "#{srcdir_root()}/metaconfig"
+  def extconf
+    ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt
+  end
+
+  #
+  # TASK setup
+  #
+
+  def exec_setup
+    exec_task_traverse 'setup'
+  end
+
+  def setup_dir_bin(rel)
+    files_of(curr_srcdir()).each do |fname|
+      update_shebang_line "#{curr_srcdir()}/#{fname}"
+    end
   end
 
+  alias setup_dir_lib noop
+
+  def setup_dir_ext(rel)
+    make if extdir?(curr_srcdir())
+  end
+
+  alias setup_dir_data noop
+  alias setup_dir_conf noop
+  alias setup_dir_man noop
+
+  def update_shebang_line(path)
+    return if no_harm?
+    return if config('shebang') == 'never'
+    old = Shebang.load(path)
+    if old
+      $stderr.puts "warning: #{path}: Shebang line includes too many args.  It is not portable and your program may not work." if old.args.size > 1
+      new = new_shebang(old)
+      return if new.to_s == old.to_s
+    else
+      return unless config('shebang') == 'all'
+      new = Shebang.new(config('rubypath'))
+    end
+    $stderr.puts "updating shebang: #{File.basename(path)}" if verbose?
+    open_atomic_writer(path) {|output|
+      File.open(path, 'rb') {|f|
+        f.gets if old   # discard
+        output.puts new.to_s
+        output.print f.read
+      }
+    }
+  end
 
-  def exectask( task )
-    if task == 'show'
-      exec_show
+  def new_shebang(old)
+    if /\Aruby/ =~ File.basename(old.cmd)
+      Shebang.new(config('rubypath'), old.args)
+    elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby'
+      Shebang.new(config('rubypath'), old.args[1..-1])
     else
-      try task
+      return old unless config('shebang') == 'all'
+      Shebang.new(config('rubypath'))
     end
   end
 
-  def try( task )
-    $stderr.printf "#{File.basename $0}: entering %s phase...\n", task if verbose?
+  def open_atomic_writer(path, &block)
+    tmpfile = File.basename(path) + '.tmp'
     begin
-      __send__ 'exec_' + task
-    rescue
-      $stderr.printf "%s failed\n", task
-      raise
+      File.open(tmpfile, 'wb', &block)
+      File.rename tmpfile, File.basename(path)
+    ensure
+      File.unlink tmpfile if File.exist?(tmpfile)
+    end
+  end
+
+  class Shebang
+    def Shebang.load(path)
+      line = nil
+      File.open(path) {|f|
+        line = f.gets
+      }
+      return nil unless /\A#!/ =~ line
+      parse(line)
+    end
+
+    def Shebang.parse(line)
+      cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ')
+      new(cmd, args)
+    end
+
+    def initialize(cmd, args = [])
+      @cmd = cmd
+      @args = args
+    end
+
+    attr_reader :cmd
+    attr_reader :args
+
+    def to_s
+      "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}")
     end
-    $stderr.printf "#{File.basename $0}: %s done.\n", task if verbose?
   end
 
   #
-  # processing arguments
+  # TASK install
   #
 
-  def parsearg_global
-    task_re = /\A(?:#{TASKS.map {|i| i[0] }.join '|'})\z/
+  def exec_install
+    rm_f 'InstalledFiles'
+    exec_task_traverse 'install'
+  end
 
-    while arg = ARGV.shift
-      case arg
-      when /\A\w+\z/
-        task_re === arg or raise InstallError, "wrong task: #{arg}"
-        return arg
+  def install_dir_bin(rel)
+    install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755
+  end
 
-      when '-q', '--quiet'
-        @options['verbose'] = false
+  def install_dir_lib(rel)
+    install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644
+  end
 
-      when       '--verbose'
-        @options['verbose'] = true
+  def install_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    install_files rubyextentions('.'),
+                  "#{config('sodir')}/#{File.dirname(rel)}",
+                  0555
+  end
 
-      when '-h', '--help'
-        print_usage $stdout
-        exit 0
+  def install_dir_data(rel)
+    install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644
+  end
 
-      when '-v', '--version'
-        puts "#{File.basename $0} version #{Version}"
-        exit 0
-      
-      when '--copyright'
-        puts Copyright
-        exit 0
+  def install_dir_conf(rel)
+    # FIXME: should not remove current config files
+    # (rename previous file to .old/.org)
+    install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644
+  end
 
-      else
-        raise InstallError, "unknown global option '#{arg}'"
-      end
-    end
+  def install_dir_man(rel)
+    install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644
+  end
 
-    raise InstallError, "No task or global option given.
-Typical installation procedure is:
-    $ ruby #{File.basename $0} config
-    $ ruby #{File.basename $0} setup
-    # ruby #{File.basename $0} install  (may require root privilege)
-"
+  def install_files(list, dest, mode)
+    mkdir_p dest, @config.install_prefix
+    list.each do |fname|
+      install fname, dest, mode, @config.install_prefix
+    end
   end
 
+  def libfiles
+    glob_reject(%w(*.y *.output), targetfiles())
+  end
 
-  def parsearg_TASK( task )
-    mid = "parsearg_#{task}"
-    if respond_to? mid, true
-      __send__ mid
-    else
-      ARGV.empty? or
-          raise InstallError, "#{task}:  unknown options: #{ARGV.join ' '}"
+  def rubyextentions(dir)
+    ents = glob_select("*.#{@config.dllext}", targetfiles())
+    if ents.empty?
+      setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first"
     end
+    ents
   end
 
-  def parsearg_config
-    re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
-    @options['config-opt'] = []
+  def targetfiles
+    mapdir(existfiles() - hookfiles())
+  end
 
-    while i = ARGV.shift
-      if /\A--?\z/ === i
-        @options['config-opt'] = ARGV.dup
-        break
-      end
-      m = re.match(i) or raise InstallError, "config: unknown option #{i}"
-      name, value = m.to_a[1,2]
-      if value
-        if ConfigTable.bool_config?(name)
-          /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i === value or raise InstallError, "config: --#{name} allows only yes/no for argument"
-          value = (/\Ay(es)?|\At(rue)/i === value) ? 'yes' : 'no'
-        end
-      else
-        ConfigTable.bool_config?(name) or raise InstallError, "config: --#{name} requires argument"
-        value = 'yes'
+  def mapdir(ents)
+    ents.map {|ent|
+      if File.exist?(ent)
+      then ent                         # objdir
+      else "#{curr_srcdir()}/#{ent}"   # srcdir
       end
-      @config[name] = value
-    end
+    }
   end
 
-  def parsearg_install
-    @options['no-harm'] = false
-    @options['install-prefix'] = ''
-    while a = ARGV.shift
-      case a
-      when /\A--no-harm\z/
-        @options['no-harm'] = true
-      when /\A--prefix=(.*)\z/
-        path = $1
-        path = File.expand_path(path) unless path[0,1] == '/'
-        @options['install-prefix'] = path
-      else
-        raise InstallError, "install: unknown option #{a}"
-      end
-    end
+  # picked up many entries from cvs-1.11.1/src/ignore.c
+  JUNK_FILES = %w( 
+    core RCSLOG tags TAGS .make.state
+    .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+    *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+    *.org *.in .*
+  )
+
+  def existfiles
+    glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.')))
   end
 
+  def hookfiles
+    %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+      %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+    }.flatten
+  end
 
-  def print_usage( out )
-    out.puts 'Typical Installation Procedure:'
-    out.puts "  $ ruby #{File.basename $0} config"
-    out.puts "  $ ruby #{File.basename $0} setup"
-    out.puts "  # ruby #{File.basename $0} install (may require root privilege)"
-    out.puts
-    out.puts 'Detailed Usage:'
-    out.puts "  ruby #{File.basename $0} <global option>"
-    out.puts "  ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+  def glob_select(pat, ents)
+    re = globs2re([pat])
+    ents.select {|ent| re =~ ent }
+  end
 
-    fmt = "  %-20s %s\n"
-    out.puts
-    out.puts 'Global options:'
-    out.printf fmt, '-q,--quiet',   'suppress message outputs'
-    out.printf fmt, '   --verbose', 'output messages verbosely'
-    out.printf fmt, '-h,--help',    'print this message'
-    out.printf fmt, '-v,--version', 'print version and quit'
-    out.printf fmt, '   --copyright',  'print copyright and quit'
+  def glob_reject(pats, ents)
+    re = globs2re(pats)
+    ents.reject {|ent| re =~ ent }
+  end
 
-    out.puts
-    out.puts 'Tasks:'
-    TASKS.each do |name, desc|
-      out.printf "  %-10s  %s\n", name, desc
-    end
+  GLOB2REGEX = {
+    '.' => '\.',
+    '$' => '\$',
+    '#' => '\#',
+    '*' => '.*'
+  }
 
-    out.puts
-    out.puts 'Options for config:'
-    ConfigTable.each_definition do |name, (default, arg, desc, default2)|
-      out.printf "  %-20s %s [%s]\n",
-                 '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
-                 desc,
-                 default2 || default
+  def globs2re(pats)
+    /\A(?:#{
+      pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|')
+    })\z/
+  end
+
+  #
+  # TASK test
+  #
+
+  TESTDIR = 'test'
+
+  def exec_test
+    unless File.directory?('test')
+      $stderr.puts 'no test in this package' if verbose?
+      return
+    end
+    $stderr.puts 'Running tests...' if verbose?
+    begin
+      require 'test/unit'
+    rescue LoadError
+      setup_rb_error 'test/unit cannot loaded.  You need Ruby 1.8 or later to invoke this task.'
     end
-    out.printf "  %-20s %s [%s]\n",
-        '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
+    runner = Test::Unit::AutoRunner.new(true)
+    runner.to_run << TESTDIR
+    runner.run
+  end
 
-    out.puts
-    out.puts 'Options for install:'
-    out.printf "  %-20s %s [%s]\n",
-        '--no-harm', 'only display what to do if given', 'off'
-    out.printf "  %-20s %s [%s]\n",
-        '--prefix',  'install path prefix', '$prefix'
+  #
+  # TASK clean
+  #
 
-    out.puts
+  def exec_clean
+    exec_task_traverse 'clean'
+    rm_f @config.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  alias clean_dir_bin noop
+  alias clean_dir_lib noop
+  alias clean_dir_data noop
+  alias clean_dir_conf noop
+  alias clean_dir_man noop
+
+  def clean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'clean' if File.file?('Makefile')
   end
 
   #
-  # config
+  # TASK distclean
   #
 
-  def exec_config
-    super
-    @config.save
+  def exec_distclean
+    exec_task_traverse 'distclean'
+    rm_f @config.savefile
+    rm_f 'InstalledFiles'
+  end
+
+  alias distclean_dir_bin noop
+  alias distclean_dir_lib noop
+
+  def distclean_dir_ext(rel)
+    return unless extdir?(curr_srcdir())
+    make 'distclean' if File.file?('Makefile')
   end
 
+  alias distclean_dir_data noop
+  alias distclean_dir_conf noop
+  alias distclean_dir_man noop
+
   #
-  # show
+  # Traversing
   #
 
-  def exec_show
-    ConfigTable.each_name do |k|
-      v = @config.get_raw(k)
-      if not v or v.empty?
-        v = '(not specified)'
+  def exec_task_traverse(task)
+    run_hook "pre-#{task}"
+    FILETYPES.each do |type|
+      if type == 'ext' and config('without-ext') == 'yes'
+        $stderr.puts 'skipping ext/* by user option' if verbose?
+        next
       end
-      printf "%-10s %s\n", k, v
+      traverse task, type, "#{task}_dir_#{type}"
     end
+    run_hook "post-#{task}"
   end
 
-end
+  def traverse(task, rel, mid)
+    dive_into(rel) {
+      run_hook "pre-#{task}"
+      __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+      directories_of(curr_srcdir()).each do |d|
+        traverse task, "#{rel}/#{d}", mid
+      end
+      run_hook "post-#{task}"
+    }
+  end
+
+  def dive_into(rel)
+    return unless File.dir?("#{@srcdir}/#{rel}")
+
+    dir = File.basename(rel)
+    Dir.mkdir dir unless File.dir?(dir)
+    prevdir = Dir.pwd
+    Dir.chdir dir
+    $stderr.puts '---> ' + rel if verbose?
+    @currdir = rel
+    yield
+    Dir.chdir prevdir
+    $stderr.puts '<--- ' + rel if verbose?
+    @currdir = File.dirname(rel)
+  end
 
-### end toplevel.rb
+  def run_hook(id)
+    path = [ "#{curr_srcdir()}/#{id}",
+             "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) }
+    return unless path
+    begin
+      instance_eval File.read(path), path, 1
+    rescue
+      raise if $DEBUG
+      setup_rb_error "hook #{path} failed:\n" + $!.message
+    end
+  end
+
+end   # class Installer
+
+
+class SetupError < StandardError; end
+
+def setup_rb_error(msg)
+  raise SetupError, msg
+end
 
 if $0 == __FILE__
   begin
     ToplevelInstaller.invoke
-  rescue
+  rescue SetupError
     raise if $DEBUG
     $stderr.puts $!.message
     $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
diff --git a/lib/fox16/aliases.rb b/lib/fox16/aliases.rb
index 4b2d42743eacf6977dbdccc4198354925f9ee98c..a4d08c30a190b03f91c7e4a069470e2625f0493e 100755
--- a/lib/fox16/aliases.rb
+++ b/lib/fox16/aliases.rb
@@ -2849,6 +2849,9 @@ module Fox
     def activeChild(*args) # :nodoc:
       getActiveChild(*args)
     end
+    def activeChild=(*args) # :nodoc:
+      setActiveChild(*args)
+    end
     def cascadeX=(*args) # :nodoc:
       setCascadeX(*args)
     end
@@ -3571,6 +3574,7 @@ module Fox
     def position=(*args) # :nodoc:
       setPosition(*args)
     end
+    undef_method(:position) if defined?(:position)
     def position # :nodoc:
       getPosition
     end
@@ -4382,6 +4386,18 @@ module Fox
     def rowHeaderMode=(hint) # :nodoc:
       setRowHeaderMode(hint)
     end
+    def columnHeaderFont # :nodoc:
+      getColumnHeaderFont
+    end
+    def columnHeaderFont=(f) # :nodoc:
+      setColumnHeaderFont(f)
+    end
+    def rowHeaderFont # :nodoc:
+      getRowHeaderFont
+    end
+    def rowHeaderFont=(f) # :nodoc:
+      setRowHeaderFont(f)
+    end
     def columnHeaderHeight # :nodoc:
       getColumnHeaderHeight()
     end
@@ -4764,6 +4780,7 @@ module Fox
     def editable?(*args) # :nodoc:
       isEditable(*args)
     end
+    alias :editable :editable?
     def editable=(*args) # :nodoc:
       setEditable(*args)
     end
diff --git a/lib/fox16/chore.rb b/lib/fox16/chore.rb
index 117d02fdce6400ed6e81bdef77751a7dda651f61..36c744b401bb70f2cf4af2fb354c3a940a926070 100755
--- a/lib/fox16/chore.rb
+++ b/lib/fox16/chore.rb
@@ -1,4 +1,5 @@
 module Fox
+  
   class FXApp
 
     alias addChoreOrig		addChore # :nodoc:
@@ -26,29 +27,41 @@ module Fox
     #
     # The last form takes a block:
     #
-    #     app.addChore() { |sender, sel, data|
+    #     app.addChore() do |sender, sel, data|
     #         ... handle the chore ...
-    #     }
+    #     end
     #
     # All of these return a reference to an opaque FXChore instance that
     # can be passed to #removeChore if it is necessary to remove the chore
     # before it fires.
     #
+    # For the last two forms, you can pass in the optional +:repeat+ parameter to
+    # cause the chore to be re-registered after it fires, e.g.
+    #
+    #     chore = app.addChore(:repeat => true) do |sender, sel, data|
+    #         ... handle the chore ...
+    #         ... re-add the chore ...
+    #     end
+    #
     def addChore(*args, &block)
+      params = {}
+      params = args.pop if args.last.is_a? Hash
       tgt, sel = nil, 0
       if args.length > 0
         if args[0].respond_to? :call
-          tgt = FXPseudoTarget.new
-	  tgt.pconnect(SEL_CHORE, args[0], block)
+          tgt = params[:target] || FXPseudoTarget.new
+          tgt.pconnect(SEL_CHORE, args[0], params)
         else
-	  tgt, sel = args[0], args[1]
+          tgt, sel = args[0], args[1]
         end
       else
-        tgt = FXPseudoTarget.new
-	tgt.pconnect(SEL_CHORE, nil, block)
+        tgt = params[:target] || FXPseudoTarget.new
+        tgt.pconnect(SEL_CHORE, block, params)
       end
       addChoreOrig(tgt, sel)
-      return { :target => tgt, :selector => sel }
+      params[:target] = tgt
+      params[:selector] = sel
+      params
     end
 
     #
@@ -60,8 +73,8 @@ module Fox
       if args.length == 2
         removeChoreOrig(args[0], args[1])
       else
-        hsh = args[0]
-        removeChoreOrig(hsh[:target], hsh[:selector])
+        params = args[0]
+        removeChoreOrig(params[:target], params[:selector])
       end
     end
 
@@ -87,5 +100,6 @@ module Fox
       end
     end
 
-  end
-end
+  end # class FXApp
+  
+end # module Fox
diff --git a/lib/fox16/core.rb b/lib/fox16/core.rb
index 1437b41153bbdcd891b456fb908091eb4b8c0b9a..041a586672858fd3cba4ffd19e498b73ddf969b4 100755
--- a/lib/fox16/core.rb
+++ b/lib/fox16/core.rb
@@ -182,6 +182,25 @@ module Fox
       end
     end
   end
+  
+  class FXHiliteStyle
+    #
+    # Construct a new FXHiliteStyle instance, with fields initialized from
+    # an FXText instance.
+    #
+    def FXHiliteStyle.from_text(textw)
+      hs = new
+      hs.activeBackColor = textw.activeBackColor
+      hs.hiliteBackColor = textw.hiliteBackColor
+      hs.hiliteForeColor = textw.hiliteTextColor
+      hs.normalBackColor = textw.backColor
+      hs.normalForeColor = textw.textColor
+      hs.selectBackColor = textw.selBackColor
+      hs.selectForeColor = textw.selTextColor
+      hs.style = 0
+      hs
+    end
+  end
 
   class FXScrollArea
 	  # Returns a reference to the scroll corner (an FXScrollCorner instance) for this window.
@@ -218,6 +237,8 @@ module Fox
     def to_s
       to_a.to_s
     end
+    
+    def inspect; to_a.inspect; end
   end
   
   class FXVec2f
@@ -226,6 +247,8 @@ module Fox
     
     # Convert to string
     def to_s; to_a.to_s; end
+    
+    def inspect; to_a.inspect; end
   end
   
   class FXVec3d
@@ -234,6 +257,8 @@ module Fox
     
     # Convert to string
     def to_s; to_a.to_s; end
+    
+    def inspect; to_a.inspect; end
   end
   
   class FXVec3f
@@ -242,6 +267,8 @@ module Fox
     
     # Convert to string
     def to_s; to_a.to_s; end
+    
+    def inspect; to_a.inspect; end
   end
   
   class FXVec4d
@@ -250,6 +277,8 @@ module Fox
     
     # Convert to string
     def to_s; to_a.to_s; end
+    
+    def inspect; to_a.inspect; end
   end
   
   class FXVec4f
@@ -258,20 +287,39 @@ module Fox
     
     # Convert to string
     def to_s; to_a.to_s; end
+    
+    def inspect; to_a.inspect; end
   end
 
   class FXWindow
     #
     # Iterate over the child windows for this window.
+    # Note that this only reaches the direct child windows for this window
+    # and no deeper descendants. To traverse the entire widget tree,
+    # use #each_child_recursive.
     #
-    def each_child
+    def each_child # :yields: child
       child = self.first
       while child
         next_child = child.next
         yield child
-	child = next_child
+        child = next_child
+      end
+    end
+    
+    #
+    # Traverse the widget tree starting from this window
+    # using depth-first traversal.
+    # 
+    def each_child_recursive # :yields: child
+      each_child do |child|
+        yield child
+        child.each_child_recursive do |subchild|
+          yield subchild
+        end
       end
     end
+    
 
     # Returns an array containing all child windows of this window
     def children
@@ -447,9 +495,7 @@ module Fox
 
     # Create input control for editing this item
     def getControlFor(table)
-      combo = FXComboBox.new(table, 1, nil, 0, COMBOBOX_STATIC, 0, 0, 0, 0,
-                             table.marginLeft, table.marginRight,
-			     table.marginTop, table.marginBottom)
+      combo = FXComboBox.new(table, 1, :opts => COMBOBOX_STATIC, :padLeft => table.marginLeft, :padRight => table.marginRight, :padTop => table.marginTop, :padBottom => table.marginBottom)
       combo.create
       justify = 0
       justify |= JUSTIFY_LEFT   if (self.justify & FXTableItem::LEFT) != 0
@@ -539,6 +585,13 @@ module Fox
       self.checkState == MAYBE
     end
   end
+  
+  class FXObject
+    require 'enumerator'
+    def self.subclasses
+      ObjectSpace.enum_for(:each_object, class << self; self; end).to_a
+    end
+  end
 
   class FXDC
     #
@@ -607,6 +660,41 @@ module Fox
     def selectItem(row, col, notify=false)
       selectRange(row, row, col, col, notify)
     end
+
+=begin
+
+    # Deselect cell at (_row_, _col_).
+    # If _notify_ is +true+, a +SEL_DESELECTED+ message is sent to the table's message target
+    # after the item is deselected.
+    # Raises IndexError if either _row_ or _col_ is out of bounds.
+    #
+    def deselectItem(row, col, notify=false)
+      raise IndexError, "row index out of bounds" if row < 0 || row >= numRows
+      raise IndexError, "column index out of bounds" if col < 0 || col >= numColumns
+      deselectRange(row, row, col, col, notify)
+    end
+
+    # Deselect range.
+    # If _notify_ is +true+, a +SEL_DESELECTED+ message is sent to the table's message
+    # target for each previously selected cell that becomes deselected as a result of
+    # this operation.
+    # Raises IndexError if _startRow_, _endRow_, _startColumn_ or _endColumn_ is out of bounds.
+    def deselectRange(startRow, endRow, startColumn, endColumn, notify=false)
+      raise IndexError, "starting row index out of bounds"    if startRow < 0 || startRow >= numRows
+      raise IndexError, "ending row index out of bounds"      if endRow < 0 || endRow >= numRows
+      raise IndexError, "starting column index out of bounds" if startColumn < 0 || startColumn >= numColumns
+      raise IndexError, "ending column index out of bounds"   if endColumn < 0 || endColumn >= numColumns
+      changes = false
+      for row in startRow..endRow
+        for col in startColumn..endColumn
+          changes |= deselectItem(row, col, notify)
+        end
+      end
+      changes
+    end
+    
+=end
+
   end
 end
 
diff --git a/lib/fox16/exceptions_for_fxerror.rb b/lib/fox16/exceptions_for_fxerror.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5cc5561bbba58cc9086c01cfbb93b180565397c6
--- /dev/null
+++ b/lib/fox16/exceptions_for_fxerror.rb
@@ -0,0 +1,17 @@
+module Fox
+  FXWindow.subclasses.each do |klass|
+    klass.send(:alias_method, :create_without_parent_created_check, :create)
+    klass.send(:define_method, :create) do
+      unless parent.created?
+        raise RuntimeError, "trying to create window before creating parent window"
+      end
+      if owner && !owner.created?
+        raise RuntimeError, "trying to create window before creating owner window"
+      end
+      if visual.nil?
+        raise RuntimeError, "trying to create window without a visual"
+      end
+      create_without_parent_created_check
+    end
+  end
+end
diff --git a/lib/fox16/input.rb b/lib/fox16/input.rb
index 55fa0596fcd989a1a09f231016c71da4bad52be8..4fbd87bb28980b2cb973039493811cd9a661800a 100755
--- a/lib/fox16/input.rb
+++ b/lib/fox16/input.rb
@@ -1,4 +1,5 @@
 module Fox
+  
   class FXApp
 
     alias addInputOrig addInput # :nodoc:
@@ -31,24 +32,28 @@ module Fox
     #
 
     def addInput(fd, mode, *args, &block)
+      params = {}
+      params = args.pop if args.last.is_a? Hash
       tgt, sel = nil, 0
       if args.length > 0
         if args[0].respond_to? :call
           tgt = FXPseudoTarget.new
-	  tgt.pconnect(SEL_IO_READ, args[0], block)
-	  tgt.pconnect(SEL_IO_WRITE, args[0], block)
-	  tgt.pconnect(SEL_IO_EXCEPT, args[0], block)
+          tgt.pconnect(SEL_IO_READ, args[0], params)
+          tgt.pconnect(SEL_IO_WRITE, args[0], params)
+          tgt.pconnect(SEL_IO_EXCEPT, args[0], params)
         else # it's some other kind of object
           tgt = args[0]
           sel = args[1]
         end
       else
         tgt = FXPseudoTarget.new
-	tgt.pconnect(SEL_IO_READ, nil, block)
-	tgt.pconnect(SEL_IO_WRITE, nil, block)
-	tgt.pconnect(SEL_IO_EXCEPT, nil, block)
+        tgt.pconnect(SEL_IO_READ, block, params)
+        tgt.pconnect(SEL_IO_WRITE, block, params)
+        tgt.pconnect(SEL_IO_EXCEPT, block, params)
       end
       addInputOrig(fd, mode, tgt, sel)
     end
-  end
-end
+    
+  end # class FXApp
+  
+end # module Fox
diff --git a/lib/fox16/iterators.rb b/lib/fox16/iterators.rb
index e521c431b3b515604e8d579bde3fdab33e472cb3..0135075c5ffd5cf907aebe13d9b167b6db8963e5 100755
--- a/lib/fox16/iterators.rb
+++ b/lib/fox16/iterators.rb
@@ -4,6 +4,13 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+    
     #
     # Calls block once for each item in the list, passing the item's text and
     # user data as parameters.
@@ -25,7 +32,7 @@ module Fox
     # reference to that item as a parameter.
     #
     def each # :yields: aFoldingItem
-      current = first
+      current = firstItem
       while current != nil
         next_current = current.next
         yield current
@@ -58,6 +65,13 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each item in the list, passing a reference to that
     # item as a parameter.
@@ -90,6 +104,13 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each item in the list, passing a reference to that
     # item as a parameter.
@@ -106,6 +127,13 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each item in the list, passing the item's text,
     # icon and user data as parameters.
@@ -122,6 +150,13 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each row in the table, passing an array of
     # references (one element per column) as a parameter.
@@ -178,12 +213,19 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each root-level tree item, passing a
     # reference to that item as a parameter.
     #
     def each # :yields: aTreeItem
-      current = first
+      current = firstItem
       while current != nil
         next_current = current.next
         yield current
@@ -197,12 +239,19 @@ module Fox
 
     include Enumerable
 
+    #
+    # Override Enumerable#first with FXWindow#first for backwards compatibility.
+    #
+    def first
+      getFirst
+    end
+
     #
     # Calls block once for each root-level tree item, passing a
     # reference to that item as a parameter.
     #
     def each # :yields: aTreeItem
-      current = first
+      current = firstItem
       while current != nil
         next_current = current.next
         yield current
@@ -234,18 +283,18 @@ module Fox
     def FXFileStream.open(filename, save_or_load, size=8192, container=nil) # :yields: theFileStream
       fstream = FXFileStream.new(container)
       if fstream.open(filename, save_or_load, size)
-	if block_given?
-	  begin
-	    yield fstream
-	  ensure
-	    fstream.close
-	  end
-	else
-	  fstream
-	end
+      	if block_given?
+      	  begin
+      	    yield fstream
+      	  ensure
+      	    fstream.close
+      	  end
+      	else
+      	  fstream
+      	end
       else
         # FXFileStream#open returned false, so report error
-	raise FXStreamError.makeStreamError(fstream.status)
+      	raise FXStreamError.makeStreamError(fstream.status)
       end
     end
   end
@@ -272,18 +321,18 @@ module Fox
     def FXMemoryStream.open(save_or_load, data, cont=nil) # :yields: theMemoryStream
       stream = FXMemoryStream.new(cont)
       if stream.open(save_or_load, data)
-	if block_given?
-	  begin
-	    yield stream
-	  ensure
-	    stream.close
-	  end
-	else
-	  stream
-	end
+      	if block_given?
+      	  begin
+      	    yield stream
+      	  ensure
+      	    stream.close
+      	  end
+      	else
+      	  stream
+      	end
       else
         # FXFileStream#open returned false, so report error
-	raise FXStreamError.makeStreamError(stream.status)
+      	raise FXStreamError.makeStreamError(stream.status)
       end
     end
   end
@@ -318,10 +367,10 @@ module Fox
       beginWaitCursor0
       if block_given?
         begin
-	  yield
-	ensure
-	  endWaitCursor
-	end
+      	  yield
+      	ensure
+      	  endWaitCursor
+      	end
       end
     end
   end
@@ -339,10 +388,10 @@ module Fox
       result = beginPrint0(job)
       if block_given?
         begin
-	  yield self
-	ensure
-	  endPrint
-	end
+      	  yield self
+      	ensure
+      	  endPrint
+      	end
       else
         result
       end
@@ -359,10 +408,10 @@ module Fox
       result = beginPage0(page)
       if block_given?
         begin
-	  yield self
-	ensure
-	  endPage
-	end
+      	  yield self
+      	ensure
+      	  endPage
+      	end
       else
         result
       end
diff --git a/lib/fox16/pseudokeyboard.rb b/lib/fox16/pseudokeyboard.rb
index 4a52e3266d183d65152eecc2a8b9ec5d3647f2f4..40792e8ab58f427018ac358cfb15c1d891c45b76 100755
--- a/lib/fox16/pseudokeyboard.rb
+++ b/lib/fox16/pseudokeyboard.rb
@@ -1,11 +1,17 @@
 module Fox
   #
-  # Based on a suggestion from Hugh Sasse on the fxruby-users mailing list,
-  # an FXPseudoKeyboard object provides a simple means to operate widgets
+  # An FXPseudoKeyboard object provides a simple means to operate widgets
   # programmatically, to aid test driven design. An FXPseudoKeyboard instance
   # can be pointed at an FXObject and will manage the sending of events to
   # it.
   #
+  # For example:
+  #
+  #   textfield = FXTextField.new(...)
+  #   pk = FXPseudoKeyboard.new(textfield)
+  #   pk.doKeyPress     # sends a SEL_KEYPRESS message to the textfield
+  #   pk.doKeyRelease   # sends a SEL_KEYRELEASE message to the textfield
+  #
   class FXPseudoKeyboard
 
     attr_accessor :target
@@ -17,16 +23,16 @@ module Fox
     def doKeyPress
       unless @target.nil?
         evt = FXEvent.new
-	evt.type = Fox::SEL_KEYPRESS
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_KEYPRESS), evt)
+        evt.type = Fox::SEL_KEYPRESS
+        @target.handle(self, Fox.FXSEL(Fox::SEL_KEYPRESS, 0), evt)
       end
     end
 
     def doKeyRelease
       unless @target.nil?
         evt = FXEvent.new
-	evt.type = Fox::SEL_KEYRELEASE
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_KEYRELEASE), evt)
+        evt.type = Fox::SEL_KEYRELEASE
+        @target.handle(self, Fox.FXSEL(Fox::SEL_KEYRELEASE, 0), evt)
       end
     end
   end
diff --git a/lib/fox16/pseudomouse.rb b/lib/fox16/pseudomouse.rb
index 545dcc07910095107b8a05898a4ae99593d48b0e..471524c333dc74b5b48cc4836aa49afed1e3d042 100755
--- a/lib/fox16/pseudomouse.rb
+++ b/lib/fox16/pseudomouse.rb
@@ -1,11 +1,16 @@
 module Fox
   #
-  # Based on a suggestion from Hugh Sasse on the fxruby-users mailing list,
-  # an FXPseudoMouse object provides a simple means to operate widgets
+  # An FXPseudoMouse object provides a simple means to operate widgets
   # programmatically, to aid test driven design. An FXPseudoMouse instance
   # can be pointed at an FXObject and will manage the sending of events to
   # it.
   #
+  # For example:
+  #
+  #   canvas = FXCanvas.new(...)
+  #   pm = FXPseudoMouse.new(canvas)
+  #   pm.doLeftButtonPress # sends a SEL_LEFTBUTTONPRESS message to the canvas
+  #
   class FXPseudoMouse < FXObject
 
     attr_accessor :target
@@ -18,7 +23,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_MOTION
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_MOTION), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_MOTION, 0), evt)
       end
     end
 
@@ -26,7 +31,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_MOUSEWHEEL
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_MOUSEWHEEL), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_MOUSEWHEEL, 0), evt)
       end
     end
 
@@ -34,7 +39,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_LEFTBUTTONPRESS
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_LEFTBUTTONPRESS), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_LEFTBUTTONPRESS, 0), evt)
       end
     end
 
@@ -42,7 +47,7 @@ module Fox
       unless @target.nil?
        evt = FXEvent.new
         evt.type = Fox::SEL_LEFTBUTTONRELEASE
-       @target.handle(self, Fox.MKUINT(0, Fox::SEL_LEFTBUTTONRELEASE), evt)
+       @target.handle(self, Fox.FXSEL(Fox::SEL_LEFTBUTTONRELEASE, 0), evt)
       end
     end
 
@@ -50,7 +55,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_MIDDLEBUTTONPRESS
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_MIDDLEBUTTONPRESS), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_MIDDLEBUTTONPRESS, 0), evt)
       end
     end
 
@@ -58,7 +63,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_MIDDLEBUTTONRELEASE
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_MIDDLEBUTTONRELEASE), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_MIDDLEBUTTONRELEASE, 0), evt)
       end
     end
 
@@ -66,7 +71,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_RIGHTBUTTONPRESS
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_RIGHTBUTTONPRESS), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_RIGHTBUTTONPRESS, 0), evt)
       end
     end
 
@@ -74,7 +79,7 @@ module Fox
       unless @target.nil?
         evt = FXEvent.new
         evt.type = Fox::SEL_RIGHTBUTTONRELEASE
-        @target.handle(self, Fox.MKUINT(0, Fox::SEL_RIGHTBUTTONRELEASE), evt)
+        @target.handle(self, Fox.FXSEL(Fox::SEL_RIGHTBUTTONRELEASE, 0), evt)
       end
     end
   end
diff --git a/lib/fox16/responder2.rb b/lib/fox16/responder2.rb
index b10c454f9a492b26925e750565d5446b07ffd14a..a73a2f750683fe50d443a32ed96304a152348c4d 100755
--- a/lib/fox16/responder2.rb
+++ b/lib/fox16/responder2.rb
@@ -21,30 +21,25 @@ module Fox
     #
     def initialize
       super
-      @blocks = {}
+      @context = {}
     end
 
     #
     # Store an association between a message of type
-    # _messageType_ with a callable object or a block.
+    # _message_type_ with a callable object.
     #
-    def pconnect(messageType, callableObject, block)
-      if callableObject.nil?
-	@blocks[messageType] = block
-      else
-	@blocks[messageType] = callableObject
-      end
-      FXMAPTYPE(messageType, :onHandleMsg)
-      
-      case messageType
-        when SEL_TIMEOUT
-	  @@targets_of_pending_timers[self] = self
-        when SEL_CHORE
-	  @@targets_of_pending_chores[self] = self
-        when SEL_SIGNAL
-	  @@targets_of_pending_signals[self] = self
-        when SEL_IO_READ, SEL_IO_WRITE, SEL_IO_EXCEPT
-	  @@targets_of_pending_inputs[self] = self
+    def pconnect(message_type, callable_object, params={})
+      @context[message_type] = { :callable => callable_object, :params => params }
+      FXMAPTYPE(message_type, :onHandleMsg)
+      case message_type
+      when SEL_TIMEOUT
+        @@targets_of_pending_timers[self] = self
+      when SEL_CHORE
+        @@targets_of_pending_chores[self] = self
+      when SEL_SIGNAL
+        @@targets_of_pending_signals[self] = self
+      when SEL_IO_READ, SEL_IO_WRITE, SEL_IO_EXCEPT
+        @@targets_of_pending_inputs[self] = self
       end
     end
 
@@ -53,18 +48,31 @@ module Fox
     # message data _ptr_.
     #
     def onHandleMsg(sender, sel, ptr)
-      messageType = Fox.FXSELTYPE(sel)
-      result = @blocks[messageType].call(sender, sel, ptr)
-      case messageType
-        when SEL_TIMEOUT
-	  @@targets_of_pending_timers.delete(self)
-        when SEL_CHORE
-	  @@targets_of_pending_chores.delete(self)
+      message_type = Fox.FXSELTYPE(sel)
+      ctx = @context[message_type]
+      callable_object = ctx[:callable]
+      params = ctx[:params]
+      result = callable_object.call(sender, sel, ptr)
+      case message_type
+      when SEL_TIMEOUT
+        if params[:repeat]
+          FXApp.instance.addTimeout(params[:delay], callable_object, params)
+        else
+          @@targets_of_pending_timers.delete(self)
+        end
+      when SEL_CHORE
+        if params[:repeat]
+          FXApp.instance.addChore(callable_object, params)
+        else
+          @@targets_of_pending_chores.delete(self)
+        end
       end
       result
     end
-  end
-end
+    
+  end # class FXPseudoTarget
+  
+end # module Fox
 
 #
 # The Responder2 module provides the #connect method,
@@ -95,13 +103,14 @@ module Responder2
   # will be "called" with three arguments (the sender, selector and
   # message data).
   #
-  def connect(messageType, callableObject=nil, &block)
+  def connect(message_type, callable_object=nil, &block)
     unless instance_variables.include?('@pseudoTarget')
       @pseudoTarget = Fox::FXPseudoTarget.new
       self.target = @pseudoTarget
     end
-    @pseudoTarget.pconnect(messageType, callableObject, block)
+    @pseudoTarget.pconnect(message_type, callable_object ? callable_object : block)
   end
+  
 end
 
 module Fox
diff --git a/lib/fox16/signal.rb b/lib/fox16/signal.rb
index 8c9a24377d861958e88901bdecc90cf964616920..513f7062bdfa4fcc1c006712ba189f413e616034 100755
--- a/lib/fox16/signal.rb
+++ b/lib/fox16/signal.rb
@@ -1,4 +1,5 @@
 module Fox
+  
   class FXApp
 
     alias addSignalOrig addSignal # :nodoc:
@@ -18,7 +19,7 @@ module Fox
     # the message to be sent when this signal is raised.
     # If _sendImmediately_ is +true+, the message will be sent to the target right away;
     # this should be used with extreme care as the application is interrupted
-    # at an unknown point it its execution.
+    # at an unknown point in its execution.
     # The _flags_ are to be set as per POSIX definitions.
     #
     # A second form of #addSignal takes a Method instance as its second argument:
@@ -38,16 +39,18 @@ module Fox
     #
 
     def addSignal(sig, *args, &block)
+      params = {}
+      params = args.pop if args.last.is_a? Hash
       tgt, sel, immediate, flags = nil, 0, false, 0
       if args.length > 0
         if args[0].respond_to? :call
           tgt = FXPseudoTarget.new
-          tgt.pconnect(SEL_SIGNAL, args[0], block)
+          tgt.pconnect(SEL_SIGNAL, args[0], params)
           immediate = (args.length > 1) ? args[1] : false
           flags = (args.length > 2) ? args[2] : 0
         elsif (args[0].kind_of? TrueClass) || (args[0].kind_of? FalseClass)
           tgt = FXPseudoTarget.new
-          tgt.pconnect(SEL_SIGNAL, nil, block)
+          tgt.pconnect(SEL_SIGNAL, block, params)
           immediate = args[0]
           flags = (args.length > 1) ? args[1] : 0
         else # it's some other kind of object
@@ -58,9 +61,11 @@ module Fox
         end
       else
         tgt = FXPseudoTarget.new
-        tgt.pconnect(SEL_SIGNAL, nil, block)
+        tgt.pconnect(SEL_SIGNAL, block, params)
       end
       addSignalOrig(sig, tgt, sel, immediate, flags)
     end
-  end
-end
+    
+  end # class FXApp
+  
+end # module Fox
diff --git a/lib/fox16/timeout.rb b/lib/fox16/timeout.rb
index ddead0978ed861131ba07fc5a4de0bd24ff0e007..6aae9b66a6b7dd93851677e5265724b08d39f9cc 100755
--- a/lib/fox16/timeout.rb
+++ b/lib/fox16/timeout.rb
@@ -1,4 +1,5 @@
 module Fox
+  
   class FXApp
 
     alias addTimeoutOrig	addTimeout # :nodoc:
@@ -7,8 +8,8 @@ module Fox
     alias remainingTimeoutOrig	remainingTimeout # :nodoc:
 
     #
-    # Add a timeout message to be sent to target object in _ms_ milliseconds;
-    # the timer fires only once after the interval expires.  The last argument
+    # Add a timeout message to be sent to target object in _ms_ milliseconds.
+    # By default, the timer fires only once after the interval expires.  The last argument
     # is optional user data which will be passed along as the _ptr_ argument of
     # the message handler. If a timer with the same target and message already exists,
     # it will be rescheduled.
@@ -34,30 +35,43 @@ module Fox
     #
     # The last form of #addTimeout takes a block:
     #
-    #     timeout = app.addTimeout(delay) { |sender, sel, data|
+    #     timeout = app.addTimeout(delay) do |sender, sel, data|
     #         ... handle the timeout ...
-    #     }
+    #     end
     #
     # All of these return a reference to an opaque object (actually, a hash) that
     # can be passed to #removeTimeout if it is necessary to remove the timeout
     # before it fires.
     #
+    # For the last two forms, you can pass in the optional +:repeat+ parameter to
+    # cause the timeout to be re-registered after it fires, e.g.
+    #
+    #     timeout = app.addTimeout(delay, :repeat => true) do |sender, sel, data|
+    #         ... handle the timeout ...
+    #         ... re-add the timeout with the same delay ...
+    #     end
+    #
     def addTimeout(ms, *args, &block)
+      params = {}
+      params = args.pop if args.last.is_a? Hash
+      params[:delay] = ms
       tgt, sel = nil, 0
       if args.length > 0
         if args[0].respond_to? :call
-          tgt = FXPseudoTarget.new
-	  tgt.pconnect(SEL_TIMEOUT, args[0], nil)
+          tgt = params[:target] || FXPseudoTarget.new
+          tgt.pconnect(SEL_TIMEOUT, args[0], params)
         else # it's some other kind of object
           tgt = args[0]
           sel = args[1]
         end
       else
-        tgt = FXPseudoTarget.new
-	tgt.pconnect(SEL_TIMEOUT, nil, block)
+        tgt = params[:target] || FXPseudoTarget.new
+        tgt.pconnect(SEL_TIMEOUT, block, params)
       end
       addTimeoutOrig(tgt, sel, ms)
-      return { :target => tgt, :selector => sel }
+      params[:target] = tgt
+      params[:selector] = sel
+      params
     end
 
     #
@@ -69,8 +83,8 @@ module Fox
       if args.length == 2
         removeTimeoutOrig(args[0], args[1])
       else
-        hsh = args[0]
-        removeTimeoutOrig(hsh[:target], hsh[:selector])
+        params = args[0]
+        removeTimeoutOrig(params[:target], params[:selector])
       end
     end
 
@@ -116,5 +130,7 @@ module Fox
         remainingTimeoutOrig(hsh[:target], hsh[:selector])
       end
     end
-  end
-end
+    
+  end # class FXApp
+  
+end # module Fox
diff --git a/pre-config.rb.in b/pre-config.rb.in
index 0040fbefc1ec9e3dfc3a5f333af4caedb5cf48d9..dd9c276405355a53e7d2d49faaf7b317b0d75734 100755
--- a/pre-config.rb.in
+++ b/pre-config.rb.in
@@ -3,7 +3,8 @@ def search_directories
   dirs = [
           "/usr/include/fox-1.6",
           "/usr/local/include/fox-1.6",
-          "/sw/include/fox-1.6"
+          "/sw/include/fox-1.6",
+	  "/opt/local/include/fox-1.6"
          ]
   ARGV.each do |arg|
     if arg =~ /--with-fox-include/
@@ -19,7 +20,7 @@ end
 def fox_include_files_found?
   search_directories.each do |path|
     filename = File.join(path, "fxver.h")
-    return true if FileTest.exists?(filename)
+    return true if FileTest.exist?(filename)
   end
   false
 end
@@ -43,7 +44,7 @@ end
 def installed_fox_version
   search_directories.each do |path|
     filename = File.join(path, "fxver.h")
-    if FileTest.exists?(filename)
+    if FileTest.exist?(filename)
       foxMajor, foxMinor, foxLevel = read_fox_version(filename)
       return [foxMajor, foxMinor, foxLevel].join('.')
     end
diff --git a/rdoc-sources/FXButton.rb b/rdoc-sources/FXButton.rb
index 85b333bd92395814f8cdfdacd66dab8d91733bcb..71da51f101234e34996f321f51c7d2bd8ccb1098 100755
--- a/rdoc-sources/FXButton.rb
+++ b/rdoc-sources/FXButton.rb
@@ -14,7 +14,7 @@ module Fox
   # The option <tt>BUTTON_AUTOGRAY</tt> (<tt>BUTTON_AUTOHIDE</tt>) causes the button to be grayed
   # out (hidden) if its handler does not respond to the <tt>SEL_UPDATE</tt> message.
   # This is useful when messages are delegated, for example when using a
-  # multiple document interface, where the ultimaye destination of a message
+  # multiple document interface, where the ultimate destination of a message
   # can be changed.
   #
   # === Events
diff --git a/rdoc-sources/FXComboBox.rb b/rdoc-sources/FXComboBox.rb
index 1b5d3e3f3b976c13f9bfd8939fc068540ae562c0..42daa6af0745c5ef4889e23fdaf0ced64d79cd8b 100755
--- a/rdoc-sources/FXComboBox.rb
+++ b/rdoc-sources/FXComboBox.rb
@@ -106,6 +106,9 @@ module Fox
     def initialize(p, cols, target=nil, selector=0, opts=COMBOBOX_NORMAL, x=0, y=0, width=0, height=0, padLeft=DEFAULT_PAD, padRight=DEFAULT_PAD, padTop=DEFAULT_PAD, padBottom=DEFAULT_PAD) # :yields: theComboBox
     end
 
+    # Return the combo box text
+    def to_s; end
+    
     # Return +true+ if combobox is editable
     def editable?() ; end
 
diff --git a/rdoc-sources/FXCursor.rb b/rdoc-sources/FXCursor.rb
index 2afb7b8d4a65be45ff5dbdfbe62d4837e26e10fd..591d405c2e5dfbb00a6ef7ff17f0b472c7955409 100755
--- a/rdoc-sources/FXCursor.rb
+++ b/rdoc-sources/FXCursor.rb
@@ -48,7 +48,7 @@ module Fox
     #
     # Make cursor from FXColor pixels; cursor size should be 32x32 for portability!
     #
-    def initialize(a, src, msk, width=32, height=32, hotX=-1, hotY=-1) # :yields: theCursor
+    def initialize(a, pixels, width=32, height=32, hotX=-1, hotY=-1) # :yields: theCursor
     end
 
     #
diff --git a/rdoc-sources/FXGroupBox.rb b/rdoc-sources/FXGroupBox.rb
index 76b89dcf770962b85bad27d0d8c6e5bc3c7f113c..7941789dc82cff2cf134c71b2a7a51631500bea6 100755
--- a/rdoc-sources/FXGroupBox.rb
+++ b/rdoc-sources/FXGroupBox.rb
@@ -28,6 +28,9 @@ module Fox
     # Construct group box layout manager
     def initialize(parent, text, opts=GROUPBOX_NORMAL, x=0, y=0, width=0, height=0, padLeft=DEFAULT_SPACING, padRight=DEFAULT_SPACING, padTop=DEFAULT_SPACING, padBottom=DEFAULT_SPACING, hSpacing=DEFAULT_SPACING, vSpacing=DEFAULT_SPACING) # :yields: theGroupBox
     end
+    
+    # Return the group box's title text
+    def to_s; text; end
   end
 end
 
diff --git a/rdoc-sources/FXHeader.rb b/rdoc-sources/FXHeader.rb
index 04ccfaec7022220042ec2461dc10127bbd8c6f7f..052a6b04d23dc3fd55fc7588a76c317125ec22b4 100755
--- a/rdoc-sources/FXHeader.rb
+++ b/rdoc-sources/FXHeader.rb
@@ -57,6 +57,9 @@ module Fox
     def initialize(text, ic=nil, s=0, ptr=nil) # :yields: theHeaderItem
     end
     
+    # Return the header item's text label
+    def to_s; text; end
+    
     # Return the item's content width in the header.
     def getWidth(header); end
     
diff --git a/rdoc-sources/FXIconDict.rb b/rdoc-sources/FXIconDict.rb
index c758a51efa11462c3d746d42c111f36689e55a88..3d6f3e5bd7b3bb9e164b3a1586537e2642296286 100644
--- a/rdoc-sources/FXIconDict.rb
+++ b/rdoc-sources/FXIconDict.rb
@@ -21,7 +21,7 @@ module Fox
     # Construct icon dictionary, and set initial search path; also
     # creates a default icon source object.
     #
-    def initialize(app, path=defaultIconPath);
+    def initialize(app, path=FXIconDict.defaultIconPath);
 
     # Change icon source to _src_ (an FXIconSource instance).
     def iconSource=(src); end
diff --git a/rdoc-sources/FXIconList.rb b/rdoc-sources/FXIconList.rb
index 1f9051c8fe977c62df6da83c5c5c3f32b5068150..50f6d5f1020549b914c6507b7114771cd28927e9 100755
--- a/rdoc-sources/FXIconList.rb
+++ b/rdoc-sources/FXIconList.rb
@@ -28,6 +28,9 @@ module Fox
     # Constructor
     def initialize(text, bigIcon=nil, miniIcon=nil, data=nil) # :yields: theIconItem
     end
+    
+    # Return the icon item's text
+    def to_s; text; end
 
     # Set the focused state for this item (where _focus_ is either +true+ or +false+)
     def setFocus(focus); end
diff --git a/rdoc-sources/FXImage.rb b/rdoc-sources/FXImage.rb
index 0c4d6f069df4333b6f75af4092577c511c3eacd2..771fc3f1c69bf7e7091aa4f77dbc6548fb572f6c 100755
--- a/rdoc-sources/FXImage.rb
+++ b/rdoc-sources/FXImage.rb
@@ -113,7 +113,8 @@ module Fox
     def release(); end
 
     #
-    # Rescale pixels image to the specified width and height. Note that this
+    # Rescale pixels image to the specified width and height and then
+    # re-render the server-side image from the client-side pixel buffer. Note that this
     # serves a slightly different purpose than the base class resize() method,
     # which simply resizes the client-side pixel data buffer but doesn't
     # transform the image.
@@ -132,7 +133,8 @@ module Fox
     def scale(w, h, quality=0) ; end
   
     #
-    # Mirror image horizontally and/or vertically.
+    # Mirror image horizontally and/or vertically and then re-render the
+    # server-side image from the client-side pixel buffer.
     #
     # ==== Parameters:
     #
@@ -142,7 +144,8 @@ module Fox
     def mirror(horizontal, vertical) ; end
   
     #
-    # Rotate image counter-clockwise by some number of degrees.
+    # Rotate image counter-clockwise by some number of degrees and then
+    # re-render the server-side image from the client-side pixel buffer.
     #
     # ==== Parameters:
     #
@@ -151,7 +154,8 @@ module Fox
     def rotate(degrees) ; end
   
     #
-    # Crop image to given rectangle; this calls resize() to adjust the client
+    # Crop image to given rectangle and then re-render the server-side image
+    # from the client-side pixel buffer. This method calls resize() to adjust the client
     # and server side representations.  The new image may be smaller or larger
     # than the old one; blank areas are filled with color. There must be at
     # least one pixel of overlap between the old and the new image.
@@ -165,6 +169,88 @@ module Fox
     # +color+::	fill color for blank areas after crop [FXColor]
     #
     def crop(x, y, w, h, color=0) ; end
+    
+    # Fill image with uniform color.
+    def fill(color); end
+    
+    #
+    # Fade an image to a certain color by a certain factor. The _factor_ is
+    # some integer value between 0 and 255 inclusive, where a factor of 255 indicates no fading and a factor
+    # of zero indicates that the image is completely faded to the fade _color_.
+    #
+    # ==== Parameters:
+    #
+    # +color+::   the fade color [FXColor]
+    # +factor+::	fading factor [Integer]
+    #
+    def fade(color, factor=255); end
+
+    #
+    # Shear image horizontally and then re-render the server-side image
+    # from the client-side pixel buffer. The number of pixels is equal to the
+    # _shear_ parameter times 256. The area outside the image is filled
+    # with transparent black, unless another _color_ is specified.
+    #
+    # ==== Parameters:
+    #
+    # +shear+::   how far to shear [Integer]
+    # +color+::	  fill color for areas outside the sheared image [FXColor]
+    #
+    def xshear(shear, color=0); end
+
+    #
+    # Shear image verticallyand then re-render the server-side image
+    # from the client-side pixel buffer. The number of pixels is equal to the
+    # _shear_ parameter times 256. The area outside the image is filled
+    # with transparent black, unless another _color_ is specified.
+    #
+    # ==== Parameters:
+    #
+    # +shear+::   how far to shear [Integer]
+    # +color+::	  fill color for areas outside the sheared image [FXColor]
+    #
+    def yshear(shear, color=0); end
+
+    #
+    # Fill image using a horizontal gradient.
+    #
+    # ==== Parameters:
+    #
+    # +left+::   starting color, for leftmost pixels [FXColor]
+    # +right+::  ending color, for rightmost pixels [FXColor]
+    #
+    def hgradient(left, right); end
+
+    #
+    # Fill image using a vertical gradient.
+    #
+    # ==== Parameters:
+    #
+    # +top+::      starting color, for topmost pixels [FXColor]
+    # +bottom+::	 ending color, for bottommost pixels [FXColor]
+    #
+    def vgradient(top, bottom); end
+
+    #
+    # Fill image using a bilinear gradient.
+    #
+    # ==== Parameters:
+    #
+    # +topleft+::      pixel color for top-left corner [FXColor]
+    # +topright+::	   pixel color for top-right corner [FXColor]
+    # +bottomleft+::   pixel color for bottom-left corner [FXColor]
+    # +bottomright+::  pixel color for bottom-right corner [FXColor]
+    #
+    def gradient(topleft, topright, bottomleft, bottomright); end
+
+    #
+    # Blend image over uniform color.
+    #
+    # ==== Parameters:
+    #
+    # +color+::	  the blended color [FXColor]
+    #
+    def blend(color); end
   
     #
     # Save pixel data to a stream.
diff --git a/rdoc-sources/FXImageFrame.rb b/rdoc-sources/FXImageFrame.rb
index 7dd0a05515867004de8b96cd17950da95fe1e4fa..ec8436060ee345a08418c9f574f1c031561180ea 100755
--- a/rdoc-sources/FXImageFrame.rb
+++ b/rdoc-sources/FXImageFrame.rb
@@ -16,6 +16,20 @@ module Fox
     #
     # Return an initialized FXImageFrame instance.
     #
+    # ==== Parameters:
+    #
+    # +p+::         the parent window for this image frame [FXComposite]
+    # +img+::       the image to display [FXImage]
+    # +opts+::	    frame options [Integer]
+    # +x+::	        initial x-position [Integer]
+    # +y+::	        initial y-position [Integer]
+    # +width+::	    initial width [Integer]
+    # +height+::	  initial height [Integer]
+    # +padLeft+::	  internal padding on the left side, in pixels [Integer]
+    # +padRight+::	internal padding on the right side, in pixels [Integer]
+    # +padTop+::	  internal padding on the top side, in pixels [Integer]
+    # +padBottom+::	internal padding on the bottom side, in pixels [Integer]
+    #
     def initialize(p, img, opts=FRAME_SUNKEN|FRAME_THICK, x=0, y=0, width=0, height=0, padLeft=0, padRight=0, padTop=0, padBottom=0) # :yields: theImageFrame
     end
   end
diff --git a/rdoc-sources/FXInputDialog.rb b/rdoc-sources/FXInputDialog.rb
index b7bbe25626f97c10b148365b010192b36524d424..42dc8007e93540a303ccf4e45541de37babb4da6 100755
--- a/rdoc-sources/FXInputDialog.rb
+++ b/rdoc-sources/FXInputDialog.rb
@@ -26,6 +26,9 @@ module Fox
     #
     def initialize(owner, caption, label, icon=nil, opts=INPUTDIALOG_STRING, x=0, y=0, width=0, height=0) # :yields: theInputDialog
     end
+    
+    # Return the input dialog's input string text
+    def to_s; text; end
   
     #
     # Change limits (where _lo_ and _hi_ are numbers).
diff --git a/rdoc-sources/FXLabel.rb b/rdoc-sources/FXLabel.rb
index abbe0bd9249daf13bc14bf5cf496b59cabd1c428..ebf456f22dd6307c46c30e819e60ccb1fad4f2fb 100755
--- a/rdoc-sources/FXLabel.rb
+++ b/rdoc-sources/FXLabel.rb
@@ -65,5 +65,8 @@ module Fox
     # Construct label with given text and icon
     def initialize(parent, text, icon=nil, opts=LABEL_NORMAL, x=0, y=0, width=0, height=0, padLeft=DEFAULT_PAD, padRight=DEFAULT_PAD, padTop=DEFAULT_PAD, padBottom=DEFAULT_PAD) # :yields: theLabel
     end
+    
+    # Return the label's text
+    def to_s; text; end
   end
 end
diff --git a/rdoc-sources/FXList.rb b/rdoc-sources/FXList.rb
index a91929d8097415a0c76c7c9dfa21eedd31efed6d..949ae6c631365952155be50a0038f0e6fecdbedd 100755
--- a/rdoc-sources/FXList.rb
+++ b/rdoc-sources/FXList.rb
@@ -29,6 +29,9 @@ module Fox
     def initialize(text, icon=nil, data=nil) # :yields: theListItem
     end
     
+    # Return the list item's text
+    def to_s; text; end
+    
     # Returns +true+ if this item has the focus
     def hasFocus?() ; end
     
@@ -288,8 +291,9 @@ module Fox
     def findItem(text, start=-1, flags=SEARCH_FORWARD|SEARCH_WRAP) ; end
 
     #
-    # Search items by associated user _data_, beginning from item _start_. If the
-    # start item is -1 the search will start at the first item in the list.
+    # Search items by associated user _data_, beginning from item _start_.
+    # Returns the integer index of the matching item, or -1 if no match is
+    # found. If the start item is -1 the search will start at the first item in the list.
     # Flags may be +SEARCH_FORWARD+ or +SEARCH_BACKWARD+ to control the
     # search direction; this can be combined with +SEARCH_NOWRAP+ or +SEARCH_WRAP+
     # to control whether the search wraps at the start or end of the list.
diff --git a/rdoc-sources/FXMDIChild.rb b/rdoc-sources/FXMDIChild.rb
index f9d18d7c770a4596e481d2bdb023446cd81dfd76..30a741f56e43dfad7f18d5a06e907e124fe59953 100755
--- a/rdoc-sources/FXMDIChild.rb
+++ b/rdoc-sources/FXMDIChild.rb
@@ -116,12 +116,6 @@ module Fox
     def initialize(p, name, ic=nil, pup=nil, opts=0, x=0, y=0, width=0, height=0) # :yields: theMDIChild
     end
   
-    # Get next MDI Child
-    def getMDINext(); end
-  
-    # Get previous MDI Child
-    def getMDIPrev(); end
-  
     #
     # Minimize this window.
     # If _notify_ is +true+, ...
diff --git a/rdoc-sources/FXMDIClient.rb b/rdoc-sources/FXMDIClient.rb
index 2553cd9483431568460a2bffd768bdaf96242d2d..5303b66f66dd08cbbeca4f279f2dc9669224e6b5 100755
--- a/rdoc-sources/FXMDIClient.rb
+++ b/rdoc-sources/FXMDIClient.rb
@@ -38,12 +38,6 @@ module Fox
     def initialize(p, opts=0, x=0, y=0, width=0, height=0) # :yields: theMDIClient
     end
 
-    # Get first MDI Child
-    def getMDIChildFirst(); end
-  
-    # Get last MDI Child
-    def getMDIChildLast(); end
-  
     #
     # Pass message to all MDI windows, stopping when one of
     # the MDI windows fails to handle the message.
diff --git a/rdoc-sources/FXMenuCaption.rb b/rdoc-sources/FXMenuCaption.rb
index 5482670bf962b19985fb728f455d27a699773e11..128ba6d1735c17160b13479984038be55013cfed 100755
--- a/rdoc-sources/FXMenuCaption.rb
+++ b/rdoc-sources/FXMenuCaption.rb
@@ -45,6 +45,9 @@ module Fox
     #
     def initialize(parent, text, icon=nil, opts=0) # :yields: theMenuCaption
     end
+    
+    # Return the menu caption's text
+    def to_s; text; end
   end
 end
 
diff --git a/rdoc-sources/FXMessageBox.rb b/rdoc-sources/FXMessageBox.rb
index ccd4043c8596c41bbc226ae4c483460622f95d49..c77b132e720bb3c2bee9c178752799c0df80fe3a 100755
--- a/rdoc-sources/FXMessageBox.rb
+++ b/rdoc-sources/FXMessageBox.rb
@@ -29,6 +29,7 @@ module Fox
   # +MBOX_CLICKED_SAVE+::	The *Save* button was clicked
   # +MBOX_CLICKED_SKIP+::	The *Skip* button was clicked
   # +MBOX_CLICKED_SKIPALL+::	The *Skip All* button was clicked
+  # +MBOX_CLICKED_DONTSAVE+:: The *Don't Save* button was clicked (same as +MBOX_CLICKED_NO+)
   #
   class FXMessageBox < FXDialogBox
     #
diff --git a/rdoc-sources/FXPacker.rb b/rdoc-sources/FXPacker.rb
index bae1fc30cbca0304868f8df925afc8c8b9888356..7472dff7e4bfd7a299dd90d69357f9767d219089 100755
--- a/rdoc-sources/FXPacker.rb
+++ b/rdoc-sources/FXPacker.rb
@@ -58,5 +58,6 @@ module Fox
     #
     def initialize(parent, opts=0, x=0, y=0, width=0, height=0, padLeft=DEFAULT_SPACING, padRight=DEFAULT_SPACING, padTop=DEFAULT_SPACING, padBottom=DEFAULT_SPACING, hSpacing=DEFAULT_SPACING, vSpacing=DEFAULT_SPACING) # :yields: thePacker
     end
+  end
 end
 
diff --git a/rdoc-sources/FXTable.rb b/rdoc-sources/FXTable.rb
index 1ea43329ccd84d9e29e3a189e01ebb03a9bd7c51..7ce4065672bd20966ad4ee112e6836245293168b 100755
--- a/rdoc-sources/FXTable.rb
+++ b/rdoc-sources/FXTable.rb
@@ -155,7 +155,42 @@ module Fox
     def destroy; end
   end
   
-  # Table Widget
+  #
+  # The FXTable widget displays a table of items, each with some text and optional
+  # icon.  A column Header control provide captions for each column, and a row
+  # Header control provides captions for each row.  Columns are resizable by
+  # means of the column Header control if the TABLE_COL_SIZABLE option is passed.
+  # Likewise, rows in the table are resizable if the TABLE_ROW_SIZABLE option is
+  # specified.  An entire row (column) can be selected by clicking on the a button
+  # in the row (column) Header control.  Passing TABLE_NO_COLSELECT disables column
+  # selection, and passing TABLE_NO_ROWSELECT disables column selection.
+  # When TABLE_COL_RENUMBER is specified, columns are automatically renumbered when
+  # columns are added or removed.  Similarly, TABLE_ROW_RENUMBER will cause row numbers
+  # to be recalculated automatically when rows are added or removed.
+  # To disable editing of cells in the table, the TABLE_READONLY can be specified.
+  # Cells in the table may or may not have items in them.  When populating a cell
+  # for the first time, an item will be automatically created if necessary.  Thus,
+  # a cell in the table takes no space unless it has actual contents.
+  # Moreover, a contiguous, rectangular region of cells in the table may refer to
+  # one single item; in that case, the item will be stretched to cover all the
+  # cells in the region, and no grid lines will be drawn interior to the spanning
+  # item.
+  #
+  # The Table widget issues SEL_SELECTED or SEL_DESELECTED when cells are selected
+  # or deselected, respectively.  The table position affected is passed along as the
+  # 3rd parameter of these messages.
+  # Whenever the current (focus) item is changed, a SEL_CHANGED message is sent with
+  # the new table position as a parameter.
+  # When items are added to the table, a SEL_INSERTED message is sent, with the table
+  # range of the newly added cells as the parameter in the message.
+  # When items are removed from the table, a SEL_DELETED message is sent prior to the
+  # removal of the items, and the table range of the removed cells is passed as a parameter.
+  # A SEL_REPLACED message is sent when the contents of a cell are changed, either through
+  # editing or by other means; the parameter is the range of affected cells.  This message
+  # is sent prior to the change.
+  # SEL_CLICKED, SEL_DOUBLECLICKED, and SEL_TRIPLECLICKED messages are sent when a cell
+  # is clicked, double-clicked, or triple-clicked, respectively. 
+  # A SEL_COMMAND is sent when an enabled item is clicked inside the table.
   #
   # === Events
   #
@@ -573,18 +608,10 @@ module Fox
     # Raises IndexError if _row_ is out of bounds.
     def getRowHeight(row) ; end
   
-    # Set x-coordinate for column.
-    # Raises IndexError if _column_ is out of bounds.
-    def setColumnX(column, x) ; end
-    
     # Get x-coordinate of column.
     # Raises IndexError if _column_ is out of bounds.
     def getColumnX(column) ; end
   
-    # Set y-coordinate of row.
-    # Raises IndexError if _row_ is out of bounds.
-    def setRowY(row, y) ; end
-    
     # Get y-coordinate of row.
     # Raises IndexError if _row_ is out of bounds.
     def getRowY(row) ; end
@@ -610,51 +637,67 @@ module Fox
     def fitColumnsToContents(col, nc=1); end
     
     # Set column header at _index_ to _text_.
+    # Raises IndexError if _index_ is out of bounds.
     def setColumnText(index, text); end
     
     # Return text of column header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getColumnText(index); end
     
     # Set row header at _index_ to _text_.
+    # Raises IndexError if _index_ is out of bounds.
     def setRowText(index, text); end
     
     # Return text of row header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getRowText(index); end
 
-    # Change column header icon
+    # Change column header icon.
+    # Raises IndexError if _index_ is out of bounds.
     def setColumnIcon(FXint index,FXIcon* icon);
 
-    # Return icon of column header at index
+    # Return icon of column header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getColumnIcon(index); end
 
-    # Change row header icon
+    # Change row header icon.
+    # Raises IndexError if _index_ is out of bounds.
     def setRowIcon(index, icon); end
     
-    # Return icon of row header at index
+    # Return icon of row header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getRowIcon(index); end
 
     # Change column header icon position, e.g. FXHeaderItem::BEFORE, etc.
+    # Raises IndexError if _index_ is out of bounds.
     def setColumnIconPosition(index, mode); end
 
-    # Return icon position of column header at index
+    # Return icon position of column header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getColumnIconPosition(index); end
 
     # Change row header icon position, e.g. FXHeaderItem::BEFORE, etc.
+    # Raises IndexError if _index_ is out of bounds.
     def setRowIconPosition(index, mode); end
 
-    # Return icon position of row header at index
+    # Return icon position of row header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getRowIconPosition(index); end
     
     # Change column header justify, e.g. FXHeaderItem::RIGHT, etc.
+    # Raises IndexError if _index_ is out of bounds.
     def setColumnJustify(index, justify); end
 
-    # Return justify of column header at index
+    # Return justify of column header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getColumnJustify(index); end
 
     # Change row header justify, e.g. FXHeaderItem::RIGHT, etc.
+    # Raises IndexError if _index_ is out of bounds.
     def setRowJustify(index, justify); end
 
-    # Return justify of row header at index
+    # Return justify of row header at _index_.
+    # Raises IndexError if _index_ is out of bounds.
     def getRowJustify(index); end
     
     #
diff --git a/rdoc-sources/FXText.rb b/rdoc-sources/FXText.rb
index 99d48bd0fff1baa2fb353cc8674ae15ecd7c913c..1ffdd7b9efc307df62e3435dc90f87f3247a4e86 100755
--- a/rdoc-sources/FXText.rb
+++ b/rdoc-sources/FXText.rb
@@ -2,7 +2,7 @@ module Fox
   #
   # Highlight style entry
   #
-  class FXHiliteStyle
+  class FXHiliteStyle 
     # Normal text foreground color [FXColor]
     attr_accessor	:normalForeColor
 
@@ -315,7 +315,7 @@ module Fox
     # +p+::	the parent window for this text widget [FXComposite]
     # +target+::	the message target, if any, for this text widget [FXObject]
     # +selector+::	the message identifier for this text widget [Integer]
-    # +opts+::	tree list options [Integer]
+    # +opts+::	text options [Integer]
     # +x+::	initial x-position [Integer]
     # +y+::	initial y-position [Integer]
     # +width+::	initial width [Integer]
@@ -324,6 +324,9 @@ module Fox
     def initialize(p, target=nil, selector=0, opts=0, x=0, y=0, width=0, height=0, padLeft=3, padRight=3, padTop=2, padBottom=2) # :yields: theText
     end
     
+    # Return the text buffer's value
+    def to_s; text; end
+    
     # Return +true+ if text was modified
     def modified? ; end
     
@@ -430,18 +433,19 @@ module Fox
     # text is inserted.
     def shiftText(startPos, endPos, amount, notify=false); end
 
-    # Search for _string_ in text buffer, returning the extent of
-    # the string in _beg_ and _end_.  The search starts from the given
+    #
+    # Search for _string_ in text buffer, and return the extent of
+    # the string as a two-element array of arrays.
+    # The first array contains the beginning index (or indices)
+    # and the second array contains the ending index (or indices).
+    # The search starts from the given
     # _start_ position, scans forward (+SEARCH_FORWARD+) or backward
     # (+SEARCH_BACKWARD+), and wraps around if +SEARCH_WRAP+ has been
     # specified.  The search type is either a plain search (+SEARCH_EXACT+),
     # case insensitive search (+SEARCH_IGNORECASE+), or regular expression
     # search (+SEARCH_REGEX+).
-    # For regular expression searches, capturing parentheses are used if
-    # _npar_ is greater than 1; in this case, the number of entries in the
-    # _beg_ and _end_ arrays must be _npar_ also.  If either _beg_ or _end_ or
-    # both are nil, internal arrays are used.
-    def findText(string, beg=nil, end=nil, start=0, flags=SEARCH_FORWARD|SEARCH_WRAP|SEARCH_EXACT, npar=1); end
+    #
+    def findText(string, start=0, flags=SEARCH_FORWARD|SEARCH_WRAP|SEARCH_EXACT); end
 
     # Return +true+ if position _pos_ is selected
     def positionSelected?(pos); end
diff --git a/rdoc-sources/FXToggleButton.rb b/rdoc-sources/FXToggleButton.rb
index 6207c43a643f1ec756d802051e5c8a3b9f4e6164..95bd9dac32d96e9ef0447e71d01650cf411c1142 100755
--- a/rdoc-sources/FXToggleButton.rb
+++ b/rdoc-sources/FXToggleButton.rb
@@ -19,6 +19,7 @@ module Fox
   # +TOGGLEBUTTON_AUTOGRAY+::	Automatically gray out when not updated
   # +TOGGLEBUTTON_AUTOHIDE+::	Automatically hide toggle button when not updated
   # +TOGGLEBUTTON_TOOLBAR+::	Toolbar style toggle button [flat look]
+  # +TOGGLEBUTTON_KEEPSTATE+::  Draw button according to state
   # +TOGGLEBUTTON_NORMAL+::	<tt>FRAME_RAISED|FRAME_THICK|JUSTIFY_NORMAL|ICON_BEFORE_TEXT</tt>
   #
   class FXToggleButton < FXLabel
diff --git a/rdoc-sources/FXToolTip.rb b/rdoc-sources/FXToolTip.rb
index 89dd950d31e877b668da14ee36f215a420e209e7..a01eaf28aa84b9e1ffb3b323e9352fc560369a22 100755
--- a/rdoc-sources/FXToolTip.rb
+++ b/rdoc-sources/FXToolTip.rb
@@ -32,5 +32,8 @@ module Fox
 
     # Set the current tip text color
     def textColor=(color); end
+    
+    # Return the tool tip's text
+    def to_s; text; end
   end
 end
diff --git a/rdoc-sources/FXVec2d.rb b/rdoc-sources/FXVec2d.rb
index a3f91842cc7f0a09cf9077efbc882405ce1379c5..0b1f419c484126e09188a576482eaf61ba90f320 100755
--- a/rdoc-sources/FXVec2d.rb
+++ b/rdoc-sources/FXVec2d.rb
@@ -7,7 +7,7 @@ module Fox
     #
     # Return an initialized FXVec2d instance.
     #
-    def initialize(xx, yy); end
+    def initialize(xx=0.0, yy=0.0); end
   
     #
     # Returns the element at _index_, where _index_ is 0 or 1.
diff --git a/rdoc-sources/FXVec2f.rb b/rdoc-sources/FXVec2f.rb
index 7706e99bd78b21ea271b78d4694a24d174abb7ba..887a4bd241604da3f322f079e6739209920df52b 100755
--- a/rdoc-sources/FXVec2f.rb
+++ b/rdoc-sources/FXVec2f.rb
@@ -7,7 +7,7 @@ module Fox
     #
     # Return an initialized FXVec2f instance.
     #
-    def initialize(xx, yy); end
+    def initialize(xx=0.0, yy=0.0); end
   
     #
     # Returns the element at _index_, where _index_ is 0 or 1.
diff --git a/rdoc-sources/FXVec3d.rb b/rdoc-sources/FXVec3d.rb
index ecfc2cb17c09a7e812fa49f794ab6dacffd57ae6..637ab0a925c34b19fbcef242efd4221f9175d120 100755
--- a/rdoc-sources/FXVec3d.rb
+++ b/rdoc-sources/FXVec3d.rb
@@ -6,9 +6,14 @@ module Fox
     attr_accessor :z
     
     #
-    # Return an initialized FXVec3d instance.
+    # Return an FXVec3d instance with _x_, _y_ and _z_ initialized to zeroes.
     #
-    def initialize(xx, yy, zz); end
+    def initialize; end
+    
+    #
+    # Return an FXVec3d instance initialized from specified component values.
+    #
+    def initialize(xx, yy, zz=1.0); end
   
     #
     # Returns the element at _index_, where _index_ is 0, 1 or 2.
diff --git a/rdoc-sources/FXVec3f.rb b/rdoc-sources/FXVec3f.rb
index 97e9bb827e07dbeec533dc95efcee2045969eb37..e3745a884878d14081eadccb1d0bdbecd287ef05 100755
--- a/rdoc-sources/FXVec3f.rb
+++ b/rdoc-sources/FXVec3f.rb
@@ -6,9 +6,14 @@ module Fox
     attr_accessor :z
     
     #
-    # Return an initialized FXVec3f instance.
+    # Return an FXVec3f instance with _x_, _y_ and _z_ initialized to zeroes.
     #
-    def initialize(xx, yy, zz); end
+    def initialize; end
+    
+    #
+    # Return an FXVec3f instance initialized with specified component values.
+    #
+    def initialize(xx, yy, zz=1.0); end
   
     #
     # Returns the element at _index_, where _index_ is 0, 1 or 2.
diff --git a/rdoc-sources/FXVec4d.rb b/rdoc-sources/FXVec4d.rb
index 527a8f65431ace30be65f1969083424797d538ee..f12a40c86c5893946185b66fdae94ba9cddf3554 100755
--- a/rdoc-sources/FXVec4d.rb
+++ b/rdoc-sources/FXVec4d.rb
@@ -7,12 +7,22 @@ module Fox
     attr_accessor :w
     
     #
-    # Return an initialized FXVec4d instance.
+    # Return an FXVec4d instance with _x_, _y_, _z_ and _w_ initialized to zeroes.
+    #
+    def initialize; end
+
+    #
+    # Return an FXVec4d instance initialized from specified component values.
     #
     def initialize(xx, yy, zz, ww=1.0); end
+    
+    #
+    # Return an FXVec4d instance initialized from an FXVec3d instance and optional scalar.
+    #
+    def initialize(vec3d, ww=1.0); end
   
     #
-    # Returns the element at _index_, where _index_ is 0, 1 or 2.
+    # Returns the element at _index_, where _index_ is 0, 1, 2 or 3.
     # Raises IndexError if _index_ is out of range.
     #
     def [](index); end
diff --git a/rdoc-sources/FXVec4f.rb b/rdoc-sources/FXVec4f.rb
index 0f79b3c01c761c9a1db1514518e16ee22264cda6..72fddce934fd521df7f9347c09a748288e7f341c 100755
--- a/rdoc-sources/FXVec4f.rb
+++ b/rdoc-sources/FXVec4f.rb
@@ -7,12 +7,22 @@ module Fox
     attr_accessor :w
     
     #
-    # Return an initialized FXVec4f instance.
+    # Return an FXVec4f instance with _x_, _y_, _z_ and _w_ initialized to zeroes.
+    #
+    def initialize; end
+
+    #
+    # Return an FXVec4f instance initialized from specified component values.
     #
     def initialize(xx, yy, zz, ww=1.0); end
+    
+    #
+    # Return an FXVec4f instance initialized from an FXVec3f instance and optional scalar.
+    #
+    def initialize(vec3f, ww=1.0); end
   
     #
-    # Returns the element at _index_, where _index_ is 0, 1 or 2.
+    # Returns the element at _index_, where _index_ is 0, 1, 2 or 3.
     # Raises IndexError if _index_ is out of range.
     #
     def [](index); end
diff --git a/rdoc-sources/FXWindow.rb b/rdoc-sources/FXWindow.rb
index 317375ec430ecaeaca9672832acbe2e925da54f2..71ce72c8251631feb72d7155f921fcb7256e7e99 100755
--- a/rdoc-sources/FXWindow.rb
+++ b/rdoc-sources/FXWindow.rb
@@ -78,6 +78,7 @@ module Fox
   # +LAYOUT_MIN_HEIGHT+::   Minimum height is the default
   # +LAYOUT_FILL_X+::       Stretch or shrink horizontally
   # +LAYOUT_FILL_Y+::       Stretch or shrink vertically
+  # +LAYOUT_FILL::          Stretch or shrink in both directions
   # +LAYOUT_EXPLICIT+::     Explicit placement
   # +LAYOUT_DOCK_SAME+::    Dock on same galley, if it fits
   # +LAYOUT_DOCK_NEXT+::    Dock on next galley
diff --git a/scripts/FXRuby.iss.in b/scripts/FXRuby.iss.in
index 4733829ea9b34541f7b6b856b7e115266cf7b974..9bbedf4055eabd5df2344ba03b83abd2f02cf3f4 100755
--- a/scripts/FXRuby.iss.in
+++ b/scripts/FXRuby.iss.in
@@ -20,14 +20,9 @@ OutputBaseFilename=FXRuby-@@FXRUBY_VERSION@@-@@RUBYVER@@
 Source: "LICENSE"; DestDir: "{app}\doc\FXRuby"; Flags: ignoreversion
 Source: "README.win32.txt"; DestDir: "{app}\doc\FXRuby"; Flags: ignoreversion
 Source: "README"; DestDir: "{app}\doc\FXRuby"; Flags: ignoreversion
-Source: "index.html"; DestDir: "{app}\doc\FXRuby"; Flags: ignoreversion
 ; HTML documentation files
 Source: "doc\*.html"; DestDir: "{app}\doc\FXRuby\doc"; Flags: ignoreversion
 Source: "doc\images\*.png"; DestDir: "{app}\doc\FXRuby\doc\images"; Flags: ignoreversion
-Source: "web\*.html"; DestDir: "{app}\doc\FXRuby\doc\web"; Flags: ignoreversion
-Source: "web\*.css"; DestDir: "{app}\doc\FXRuby\doc\web"; Flags: ignoreversion
-Source: "web\art\*.gif"; DestDir: "{app}\doc\FXRuby\doc\web\art"; Flags: ignoreversion
-Source: "web\art\*.png"; DestDir: "{app}\doc\FXRuby\doc\web\art"; Flags: ignoreversion
 ; unit tests
 Source: "tests\README"; DestDir: "{app}\doc\FXRuby\tests"; Flags: ignoreversion
 Source: "tests\*.rb"; DestDir: "{app}\doc\FXRuby\tests"; Flags: ignoreversion
diff --git a/scripts/generate_kwargs_lib.rb b/scripts/generate_kwargs_lib.rb
index 712a056f8dce2d6bd2d27671713320da2d2556f6..0c9cc8a7ac7b86bfb5525d4c8bbe6ebd335c09ae 100644
--- a/scripts/generate_kwargs_lib.rb
+++ b/scripts/generate_kwargs_lib.rb
@@ -13,27 +13,91 @@ Known problems (due to overloaded constructors):
 
 =end
 
+CLASSES_TO_SKIP = %w{FX4Splitter FXCursor FXDCWindow FXExtentd FXExtentf FXFont FXGLCanvas FXGLShape FXGLViewer FXDockBar FXMenuBar FXToolBar FXQuatd FXQuatf FXRanged FXRangef FXRecentFiles FXRectangle FXRegion FXSize FXSphered FXSpheref FXSplitter FXVec2d FXVec2f FXVec3d FXVec3f FXVec4d FXVec4f FXWindow}
+
 class Arg
   attr_reader :name
   attr_reader :value
+
   def initialize(name, value)
     @name = name
     @value = value
   end
 end
 
-class Desc
-  
-  attr_accessor :class_name
+class MethodDescription
+  attr_accessor :method_name
   attr_accessor :required_args
   attr_accessor :optional_args
-  
+
   def initialize
-    @class_name = nil
+    @method_name = nil
     @required_args = []
     @optional_args = []
   end
+  
+  def generate_alias
+    "    alias old_#{method_name} #{method_name}\n"
+  end
+  
+  def generate_body
+    argument_names = optional_args.map { |arg| arg.name }
+    defaults_hash = optional_args.map { |arg| ":#{arg.name} => #{arg.value}"}
+    defaults_hash = "{ #{defaults_hash.join(', ')} }"
+    required = required_args.join(", ")
+    optional = optional_args.map { |arg| "params[:#{arg.name}]"}
+    optional = optional.join(", ")
+    buffer = ""
+    buffer << "    def #{method_name}(#{required}#{required_args.length > 0 ? ', ' : ''}*args#{expects_block? ? ', &blk' : ''})\n"
+    buffer << "      argument_names = %w{#{argument_names.join(' ')}}\n"
+    buffer << "      default_params = #{defaults_hash}\n"
+    buffer << "      params = {}\n"
+    buffer << "      params = args.pop if args.last.is_a? Hash\n"
+    buffer << "      args.each_with_index { |e, i| params[argument_names[i].intern] = e }\n"
+    if optional_args.any? { |arg| arg.name == "padLeft" }
+      buffer << "      if params.key? :padding\n"
+      buffer << "        value = params.delete(:padding)\n"
+      buffer << "        [:padLeft, :padRight, :padTop, :padBottom].each { |s| params[s] ||= value }\n"
+      buffer << "      end\n"
+    end
+    buffer << "      params.keys.each { |key| raise ArgumentError, \"Unrecognized parameter \#{key}\" unless default_params.keys.include?(key) }\n"
+    buffer << "      params = default_params.merge(params)\n"
+    buffer << "      old_#{method_name}(#{required}#{(required_args.length > 0) && (optional_args.length > 0) ? ', ' : ''}#{optional}#{expects_block? ? ', &blk' : ''})\n"
+    buffer << "    end\n"
+    buffer
+  end
+  
+  def expects_block?
+    method_name == "initialize"
+  end
+end
 
+class ClassDescription  
+  attr_accessor :class_name
+  attr_accessor :method_descriptions
+  
+  def initialize
+    @class_name = nil
+    @method_descriptions = []
+  end
+  
+  def generate_class_initializer
+    buffer = ""
+    buffer << "  class #{class_name}\n"
+    method_descriptions.each do |method_description|
+      buffer << method_description.generate_alias
+      buffer << method_description.generate_body
+    end
+    buffer << "  end\n\n"
+    buffer
+  end
+  
+  def has_methods_with_optional_arguments?
+    method_descriptions.each do |m|
+      return true if m.optional_args.length > 0
+    end
+    false
+  end
 end
 
 class Generator
@@ -46,88 +110,65 @@ class Generator
     out.puts <<-END
 require 'fox16'
 
+$VERBOSE = nil
+
 module Fox
 
 END
     out.puts(DATA.read)
   end
 
-  def generate_class_initializer(desc)
-    argument_names = desc.optional_args.map { |arg| arg.name }
-    defaults_hash = desc.optional_args.map { |arg| ":#{arg.name} => #{arg.value}"}
-    defaults_hash = "{ #{defaults_hash.join(', ')} }"
-    required_args = desc.required_args.join(", ")
-    optional_args = desc.optional_args.map { |arg| "params[:#{arg.name}]"}
-    optional_args = optional_args.join(", ")
-    buffer = ""
-    buffer << "  class #{desc.class_name}\n"
-    buffer << "    alias old_initialize initialize\n"
-    buffer << "    def initialize(#{required_args}#{desc.required_args.length > 0 ? ', ' : ''}*args, &blk)\n"
-    buffer << "      argument_names = %w{#{argument_names.join(' ')}}\n"
-    buffer << "      default_params = #{defaults_hash}\n"
-    buffer << "      params = {}\n"
-    buffer << "      params = args.pop if args.last.is_a? Hash\n"
-    buffer << "      args.each_with_index { |e, i| params[argument_names[i].intern] = e }\n"
-    if desc.optional_args.any? { |arg| arg.name == "padLeft" }
-    buffer << "      if params.key? :padding\n"
-    buffer << "        value = params.delete(:padding)\n"
-    buffer << "        [:padLeft, :padRight, :padTop, :padBottom].each { |s| params[s] ||= value }\n"
-    buffer << "      end\n"
-    end
-    buffer << "      params.keys.each { |key| raise ArgumentError, \"Unrecognized parameter \#{key}\" unless default_params.keys.include?(key) }\n"
-    buffer << "      params = default_params.merge(params)\n"
-    buffer << "      old_initialize(#{required_args}#{(desc.required_args.length > 0) && (desc.optional_args.length > 0) ? ', ' : ''}#{optional_args}, &blk)\n"
-    buffer << "    end\n"
-    buffer << "  end\n\n"
-    buffer
-  end
-  
   def go(filenames, output_filename)
     out = File.new(output_filename, "w")
-    descriptions = []
-    filenames.each { |filename| descriptions += scan_for_descriptions(filename) }
+    class_descriptions = []
+    filenames.each { |filename| class_descriptions += scan_for_descriptions(filename) }
     generate_preamble(out)
-    descriptions.each do |desc|
-      out.puts generate_class_initializer(desc) if desc.optional_args.length > 0
+    class_descriptions.each do |class_description|
+      out.puts class_description.generate_class_initializer if class_description.has_methods_with_optional_arguments?
     end
     generate_closing(out)
   end
   
   def generate_closing(out)
     out.puts "end"
+    out.puts ""
+    out.puts "$VERBOSE = true"
   end
   
   def scan_for_descriptions(filename)
-    desc = nil
-    descriptions = []
+    class_description = nil
+    class_descriptions = []
     IO.foreach(filename) do |str|
       if str =~ /^  class\s*(\w+).*$/
-        desc = Desc.new
-        desc.class_name = $1
-      elsif str =~ /def initialize\((.*)\)/
-#       args = $1.split(',').map { |x| x.strip }
-        args = $1.split(', ').map { |x| x.strip }
+        class_description = ClassDescription.new
+        class_description.class_name = $1
+      elsif str =~ /def (initialize|findText)\((.*)\)/
+        method_description = MethodDescription.new
+        method_description.method_name = $1
+#       args = $2.split(',').map { |x| x.strip }
+        args = $2.split(', ').map { |x| x.strip }
         args.each do |arg|
           if arg =~ /(.*)=(.*)/
-            desc.optional_args << Arg.new($1, $2)
+            method_description.optional_args << Arg.new($1, $2)
           elsif
-            desc.required_args << arg
+            method_description.required_args << arg
           end
         end
-        if @known_classes.has_key? desc.class_name
-          warn "Overloaded initialize method for class: #{desc.class_name}"
+        if @known_classes.has_key? class_description.class_name
+          warn "Overloaded initialize method for class: #{class_description.class_name}"
         end
-        @known_classes[desc.class_name] = 1
+        @known_classes[class_description.class_name] = 1
+        class_description.method_descriptions << method_description
       elsif str =~ /^  end/
-        descriptions << desc unless skip?(desc.class_name)
-        desc = nil
+        class_descriptions << class_description unless skip?(class_description.class_name)
+        class_description = nil
       end
     end
-    descriptions
+    class_descriptions
   end
   
   def skip?(name)
-    %w{FX4Splitter FXCursor FXDCWindow FXExtentd FXExtentf FXFont FXGLCanvas FXGLShape FXGLViewer FXDockBar FXMenuBar FXToolBar FXQuatd FXQuatf FXRanged FXRangef FXRecentFiles FXRectangle FXRegion FXSize FXSphered FXSpheref FXSplitter FXWindow}.include? name
+    CLASSES_TO_SKIP.include? name
   end
 
 end
@@ -191,7 +232,9 @@ __END__
   end
   
   class FXFont
+
     alias old_initialize initialize
+    
     def initialize(a, arg1, *args, &blk)
       if args.length > 0
         face, size = arg1, args[0]
@@ -207,6 +250,22 @@ __END__
         old_initialize(a, arg1, &blk)
       end
     end
+
+    class << self
+      alias old_listFonts listFonts
+    end
+    
+    def FXFont.listFonts(face, *args)
+      argument_names = %w{weight slant setWidth encoding hints}
+      default_params = { :weight => 0, :slant => 0, :setWidth => 0, :encoding => 0, :hints => 0 }     
+      params = {}
+      params = args.pop if args.last.is_a? Hash
+      args.each_with_index { |e, i| params[argument_names[i].intern] = e }
+      params.keys.each { |key| raise ArgumentError, "Unrecognized parameter #{key}" unless default_params.keys.include?(key) }
+      params = default_params.merge(params)
+      old_listFonts(face, params[:weight], params[:slant], params[:setWidth], params[:encoding], params[:hints])
+    end
+
   end
   
   class FXGLCanvas
@@ -261,6 +320,7 @@ __END__
       params = {}
       params = args.pop if args.last.is_a? Hash
       if args.length > 0 && (args[0].nil? || args[0].is_a?(FXComposite))
+        q = args[0]
         args.each_with_index { |e, i| params[argument_names[i-1].intern] = e if i >= 1 }
         if params.key? :padding
           value = params.delete(:padding)
diff --git a/swig-interfaces/FXApp.i b/swig-interfaces/FXApp.i
index 56d6546b535f87cfc5855a071259b82b22a60638..b05387f0e7f64bd379be1a3355ea93a606331c10 100755
--- a/swig-interfaces/FXApp.i
+++ b/swig-interfaces/FXApp.i
@@ -173,7 +173,13 @@ public:
     * as keys into the registry database for this application's settings
     */
     FXApp(const FXchar* name="Application",const FXchar* vendor="FoxDefault"){
-      return FXRbApp::constructAndInit(name,vendor);
+      if(FXApp::instance()){
+        rb_raise(rb_eRuntimeError,"attempted to create more than one FXApp instance");
+        return 0;
+        }
+      else{
+	      return FXRbApp::constructAndInit(name,vendor);
+        }
       }
   }
 
@@ -315,7 +321,7 @@ public:
       FXint sig;
       switch(TYPE(sigObj)){
         case T_STRING:
-          s=STR2CSTR(sigObj);
+          s=StringValuePtr(sigObj);
           sig=FXRbSignalNameToNumber(s);
           if(sig==0) rb_raise(rb_eArgError,"unrecognized signal name `%s'",s);
           break;
@@ -335,7 +341,7 @@ public:
       FXint sig;
       switch(TYPE(sigObj)){
         case T_STRING:
-          s=STR2CSTR(sigObj);
+          s=StringValuePtr(sigObj);
           sig=FXRbSignalNameToNumber(s);
           if(sig==0) rb_raise(rb_eArgError,"unrecognized signal name `%s'",s);
           break;
diff --git a/swig-interfaces/FXDialogBox.i b/swig-interfaces/FXDialogBox.i
index 831f78c1ef0c99d5521e3b4d2e32c24f0921d082..31dcb24a4c1cef5d5c4ebfb2d1e3b20a27e9bce7 100755
--- a/swig-interfaces/FXDialogBox.i
+++ b/swig-interfaces/FXDialogBox.i
@@ -20,7 +20,6 @@
  * at "lyle@users.sourceforge.net".
  ***********************************************************************/
 
-
 /**
 * DialogBox window.
 * When receiving ID_CANCEL or ID_ACCEPT, the DialogBox breaks out of the 
@@ -44,13 +43,13 @@ public:
 public:
   %extend {
     /// Construct free-floating dialog
-    FXDialogBox(FXApp* a,const FXString& name,FXuint opts=DECOR_TITLE|DECOR_BORDER,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=10,FXint pr=10,FXint pt=10,FXint pb=10,FXint hs=4,FXint vs=4){
-      return new FXRbDialogBox(a,name,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
+    FXDialogBox(FXApp* APP,const FXString& name,FXuint opts=DECOR_TITLE|DECOR_BORDER,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=10,FXint pr=10,FXint pt=10,FXint pb=10,FXint hs=4,FXint vs=4){
+      return new FXRbDialogBox(APP,name,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
       }
   
     /// Construct dialog which will always float over the owner window
-    FXDialogBox(FXWindow* owner,const FXString& name,FXuint opts=DECOR_TITLE|DECOR_BORDER,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=10,FXint pr=10,FXint pt=10,FXint pb=10,FXint hs=4,FXint vs=4){
-      return new FXRbDialogBox(owner,name,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
+    FXDialogBox(FXWindow* OWNER,const FXString& name,FXuint opts=DECOR_TITLE|DECOR_BORDER,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=10,FXint pr=10,FXint pt=10,FXint pb=10,FXint hs=4,FXint vs=4){
+      return new FXRbDialogBox(OWNER,name,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
       }
     }
   
diff --git a/swig-interfaces/FXFileDialog.i b/swig-interfaces/FXFileDialog.i
index cf256b87c7e48404da4e97ec8807a62facb4fefc..421f731cf9bb8eaaf20ecd1def82b9e8a7c05573 100755
--- a/swig-interfaces/FXFileDialog.i
+++ b/swig-interfaces/FXFileDialog.i
@@ -104,13 +104,13 @@ public:
     void setPatternList(VALUE ary) {
       FXString patterns;
       if(TYPE(ary)==T_STRING){
-        patterns=FXString(STR2CSTR(ary));
+        patterns=FXString(StringValuePtr(ary));
         }
       else if(TYPE(ary)==T_ARRAY){
-        for(long i=0; i<RARRAY(ary)->len; i++){
+        for(long i=0; i<RARRAY_LEN(ary); i++){
           VALUE obj=rb_ary_entry(ary,i);
           Check_Type(obj,T_STRING);
-          patterns+=FXString(STR2CSTR(obj))+FXString("\n");
+          patterns+=FXString(StringValuePtr(obj))+FXString("\n");
           }
         }
       else{
diff --git a/swig-interfaces/FXFileSelector.i b/swig-interfaces/FXFileSelector.i
index 90b9efd60dca2aa221c413355a1ff6de523132de..1070ba535c51c81a915e2b546abb6065198d3cef 100755
--- a/swig-interfaces/FXFileSelector.i
+++ b/swig-interfaces/FXFileSelector.i
@@ -201,13 +201,13 @@ public:
     void setPatternList(VALUE ary) {
       FXString patterns;
       if(TYPE(ary)==T_STRING){
-        patterns=FXString(STR2CSTR(ary));
+        patterns=FXString(StringValuePtr(ary));
         }
       else if(TYPE(ary)==T_ARRAY){
-        for(long i=0; i<RARRAY(ary)->len; i++){
+        for(long i=0; i<RARRAY_LEN(ary); i++){
           VALUE obj=rb_ary_entry(ary,i);
           Check_Type(obj,T_STRING);
-          patterns+=FXString(STR2CSTR(obj))+FXString("\n");
+          patterns+=FXString(StringValuePtr(obj))+FXString("\n");
           }
         }
       else{
diff --git a/swig-interfaces/FXFoldingList.i b/swig-interfaces/FXFoldingList.i
index e35df45a584391b945ad1b8e5f0db6d283757416..cd33629a6d89ceb6276eb9738d37d4d7a5837b6f 100755
--- a/swig-interfaces/FXFoldingList.i
+++ b/swig-interfaces/FXFoldingList.i
@@ -228,11 +228,12 @@ public:
     /// Set headers from array of strings
     void setHeaders(VALUE stringArray,FXint size=1){
       Check_Type(stringArray,T_ARRAY);
-      long len=RARRAY(stringArray)->len;
+      long len=RARRAY_LEN(stringArray);
       const FXchar **strings;
       if(FXMALLOC(&strings,FXchar*,len+1)){
         for(long i=0;i<len;i++){
-	  strings[i]=STR2CSTR(rb_ary_entry(stringArray,i));
+          VALUE s=rb_ary_entry(stringArray,i);
+	  strings[i]=StringValuePtr(s);
           }
 	strings[len]=0;
         self->setHeaders(strings,size);
diff --git a/swig-interfaces/FXImage.i b/swig-interfaces/FXImage.i
index fd6fbfaa61a1baef8ea356e2a3702a3e8097a3b1..3ecef04abe6164cc33f5f8fd5097726c6caaff1b 100755
--- a/swig-interfaces/FXImage.i
+++ b/swig-interfaces/FXImage.i
@@ -59,8 +59,8 @@ public:
       FXColor* pix=0;
       if(!NIL_P(ary)){
         Check_Type(ary,T_ARRAY);
-        if(FXMALLOC(&pix,FXColor,RARRAY(ary)->len)){
-          for(long i=0; i<RARRAY(ary)->len; i++){
+        if(FXMALLOC(&pix,FXColor,RARRAY_LEN(ary))){
+          for(long i=0; i<RARRAY_LEN(ary); i++){
             pix[i]=static_cast<FXColor>(NUM2UINT(rb_ary_entry(ary,i)));
 	    }
           }
diff --git a/swig-interfaces/FXMainWindow.i b/swig-interfaces/FXMainWindow.i
index dd59958e3685d1eb93f34ae5d0f29cc1d74128a3..08f461aedb1bcc9c03a3b629f6838f16b94f9bc6 100755
--- a/swig-interfaces/FXMainWindow.i
+++ b/swig-interfaces/FXMainWindow.i
@@ -20,7 +20,6 @@
  * at "lyle@users.sourceforge.net".
  ***********************************************************************/
 
-
 /**
 * Main application window.  There may be any number of
 * MainWindows in an application.
@@ -36,8 +35,8 @@ protected:
 public:
   %extend {
     /// Construct a main window
-    FXMainWindow(FXApp* a,const FXString& name,FXIcon *ic=NULL,FXIcon *mi=NULL,FXuint opts=DECOR_ALL,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=0,FXint pr=0,FXint pt=0,FXint pb=0,FXint hs=0,FXint vs=0){
-      return new FXRbMainWindow(a,name,ic,mi,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
+    FXMainWindow(FXApp* APP,const FXString& name,FXIcon *ic=NULL,FXIcon *mi=NULL,FXuint opts=DECOR_ALL,FXint x=0,FXint y=0,FXint w=0,FXint h=0,FXint pl=0,FXint pr=0,FXint pt=0,FXint pb=0,FXint hs=0,FXint vs=0){
+      return new FXRbMainWindow(APP,name,ic,mi,opts,x,y,w,h,pl,pr,pt,pb,hs,vs);
       }
     }
 
diff --git a/swig-interfaces/FXMemoryStream.i b/swig-interfaces/FXMemoryStream.i
index cf503ddf32522fe74354fa7ba5cc6d73d2186adb..8f7558e6ae98206fcd1632b8a106964cb8006a7a 100755
--- a/swig-interfaces/FXMemoryStream.i
+++ b/swig-interfaces/FXMemoryStream.i
@@ -36,8 +36,8 @@ public:
       FXuval size=0;
       FXuchar *data=0;
       if(!NIL_P(str)){
-        size=RSTRING(str)->len;
-        data=reinterpret_cast<FXuchar*>(STR2CSTR(str));
+        size=RSTRING_LEN(str);
+        data=reinterpret_cast<FXuchar*>(StringValuePtr(str));
         return self->open(save_or_load,size,data);
         }
       else{
@@ -59,7 +59,7 @@ public:
     void giveBuffer(VALUE str){
       Check_Type(str,T_STRING);
       FXuchar* buffer=reinterpret_cast<FXuchar*>(StringValuePtr(str));
-      FXuval sp=RSTRING(str)->len;
+      FXuval sp=RSTRING_LEN(str);
       self->giveBuffer(buffer,sp);
       }
   }
diff --git a/swig-interfaces/FXMessageBox.i b/swig-interfaces/FXMessageBox.i
index 47c5f31dcb9eca103dbae9b3817d8b62c4235aba..45250b06989bed1bd72724133b9dc532105ef921 100755
--- a/swig-interfaces/FXMessageBox.i
+++ b/swig-interfaces/FXMessageBox.i
@@ -28,10 +28,12 @@ enum {
   MBOX_YES_NO_CANCEL    = 0x40000000,   /// Message box has YES, NO, and CANCEL buttons
   MBOX_QUIT_CANCEL      = 0x50000000,   /// Message box has QUIT and CANCEL buttons
   MBOX_QUIT_SAVE_CANCEL   = 0x60000000, /// Message box has QUIT, SAVE, and CANCEL buttons
-  MBOX_SKIP_SKIPALL_CANCEL  = 0x70000000, /// Message box has SKIP, SKIP ALL, and CANCEL buttons
-  MBOX_SAVE_CANCEL_DONTSAVE = 0x80000000  /// Message box has DON'T SAVE,CANCEL and SAVE buttons
+  MBOX_SKIP_SKIPALL_CANCEL  = 0x70000000 /// Message box has SKIP, SKIP ALL, and CANCEL buttons
   };
 
+/* SWIG doesn't wrap this value correctly without a hint */
+%constant FXuint MBOX_SAVE_CANCEL_DONTSAVE = 0x80000000; // Message box has DON'T SAVE,CANCEL and SAVE buttons
+
 
 // Return values
 enum {
@@ -45,6 +47,8 @@ enum {
   MBOX_CLICKED_SKIPALL  = 8             /// The SKIP ALL button was clicked
   };
 
+/* FOX doesn't define this constant, but we do for consistency */
+%constant MBOX_CLICKED_DONTSAVE = MBOX_CLICKED_NO;
 
 /**
 * A Message Box is a convenience class which provides a dialog for
diff --git a/swig-interfaces/FXPoint.i b/swig-interfaces/FXPoint.i
index a28bcf82117d25e074c5d52acf01bcdf68f67dc3..ad333477d462eb524ee519cdee49d89fbb651acf 100755
--- a/swig-interfaces/FXPoint.i
+++ b/swig-interfaces/FXPoint.i
@@ -28,10 +28,9 @@ public:
 public:
 
   /// Constructors
-  FXPoint();
   FXPoint(const FXSize& s);
   FXPoint(const FXPoint& p);
-  FXPoint(FXshort xx,FXshort yy);
+  FXPoint(FXshort xx=0,FXshort yy=0);
 
   %extend {
     /// Equality
diff --git a/swig-interfaces/FXRanged.i b/swig-interfaces/FXRanged.i
index 9aafeeffb83280bf9a3c81f83c499df7fe78b8ee..5679eb61a7688c69e3eff08d3f6c90b821dbc097 100755
--- a/swig-interfaces/FXRanged.i
+++ b/swig-interfaces/FXRanged.i
@@ -146,6 +146,10 @@ public:
       }
 
     /// Union of two boxes
+    // This is not a typo.
+    // We're calling this method "onion" to work around a bug in SWIG
+    // that mistakes the method name "union" for the C++ keyword of the same
+    // name.
     FXRanged onion(const FXRanged& other) const {
       return FX::unite(*self,other);
       }
diff --git a/swig-interfaces/FXRangef.i b/swig-interfaces/FXRangef.i
index 88059ae5550d596a70b63446972cd1cedf6d54f4..c3fde7692d58f9b5255fdab5992a59d8b9283b34 100755
--- a/swig-interfaces/FXRangef.i
+++ b/swig-interfaces/FXRangef.i
@@ -40,9 +40,6 @@
 
 /// Range
 class FXRangef {
-public:
-  FXVec3f lower;
-  FXVec3f upper;
 public:
 
   // Default constructor
@@ -68,12 +65,21 @@ public:
         }
       return (*self)[i];
       }
+    
     void __setitem__(FXint i,FXVec3f& slice){
       if(i<0||1<i){
         rb_raise(rb_eIndexError,"index %d out of bounds",i);
         }
       (*self)[i]=slice;
       }
+
+    FXVec3f upper() const {
+      return self->upper;
+      }
+
+    FXVec3f lower() const {
+      return self->lower;
+      }
   }
 
   // Width of box
@@ -151,6 +157,8 @@ public:
       }
 
     /// Union of two boxes
+    // This is not a typo. We're calling it "onion" here to work around
+    // a bug in SWIG that thinks "union" is the C++ keyword union.
     FXRangef onion(const FXRangef& other) const {
       return FX::unite(*self,other);
       }
diff --git a/swig-interfaces/FXScintilla.i b/swig-interfaces/FXScintilla.i
index b8963672dd5b993a3de10e6e1e1760dad1147460..cacb74919abc81f811a571c7d799223f43d8c228 100755
--- a/swig-interfaces/FXScintilla.i
+++ b/swig-interfaces/FXScintilla.i
@@ -143,7 +143,7 @@ public:
           wp=static_cast<uptr_t>(NUM2UINT(wParam));
           break;
         case T_STRING:
-          wp=static_cast<uptr_t>(reinterpret_cast<long>(RSTRING(wParam)->ptr));
+          wp=static_cast<uptr_t>(reinterpret_cast<long>(RSTRING_PTR(wParam)));
           break;
         case T_TRUE:
         case T_FALSE:
@@ -161,7 +161,7 @@ public:
           lp=static_cast<sptr_t>(NUM2UINT(lParam));
           break;
         case T_STRING:
-          lp=static_cast<sptr_t>(reinterpret_cast<long>(RSTRING(lParam)->ptr));
+          lp=static_cast<sptr_t>(reinterpret_cast<long>(RSTRING_PTR(lParam)));
           break;
         case T_TRUE:
         case T_FALSE:
diff --git a/swig-interfaces/FXSettings.i b/swig-interfaces/FXSettings.i
index 77e0b7d930bddc980337af16c65ca24a652d3539..a8df6c57e91d4ebfee9740555ec5426a6bf43dd0 100755
--- a/swig-interfaces/FXSettings.i
+++ b/swig-interfaces/FXSettings.i
@@ -26,6 +26,8 @@ class FXStringDict;
 %ignore FXSettings::operator=(const FXSettings& orig);
 %ignore FXSettings::readFormatEntry(const FXchar *section,const FXchar *key,const FXchar *fmt,...);
 %ignore FXSettings::writeFormatEntry(const FXchar *section,const FXchar *key,const FXchar *fmt,...);
+%ignore FXSettings::readBoolEntry(const FXchar *,const FXchar *,FXbool);
+%ignore FXSettings::writeBoolEntry(const FXchar *,const FXchar *,FXbool);
 
 /**
 * The Settings class manages a key-value database.  This is normally used as
diff --git a/swig-interfaces/FXTable.i b/swig-interfaces/FXTable.i
index 97464a33c90ef4c56defbf2e4852acbc02428f87..7cf539b2cc57a9588195c63b9e9f726abab3e1af 100755
--- a/swig-interfaces/FXTable.i
+++ b/swig-interfaces/FXTable.i
@@ -554,52 +554,52 @@ public:
   void fitColumnsToContents(FXint col,FXint nc=1);
 
   /// Change column header
-  void setColumnText(FXint index,const FXString& text);
+  void setColumnText(FXint TABLE_COLUMN_INDEX,const FXString& text);
 
   /// Return text of column header at index
-  FXString getColumnText(FXint index) const;
+  FXString getColumnText(FXint TABLE_COLUMN_INDEX) const;
 
   /// Change row header
-  void setRowText(FXint index,const FXString& text);
+  void setRowText(FXint TABLE_ROW_INDEX,const FXString& text);
 
   /// Return text of row header at index
-  FXString getRowText(FXint index) const;
+  FXString getRowText(FXint TABLE_ROW_INDEX) const;
 
   /// Change column header icon
-  void setColumnIcon(FXint index,FXIcon* icon);
+  void setColumnIcon(FXint TABLE_COLUMN_INDEX,FXIcon* icon);
 
   /// Return icon of column header at index
-  FXIcon* getColumnIcon(FXint index) const;
+  FXIcon* getColumnIcon(FXint TABLE_COLUMN_INDEX) const;
 
   /// Change row header icon
-  void setRowIcon(FXint index,FXIcon* icon);
+  void setRowIcon(FXint TABLE_ROW_INDEX,FXIcon* icon);
 
   /// Return icon of row header at index
-  FXIcon* getRowIcon(FXint index) const;
+  FXIcon* getRowIcon(FXint TABLE_ROW_INDEX) const;
 
   /// Change column header icon position, e.g. FXHeaderItem::BEFORE, etc.
-  void setColumnIconPosition(FXint index,FXuint mode);
+  void setColumnIconPosition(FXint TABLE_COLUMN_INDEX,FXuint mode);
 
   /// Return icon position of column header at index
-  FXuint getColumnIconPosition(FXint index) const;
+  FXuint getColumnIconPosition(FXint TABLE_COLUMN_INDEX) const;
 
   /// Change row header icon position, e.g. FXHeaderItem::BEFORE, etc.
-  void setRowIconPosition(FXint index,FXuint mode);
+  void setRowIconPosition(FXint TABLE_ROW_INDEX,FXuint mode);
 
   /// Return icon position of row header at index
-  FXuint getRowIconPosition(FXint index) const;
+  FXuint getRowIconPosition(FXint TABLE_ROW_INDEX) const;
 
   /// Change column header justify, e.g. FXHeaderItem::RIGHT, etc.
-  void setColumnJustify(FXint index,FXuint justify);
+  void setColumnJustify(FXint TABLE_COLUMN_INDEX,FXuint justify);
 
   /// Return justify of column header at index
-  FXuint getColumnJustify(FXint index) const;
+  FXuint getColumnJustify(FXint TABLE_COLUMN_INDEX) const;
 
   /// Change row header justify, e.g. FXHeaderItem::RIGHT, etc.
-  void setRowJustify(FXint index,FXuint justify);
+  void setRowJustify(FXint TABLE_ROW_INDEX,FXuint justify);
 
   /// Return justify of row header at index
-  FXuint getRowJustify(FXint index) const;
+  FXuint getRowJustify(FXint TABLE_ROW_INDEX) const;
 
   %extend {
     /// Modify cell text
@@ -652,21 +652,19 @@ public:
   %extend {
     /// Extract cells from given range as text.
     VALUE extractText(FXint startrow,FXint endrow,FXint startcol,FXint endcol,const FXchar* cs="\t",const FXchar* rs="\n") const {
-      FXchar* text;
-      FXint size;
+      FXString str;
       VALUE result;
       if(startrow<0 || startcol<0 || self->getNumRows()<=endrow || self->getNumColumns()<=endcol) rb_raise(rb_eIndexError,"index out of bounds");
-      self->extractText(text,size,startrow,endrow,startcol,endcol,cs,rs);
-      result=rb_str_new2(text);
-      FXFREE(&text);
+      self->extractText(str,startrow,endrow,startcol,endcol,cs,rs);
+      result=rb_str_new2(str.text());
       return result;
       }
 
     /// Overlay text over given cell range
     void overlayText(FXint startrow,FXint endrow,FXint startcol,FXint endcol,VALUE str,const FXchar* cs="\t",const FXchar* rs="\n",FXbool notify=FALSE){
       if(startrow<0 || startcol<0 || self->getNumRows()<=endrow || self->getNumColumns()<=endcol) rb_raise(rb_eIndexError,"index out of bounds");
-      const FXchar* text=reinterpret_cast<FXchar*>(STR2CSTR(str));
-      FXint size=RSTRING(str)->len;
+      const FXchar* text=reinterpret_cast<FXchar*>(StringValuePtr(str));
+      FXint size=RSTRING_LEN(str);
       self->overlayText(startrow,endrow,startcol,endcol,text,size,cs,rs,notify);
       }
   }
diff --git a/swig-interfaces/FXText.i b/swig-interfaces/FXText.i
index 0a0d45ee846cf0c598be21b26c8a9c5110fb8bb1..0c3e9963be6b0c77b5a79909b793fb7fbf88f766 100755
--- a/swig-interfaces/FXText.i
+++ b/swig-interfaces/FXText.i
@@ -43,7 +43,20 @@ enum FXTextSelectionMode {
 
 /// Highlight style entry
 struct FXHiliteStyle {
-  FXHiliteStyle();
+  %extend {
+		FXHiliteStyle(){
+			FXHiliteStyle *self = new FXHiliteStyle();
+			self->normalForeColor = 0;
+			self->normalBackColor = 0;
+			self->selectForeColor = 0;
+			self->selectBackColor = 0;
+			self->hiliteForeColor = 0;
+			self->hiliteBackColor = 0;
+			self->activeBackColor = 0;
+			self->style = 0;
+			return self;
+			}
+    }
   FXColor normalForeColor;            /// Normal text foreground color
   FXColor normalBackColor;            /// Normal text background color
   FXColor selectForeColor;            /// Selected text foreground color
@@ -519,29 +532,25 @@ public:
     * both are NULL, internal arrays are used.
     * [This API is still subject to change!!]
     */
-    VALUE findText(const FXString& string,FXint start=0,FXuint flags=SEARCH_FORWARD|SEARCH_WRAP|SEARCH_EXACT,FXint npar=1){
+    VALUE findText(const FXString& string,FXint start=0,FXuint flags=SEARCH_FORWARD|SEARCH_WRAP|SEARCH_EXACT){
       FXint* beg;
       FXint* end;
       VALUE ary=Qnil;
-      
-      if(!FXMALLOC(&beg,FXint,npar)){
+			FXint ngroups=string.contains('(')+1;  // FIXME: is this right?
+      if(!FXMALLOC(&beg,FXint,ngroups)){
         return Qnil;
-	}
-	
-      if(!FXMALLOC(&end,FXint,npar)){
+				}
+      if(!FXMALLOC(&end,FXint,ngroups)){
         FXFREE(&beg);
-	return Qnil;
-	}
-	
-      if(self->findText(string,beg,end,start,flags,npar)){
+				return Qnil;
+				}
+      if(self->findText(string,beg,end,start,flags,ngroups)){
         ary=rb_ary_new();
-	rb_ary_push(ary,FXRbMakeArray(beg,npar));
-	rb_ary_push(ary,FXRbMakeArray(end,npar));
+				rb_ary_push(ary,FXRbMakeArray(beg,ngroups));
+				rb_ary_push(ary,FXRbMakeArray(end,ngroups));
         }
-	
       FXFREE(&beg);
       FXFREE(&end);
-      
       return ary;
       }
   }
@@ -706,7 +715,7 @@ public:
 	  delete [] text->styles;
 	  text->numStyles=0;
 	  }
-	text->numStyles=RARRAY(styles)->len;
+	text->numStyles=RARRAY_LEN(styles);
 	if(text->numStyles>0){
           text->styles=new FXHiliteStyle[text->numStyles];
           for (long i=0; i<text->numStyles; i++){
diff --git a/swig-interfaces/FXVec2d.i b/swig-interfaces/FXVec2d.i
index 3b296727be9a9c1fb451c3d3eb5988d9899d3b9e..25447940b1e151b192af22752656acf8a9ea7568 100755
--- a/swig-interfaces/FXVec2d.i
+++ b/swig-interfaces/FXVec2d.i
@@ -27,15 +27,12 @@ public:
   FXdouble y;
 public:
 
-  /// Default constructor
-  FXVec2d();
+	/// Initialize with components
+	FXVec2d(FXdouble xx=0.0,FXdouble yy=0.0);
 
   /// Copy constructor
   FXVec2d(const FXVec2d& v);
 
-  /// Initialize with components
-  FXVec2d(FXdouble xx,FXdouble yy);
-
   /// Length and square of length
   FXdouble length2() const;
   FXdouble length() const;
diff --git a/swig-interfaces/FXVec2f.i b/swig-interfaces/FXVec2f.i
index b590a5e5dafddf40045046c0024ffcb918522a52..173bbcca34ab268790cae23111d2dc4377214ff6 100755
--- a/swig-interfaces/FXVec2f.i
+++ b/swig-interfaces/FXVec2f.i
@@ -27,8 +27,8 @@ public:
   FXfloat y;
 public:
 
-  /// Default constructor
-  FXVec2f();
+	/// Initialize with components
+	FXVec2f(FXfloat xx=0.0f,FXfloat yy=0.0f);
 
   /// Copy constructor
   FXVec2f(const FXVec2f& v);
@@ -36,9 +36,6 @@ public:
   // Initialize from array of floats
   FXVec2f(const FXfloat v[]);
 
-  /// Initialize with components
-  FXVec2f(FXfloat xx,FXfloat yy);
-
   /// Length and square of length
   FXfloat length2() const;
   FXfloat length() const;
diff --git a/swig-interfaces/FXVec3d.i b/swig-interfaces/FXVec3d.i
index 0ac564bbe938be10e3b829bf9d3abea929672409..61d78e6a3839bf33f9bb57720622856509a6706d 100755
--- a/swig-interfaces/FXVec3d.i
+++ b/swig-interfaces/FXVec3d.i
@@ -29,7 +29,11 @@ public:
 public:
 
   /// Default constructor
-  FXVec3d();
+  %extend {
+		FXVec3d() {
+			return new FXVec3d(0.0, 0.0, 0.0);
+		}
+	}
 
   /// Copy constructor
   FXVec3d(const FXVec3d& v);
diff --git a/swig-interfaces/FXVec3f.i b/swig-interfaces/FXVec3f.i
index 86ce4922f30a897ee03b16fa55557da1c8a6aa1d..f32b33d570c7d6f5e51895bb10db189c7a60b6e6 100755
--- a/swig-interfaces/FXVec3f.i
+++ b/swig-interfaces/FXVec3f.i
@@ -29,7 +29,11 @@ public:
 public:
 
   /// Default constructor
-  FXVec3f();
+  %extend {
+		FXVec3f() {
+			return new FXVec3f(0.0f, 0.0f, 0.0f);
+		}
+	}
 
   /// Copy constructor
   FXVec3f(const FXVec3f& v);
diff --git a/swig-interfaces/FXVec4d.i b/swig-interfaces/FXVec4d.i
index 7882ffee860a640a1a22347c5e28fd6d2e36c960..ff3560fe128df4a629a0aed10e9b48e6d787c8f3 100755
--- a/swig-interfaces/FXVec4d.i
+++ b/swig-interfaces/FXVec4d.i
@@ -32,7 +32,11 @@ public:
 public:
 
   /// Default constructor
-  FXVec4d();
+  %extend {
+		FXVec4d() {
+			return new FXVec4d(0.0, 0.0, 0.0, 0.0);
+		}
+	}
 
   /// Copy constructor
   FXVec4d(const FXVec4d& v);
diff --git a/swig-interfaces/FXVec4f.i b/swig-interfaces/FXVec4f.i
index 0eeaa66af5cbbe8224a6077041ff9cb45c4ee8d0..2ba700a3610bff04deb8c38edde2caf006a6c14d 100755
--- a/swig-interfaces/FXVec4f.i
+++ b/swig-interfaces/FXVec4f.i
@@ -32,7 +32,11 @@ public:
 public:
 
   /// Default constructor
-  FXVec4f();
+  %extend {
+		FXVec4f() {
+			return new FXVec4f(0.0f, 0.0f, 0.0f, 0.0f);
+		}
+	}
 
   /// Copy constructor
   FXVec4f(const FXVec4f& w);
diff --git a/swig-interfaces/FXWindow.i b/swig-interfaces/FXWindow.i
index 28aad47a41b5ab5db9f3fd32b72a8308d96ff50d..5f2462100804631bb00da1d8e2b9b6a91e27c800 100755
--- a/swig-interfaces/FXWindow.i
+++ b/swig-interfaces/FXWindow.i
@@ -595,7 +595,7 @@ public:
     bool acquireSelection(VALUE typesArray){
       Check_Type(typesArray,T_ARRAY);
       FXDragType *types=0;
-      FXuint numtypes=RARRAY(typesArray)->len;
+      FXuint numtypes=RARRAY_LEN(typesArray);
       if(numtypes>0){
         types=new FXDragType[numtypes];
         for(FXuint i=0;i<numtypes;i++){
@@ -619,7 +619,7 @@ public:
     bool acquireClipboard(VALUE typesArray){
       Check_Type(typesArray,T_ARRAY);
       FXDragType *types=0;
-      FXuint numtypes=RARRAY(typesArray)->len;
+      FXuint numtypes=RARRAY_LEN(typesArray);
       if(numtypes>0){
         types=new FXDragType[numtypes];
         for(FXuint i=0;i<numtypes;i++){
@@ -646,7 +646,7 @@ public:
     bool beginDrag(VALUE typesArray){
       Check_Type(typesArray,T_ARRAY);
       FXDragType *types=0;
-      FXuint numtypes=RARRAY(typesArray)->len;
+      FXuint numtypes=RARRAY_LEN(typesArray);
       if(numtypes>0){
         types=new FXDragType[numtypes];
         for(FXuint i=0;i<numtypes;i++){
@@ -728,9 +728,9 @@ public:
     void setDNDData(FXDNDOrigin origin, FXDragType type, VALUE str) const {
       Check_Type(str, T_STRING);
       FXuchar* data;
-      FXuint size = RSTRING(str)->len;
+      FXuint size = RSTRING_LEN(str);
       if (FXMALLOC(&data, FXuchar, size)) {
-        memcpy((void *) data, (void *) RSTRING(str)->ptr, size);
+        memcpy((void *) data, (void *) RSTRING_PTR(str), size);
         self->setDNDData(origin, type, data, size);
       } else {
         rb_raise(rb_eNoMemError, "couldn't copy drag-and-drop data");
diff --git a/swig-interfaces/FXXPMIcon.i b/swig-interfaces/FXXPMIcon.i
index cc29a0439705cd692a50d7a1aec2a631452da296..e648f466cf91a6ab56d29b4c004cc82bc32630fa 100755
--- a/swig-interfaces/FXXPMIcon.i
+++ b/swig-interfaces/FXXPMIcon.i
@@ -86,7 +86,7 @@ DECLARE_FXIMAGE_VIRTUALS(FXXPMIcon)
     
     // Confirm that the input is an array of strings
     Check_Type(strArray,T_ARRAY);
-    len=RARRAY(strArray)->len;
+    len=RARRAY_LEN(strArray);
     for(i=0; i<len; i++){
       str=rb_ary_entry(strArray,i);
       Check_Type(str,T_STRING);
diff --git a/swig-interfaces/Makefile b/swig-interfaces/Makefile
index ee28aaec27d2122a4135073bc92fa3a72e840a5d..a989672c619b91b05bfe437436af2a63bf5937a9 100755
--- a/swig-interfaces/Makefile
+++ b/swig-interfaces/Makefile
@@ -2,17 +2,17 @@
 # This makefile is used to generate the wrapper code from the
 # SWIG interface files.
 #
-# $Id: Makefile 2300 2005-12-07 14:05:03Z lyle $
+# $Id: Makefile 2827 2008-03-28 16:04:44Z lyle $
 #
 
 .PHONY: clean
 
-SWIG = swig
+SWIG = /usr/local/bin/swig
 SWIGFLAGS = -fcompact -noruntime -c++ -ruby -no_default -I../fox-includes
 SRCDIR = ../ext/fox16
 SED = sed -f swig.sed
 RUBY = ruby
-SWIGLIB := $(shell swig -swiglib)
+SWIGLIB := $(shell /usr/local/bin/swig -swiglib)
 
 MODULES = \
 	$(SRCDIR)/core_wrap.cpp \
diff --git a/swig-interfaces/macros.i b/swig-interfaces/macros.i
index 4d251bd558a47f043b373f5998f2c009223b7398..aacc3ff465adafe4593c1ad3eaa3c8bc504f141e 100755
--- a/swig-interfaces/macros.i
+++ b/swig-interfaces/macros.i
@@ -433,8 +433,8 @@
     /// See if font has glyph for ch
     virtual FXbool hasChar(VALUE ch) const {
       if(TYPE(ch)==T_STRING){
-        if(RSTRING(ch)->len==1){
-          return self->hasChar(*(STR2CSTR(ch))); // FIXME: hasChar() expects an FXwchar
+        if(RSTRING_LEN(ch)==1){
+          return self->hasChar(*(StringValuePtr(ch))); // FIXME: hasChar() expects an FXwchar
 	  }
 	else{
 	  rb_raise(rb_eArgError,"expected a string of length one");
@@ -708,7 +708,7 @@
 %extend klass {
   /**
   * Retrieves pixels from the server-side image.  For example, to make
-  * screen snapshots, or to retrieve an image after it has been drawin
+  * screen snapshots, or to retrieve an image after it has been drawn
   * into by various means.
   */
   virtual void restore();
diff --git a/swig-interfaces/ruby-typemaps.i b/swig-interfaces/ruby-typemaps.i
index 61ae7237b295ead8830a83a2f3025f87031e0658..a059b04df179396a4927131ca53a32a4dcef2dfa 100755
--- a/swig-interfaces/ruby-typemaps.i
+++ b/swig-interfaces/ruby-typemaps.i
@@ -20,9 +20,13 @@
  * at "lyle@users.sourceforge.net".
  ***********************************************************************/
 
-/***********************************************************************
- * $Id: ruby-typemaps.i 2460 2006-07-09 23:38:59Z lyle $
- ***********************************************************************/
+%include constraints.i
+
+%apply Pointer NONNULL {
+  FXApp* APP,
+	FXComposite* PARENT,
+	FXWindow* OWNER
+}
 
 /* Type-checking rules */
 %typecheck(SWIG_TYPECHECK_STRING) const FXString&, FXuchar *data {
@@ -61,7 +65,7 @@ inline FXColor to_FXColor(VALUE obj){
 inline FXString to_FXString(VALUE obj){
   if(!NIL_P(obj)){
     Check_Type(obj,T_STRING);
-    return FXString(STR2CSTR(obj));
+    return FXString(StringValuePtr(obj));
     }
   else{
     return FXString::null;
@@ -112,7 +116,7 @@ inline FXbool to_FXbool(VALUE obj){
 %typemap(in) const void* pix {
   if ($input != Qnil) {
     Check_Type($input, T_STRING);
-    $1 = reinterpret_cast<$1_ltype>(RSTRING($input)->ptr);
+    $1 = reinterpret_cast<$1_ltype>(RSTRING_PTR($input));
   } else {
     $1 = NULL;
   }
@@ -127,8 +131,8 @@ inline FXbool to_FXbool(VALUE obj){
   $1=NULL;
   if($input!=Qnil){
     Check_Type($input,T_ARRAY);
-    if(FXMALLOC(&$1,FXColor,RARRAY($input)->len)){
-      for(long i=0; i<RARRAY($input)->len; i++){
+    if(FXMALLOC(&$1,FXColor,RARRAY_LEN($input))){
+      for(long i=0; i<RARRAY_LEN($input); i++){
         $1[i]=static_cast<FXColor>(NUM2UINT(rb_ary_entry($input,i)));
 	}
       }
@@ -149,9 +153,10 @@ inline FXbool to_FXbool(VALUE obj){
   $1 = NULL;
   if ($input != Qnil) {
     Check_Type($input, T_ARRAY);
-    if (FXMALLOC(&$1, FXchar *, RARRAY($input)->len)) {
-      for (long i = 0; i < RARRAY($input)->len; i++) {
-        $1[i] = (FXchar *) STR2CSTR(rb_ary_entry($input, i));
+    if (FXMALLOC(&$1, FXchar *, RARRAY_LEN($input))) {
+      for (long i = 0; i < RARRAY_LEN($input); i++) {
+        VALUE e = rb_ary_entry($input, i);
+        $1[i] = (FXchar *) StringValuePtr(e);
       }
     }
   }
@@ -166,7 +171,7 @@ inline FXbool to_FXbool(VALUE obj){
 %typecheck(SWIG_TYPECHECK_STRING_ARRAY) const FXchar** strings {
   $1 = (TYPE($input) == T_ARRAY) ? 1 : 0;
   if ($1 != 0) {
-    for (long i = 0; i < RARRAY($input)->len; i++) {
+    for (long i = 0; i < RARRAY_LEN($input); i++) {
       if (TYPE(rb_ary_entry($input, i)) != T_STRING) {
         $1 = 0;
 	break;
@@ -179,11 +184,12 @@ inline FXbool to_FXbool(VALUE obj){
   $1 = NULL;
   if(!NIL_P($input)){
     Check_Type($input, T_ARRAY);
-    if (FXMALLOC(&$1, FXchar *, RARRAY($input)->len)+1) {
-      for (long i = 0; i < RARRAY($input)->len; i++) {
-        $1[i] = (FXchar *) STR2CSTR(rb_ary_entry($input, i));
+    if (FXMALLOC(&$1, FXchar *, RARRAY_LEN($input))+1) {
+      for (long i = 0; i < RARRAY_LEN($input); i++) {
+        VALUE e = rb_ary_entry($input, i);
+        $1[i] = (FXchar *) StringValuePtr(e);
       }
-      $1[RARRAY($input)->len] = 0;
+      $1[RARRAY_LEN($input)] = 0;
     }
   }
 }
@@ -195,11 +201,11 @@ inline FXbool to_FXbool(VALUE obj){
   $1 = NULL;
   if(!NIL_P($input)){
     Check_Type($input, T_ARRAY);
-    if (FXMALLOC(&$1, FXColor, RARRAY($input)->len)+1) {
-      for (long i = 0; i < RARRAY($input)->len; i++) {
+    if (FXMALLOC(&$1, FXColor, RARRAY_LEN($input))+1) {
+      for (long i = 0; i < RARRAY_LEN($input); i++) {
         $1[i] = static_cast<FXColor>(NUM2ULONG(rb_ary_entry($input, i)));
       }
-      $1[RARRAY($input)->len] = 0;
+      $1[RARRAY_LEN($input)] = 0;
     }
   }
 }
@@ -231,7 +237,7 @@ inline void* to_FXEvent(VALUE obj){
 %typemap(in) void* PTR_COLOR "$1 = reinterpret_cast<void*>(NUM2UINT($input));";
 
 /* Convert a Ruby string to a C string */
-%typemap(in) void* PTR_CSTRING "$1 = static_cast<void*>(STR2CSTR($input));";
+%typemap(in) void* PTR_CSTRING "$1 = static_cast<void*>(StringValuePtr($input));";
 
 /* Convert a Ruby array (of size 2) into an FXdouble array */
 %typemap(in) void* PTR_DBLRANGE_IN(FXdouble values[2]) {
@@ -320,7 +326,7 @@ inline void* to_FXEvent(VALUE obj){
 
 /* Convert a Ruby string to a pointer to an FXString */
 %typemap(in) void* PTR_STRING(FXString value) {
-  value = FXString(STR2CSTR($input));
+  value = FXString(StringValuePtr($input));
   $1 = (void *) &value;
 }
 
@@ -456,6 +462,14 @@ inline void* to_FXEvent(VALUE obj){
 }
 %typemap(out) FXMat4f& "$result = FXRbGetRubyObj($1, \"$1_ltype\");";
 
+/* Output typemap for FXVec2d instances */
+%typemap(out) FXVec2d* "$result = FXRbGetRubyObj($1, \"$1_ltype\");";
+%typemap(out) FXVec2d& "$result = FXRbGetRubyObj($1, \"$1_ltype\");";
+
+/* Output typemap for FXVec2f instances */
+%typemap(out) FXVec2f* "$result = FXRbGetRubyObj($1, \"$1_ltype\");";
+%typemap(out) FXVec2f& "$result = FXRbGetRubyObj($1, \"$1_ltype\");";
+
 /* Output typemap for FXVec4f instances */
 %typemap(out) FXVec4f {
     FXVec4f* resultptr = new FXVec4f($1);
@@ -604,8 +618,8 @@ inline void* to_FXEvent(VALUE obj){
 }
 %typemap(in) (const FXPoint* points, FXuint npoints) {
     Check_Type($input, T_ARRAY);
-    $1 = new FXPoint[RARRAY($input)->len];
-    $2 = static_cast<FXuint>( RARRAY($input)->len );
+    $1 = new FXPoint[RARRAY_LEN($input)];
+    $2 = static_cast<FXuint>( RARRAY_LEN($input) );
     for (FXuint i = 0; i < $2; i++) {
         FXPoint *pPoint;
         Data_Get_Struct(rb_ary_entry($input, i), FXPoint, pPoint);
@@ -619,8 +633,8 @@ inline void* to_FXEvent(VALUE obj){
 // Extract a C array (segments) and its length (nsegments) from a Ruby array of FXSegment instances
 %typemap(in) (const FXSegment* segments, FXuint nsegments) {
     Check_Type($input, T_ARRAY);
-    $1 = new FXSegment[RARRAY($input)->len];
-    $2 = static_cast<FXuint>( RARRAY($input)->len );
+    $1 = new FXSegment[RARRAY_LEN($input)];
+    $2 = static_cast<FXuint>( RARRAY_LEN($input) );
     for (FXuint i = 0; i < $2; i++) {
         FXSegment *pSeg;
         Data_Get_Struct(rb_ary_entry($input, i), FXSegment, pSeg);
@@ -635,8 +649,8 @@ inline void* to_FXEvent(VALUE obj){
 // Extract a C array (rectangles) and its length (nrectangles) from a Ruby array of FXRectangle instances
 %typemap(in) (const FXRectangle* rectangles, FXuint nrectangles) {
     Check_Type($input, T_ARRAY);
-    $1 = new FXRectangle[RARRAY($input)->len];
-    $2 = static_cast<FXuint>( RARRAY($input)->len );
+    $1 = new FXRectangle[RARRAY_LEN($input)];
+    $2 = static_cast<FXuint>( RARRAY_LEN($input) );
     for (FXuint i = 0; i < $2; i++) {
         FXRectangle *pRect;
         Data_Get_Struct(rb_ary_entry($input, i), FXRectangle, pRect);
@@ -651,8 +665,8 @@ inline void* to_FXEvent(VALUE obj){
 // Extract a C array (arcs) and its length (narcs) from a Ruby array of FXArc instances
 %typemap(in) (const FXArc* arcs, FXuint narcs) {
     Check_Type($input, T_ARRAY);
-    $1 = new FXArc[RARRAY($input)->len];
-    $2 = static_cast<FXuint>( RARRAY($input)->len );
+    $1 = new FXArc[RARRAY_LEN($input)];
+    $2 = static_cast<FXuint>( RARRAY_LEN($input) );
     for (FXuint i = 0; i < $2; i++) {
         FXArc *pArc;
         Data_Get_Struct(rb_ary_entry($input, i), FXArc, pArc);
@@ -667,15 +681,15 @@ inline void* to_FXEvent(VALUE obj){
 // Extract the C string pointer and string length from a Ruby string
 %typemap(in) (const FXchar* string, FXuint length) {
     Check_Type($input, T_STRING);
-    $1 = STR2CSTR($input);
-    $2 = RSTRING($input)->len;
+    $1 = StringValuePtr($input);
+    $2 = RSTRING_LEN($input);
 }
 
 // Extract a C array (dashpattern) and its length (dashlength) from a Ruby array of Fixnums
 %typemap(in) (const FXchar* dashpattern, FXuint dashlength) {
     Check_Type($input, T_ARRAY);
-    $1 = new FXchar[RARRAY($input)->len];
-    $2 = static_cast<FXuint>( RARRAY($input)->len );
+    $1 = new FXchar[RARRAY_LEN($input)];
+    $2 = static_cast<FXuint>( RARRAY_LEN($input) );
     for (FXuint i = 0; i < $2; i++) {
         $1[i] = NUM2INT(rb_ary_entry($input, i));
     }
@@ -687,8 +701,8 @@ inline void* to_FXEvent(VALUE obj){
 
 %typemap(in) (FXuint* path, FXint n) {
   Check_Type($input, T_ARRAY);
-  FXMALLOC(&$1,FXuint,RARRAY($input)->len);
-  $2=static_cast<FXint>(RARRAY($input)->len);
+  FXMALLOC(&$1,FXuint,RARRAY_LEN($input));
+  $2=static_cast<FXint>(RARRAY_LEN($input));
   for(FXint i=0; i<$2; i++){
     $1[i]=NUM2UINT(rb_ary_entry($input,i));
     }
@@ -701,8 +715,8 @@ inline void* to_FXEvent(VALUE obj){
 /* Convert an array of FXColor values (see constructor for FXMemoryBuffer) */
 %typemap(in) (FXColor *data,FXuint size) {
   Check_Type($input, T_ARRAY);
-  FXMALLOC(&$1,FXColor,RARRAY($input)->len);
-  $2=static_cast<FXuint>(RARRAY($input)->len);
+  FXMALLOC(&$1,FXColor,RARRAY_LEN($input));
+  $2=static_cast<FXuint>(RARRAY_LEN($input));
   for(FXint i=0; i<$2; i++){
     $1[i]=static_cast<FXColor>(NUM2UINT(rb_ary_entry($input,i)));
     }
@@ -746,7 +760,7 @@ inline void* to_FXEvent(VALUE obj){
 /* Convert an FXID to a Ruby Integer (fxid_to_int() is defined in FXRuby.h) */
 %typemap(out) FXID "$result = fxid_to_int($1);";
 
-%typemap(in) FXuchar *data "$1 = NIL_P($input) ? 0 : reinterpret_cast<FXuchar*>(STR2CSTR($input));";
+%typemap(in) FXuchar *data "$1 = NIL_P($input) ? 0 : reinterpret_cast<FXuchar*>(StringValuePtr($input));";
 
 // FXlong values
 %typemap(in)  FXlong "$1 = static_cast<FXlong>(NUM2LONG($input));";
diff --git a/tests/TC_FXApp.rb b/tests/TC_FXApp.rb
index a21747c00743080b449f57d6864383b98d4ffaa1..3c706ece54732c8e4944e2b5392c7ecd811eece7 100755
--- a/tests/TC_FXApp.rb
+++ b/tests/TC_FXApp.rb
@@ -1,15 +1,16 @@
 require 'test/unit'
 require 'fox16'
-require 'testcase'
 
 include Fox
 
-class TC_FXApp < TestCase
-  def setup
-    super(self.class.name)
-  end
-  def test_initialized
-    assert(app.initialized?)
+class TC_FXApp < Test::Unit::TestCase
+  def test_exception_for_second_app
+    app = FXApp.new
+    mainWindow = FXMainWindow.new(app, "")
+    app.create
+    assert_raise RuntimeError do
+      app2 = FXApp.new
+    end
   end
 end
 
diff --git a/tests/TC_FXButton.rb b/tests/TC_FXButton.rb
index cc80bd8a4a7792d446fd29a3a559d41e117f3203..ac4484fd724d87531caa6730dcb294a0402a965d 100755
--- a/tests/TC_FXButton.rb
+++ b/tests/TC_FXButton.rb
@@ -69,4 +69,10 @@ class TC_FXButton < TestCase
     @button.state = STATE_UNCHECKED
     assert_equal(STATE_UNCHECKED, @button.state)
   end
+
+  def test_create_for_non_created_parent_window_raises_runtime_error
+    assert_raise RuntimeError do
+      @button.create
+    end
+  end
 end
diff --git a/tests/TC_FXComboBox.rb b/tests/TC_FXComboBox.rb
index 6c2ac898ad9394166ad3540aba48c4d98cf915e2..faaf6aebbd5ce6972a6357cb0fa75768d2a6bf33 100755
--- a/tests/TC_FXComboBox.rb
+++ b/tests/TC_FXComboBox.rb
@@ -48,5 +48,16 @@ class TC_FXComboBox < TestCase
     end
   end
 
+  def test_fill_items_returns_num_items_added
+    assert_equal(3, @comboBox.fillItems(%w{one two three}))
+  end
+
+  def test_fill_items
+    @comboBox.fillItems(%w{one two three})
+    items = @comboBox.map { |text, data| text }
+    assert_equal("one", items[0])
+    assert_equal("two", items[1])
+    assert_equal("three", items[2])
+  end
 end
 
diff --git a/tests/TC_FXDC.rb b/tests/TC_FXDC.rb
index bb7a3d748f2e1ee6a2d6c1125947746e8f344f1f..e4d25c3d7292307ce71f12995f96c002ef064d2b 100755
--- a/tests/TC_FXDC.rb
+++ b/tests/TC_FXDC.rb
@@ -79,7 +79,7 @@ class TC_FXDC < Test::Unit::TestCase
     @dc.fillRectangle(x, y, w, h)
   end
   
-  def testFillRectangles(rectangles)
+  def testFillRectangles
     rectangles = [ FXRectangle.new, FXRectangle.new ]
     @dc.fillRectangles(rectangles)
   end
diff --git a/tests/TC_FXDCPrint.rb b/tests/TC_FXDCPrint.rb
index 96907f8f89253ee8c420efa72d2d1fb591682329..c06fa52cdf0c86f3dba80ef9f072c9488a2cf83e 100755
--- a/tests/TC_FXDCPrint.rb
+++ b/tests/TC_FXDCPrint.rb
@@ -1,7 +1,6 @@
 require 'test/unit'
 
 require 'fox16'
-require 'ftools'
 
 include Fox
 
@@ -64,14 +63,14 @@ public
   def test_beginPrint
     @dc.beginPrint(printJob)
     @dc.endPrint
-    assert_same_file_contents("blankpage.ps", printJob.name)
+    assert_same_file_contents(File.join(File.dirname(__FILE__), "blankpage.ps"), printJob.name)
   end
 
   def test_beginPrint_with_block
     @dc.beginPrint(printJob) do |theDC|
       assert_same(@dc, theDC)
     end
-    assert_same_file_contents("blankpage.ps", printJob.name)
+    assert_same_file_contents(File.join(File.dirname(__FILE__), "blankpage.ps"), printJob.name)
   end
 
   def test_beginPage
@@ -96,7 +95,7 @@ public
   
   def teardown
     if File.exists?("output.ps")
-      File.rm_f("output.ps")
+      FileUtils.rm_f("output.ps")
     end
   end
 end
diff --git a/tests/TC_FXDialogBox.rb b/tests/TC_FXDialogBox.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e65bee693860732fc935d62adeb3a100524975f2
--- /dev/null
+++ b/tests/TC_FXDialogBox.rb
@@ -0,0 +1,12 @@
+require 'test/unit'
+require 'fox16'
+
+include Fox
+
+class TC_FXDialogBox < Test::Unit::TestCase
+  def test_nil_app_raises_argument_error
+    assert_raise ArgumentError do
+      FXDialogBox.new(nil, "title")
+    end
+  end
+end
\ No newline at end of file
diff --git a/tests/TC_FXExtentd.rb b/tests/TC_FXExtentd.rb
new file mode 100755
index 0000000000000000000000000000000000000000..64d37b0fd87111f0c230695df0533154cf380aba
--- /dev/null
+++ b/tests/TC_FXExtentd.rb
@@ -0,0 +1,21 @@
+require 'test/unit'
+require 'fox16'
+
+include Fox
+
+class TC_FXExtentd < Test::Unit::TestCase
+  def test_lower_always_returns_same_instance
+    e = FXExtentd.new(0, 1, 0, 1)
+    assert_same e.lower, e.lower
+  end
+  
+  def test_upper_always_returns_same_instance
+    e = FXExtentd.new(0, 1, 0, 1)
+    assert_same e.upper, e.upper
+  end
+  
+  def test_index_always_returns_same_instance
+    e = FXExtentd.new(0, 1, 0, 1)
+    assert_same e[0], e[0]
+  end
+end
diff --git a/tests/TC_FXExtentf.rb b/tests/TC_FXExtentf.rb
new file mode 100755
index 0000000000000000000000000000000000000000..87a0db656f112a7ffb10d6e727693e6fb3fe9400
--- /dev/null
+++ b/tests/TC_FXExtentf.rb
@@ -0,0 +1,21 @@
+require 'test/unit'
+require 'fox16'
+
+include Fox
+
+class TC_FXExtentf < Test::Unit::TestCase
+  def test_lower_always_returns_same_instance
+    e = FXExtentf.new(0, 1, 0, 1)
+    assert_same e.lower, e.lower
+  end
+  
+  def test_upper_always_returns_same_instance
+    e = FXExtentf.new(0, 1, 0, 1)
+    assert_same e.upper, e.upper
+  end
+  
+  def test_index_always_returns_same_instance
+    e = FXExtentf.new(0, 1, 0, 1)
+    assert_same e[0], e[0]
+  end
+end
diff --git a/tests/TC_FXFileStream.rb b/tests/TC_FXFileStream.rb
index d331a88d5cc6ae18d4d300e172da8191da5a62d2..22c94883a107acd4ea45a5cd17245f7c55b333b2 100755
--- a/tests/TC_FXFileStream.rb
+++ b/tests/TC_FXFileStream.rb
@@ -1,6 +1,5 @@
 require 'test/unit'
 require 'fox16'
-require 'ftools'
 require 'tempfile'
 
 include Fox
@@ -84,7 +83,7 @@ class TC_FXFileStream < Test::Unit::TestCase
   
   def teardown
     if File.exists?("goobers")
-      File.rm_f("goobers")
+      FileUtils.rm_f("goobers")
     end
   end
 end
diff --git a/tests/TC_FXFoldingList.rb b/tests/TC_FXFoldingList.rb
new file mode 100755
index 0000000000000000000000000000000000000000..056c2b019b928167ae9724f81a38a3b1f8d01b1a
--- /dev/null
+++ b/tests/TC_FXFoldingList.rb
@@ -0,0 +1,32 @@
+require 'test/unit'
+require 'testcase'
+require 'fox16'
+
+include Fox
+
+class TC_FXFoldingList < TestCase
+  
+  def setup
+    super(self.class.name)
+    @foldingList = FXFoldingList.new(mainWindow)
+  end
+
+  def test_each_for_empty_list
+    count = 0
+    @foldingList.each { |item| count += 1 }
+    assert_equal(0, count, "count for empty list should be zero")
+  end
+  
+  def test_each
+    @foldingList.appendItem(nil, "1")
+    @foldingList.appendItem(nil, "2")
+    @foldingList.appendItem(nil, "3")
+    @foldingList.appendItem(nil, "4")
+    @foldingList.appendItem(nil, "5")
+    count = 0
+    @foldingList.each { |item| count += 1 }
+    assert_equal(5, count, "count didn't match expected number of items")
+  end
+  
+end
+
diff --git a/tests/TC_FXHiliteStyle.rb b/tests/TC_FXHiliteStyle.rb
new file mode 100755
index 0000000000000000000000000000000000000000..35fe085c5e28c732af66d6588d3ddc0aff000382
--- /dev/null
+++ b/tests/TC_FXHiliteStyle.rb
@@ -0,0 +1,23 @@
+require 'fox16'
+require 'test/unit'
+
+include Fox
+
+class TC_FXHiliteStyle < Test::Unit::TestCase
+
+  def setup
+    @style = FXHiliteStyle.new
+  end
+
+  def test_new_object_is_initialized
+    assert_equal(0, @style.normalForeColor)
+    assert_equal(0, @style.normalBackColor)
+    assert_equal(0, @style.selectForeColor)
+    assert_equal(0, @style.selectBackColor)
+    assert_equal(0, @style.hiliteForeColor)
+    assert_equal(0, @style.hiliteBackColor)
+    assert_equal(0, @style.activeBackColor)
+    assert_equal(0, @style.style)
+  end
+end
+
diff --git a/tests/TC_FXId.rb b/tests/TC_FXId.rb
index a6f4d4dacd9682ff1f2fbd17eed74ed860aca580..fae3391d39683ae1d7c408a368c6e01e553c95f3 100755
--- a/tests/TC_FXId.rb
+++ b/tests/TC_FXId.rb
@@ -10,10 +10,10 @@ class TC_FXId < TestCase
   end
 
   def test_created?
-    assert(!mainWindow.created?)
+    assert !mainWindow.created?
     app.create
-    assert(mainWindow.created?)
+    assert mainWindow.created?, "main window should be created after call to FXApp#create"
     mainWindow.destroy
-    assert(!mainWindow.created?)
+    assert !mainWindow.created?
   end
 end
diff --git a/tests/TC_FXMainWindow.rb b/tests/TC_FXMainWindow.rb
new file mode 100644
index 0000000000000000000000000000000000000000..aa88b1d7a98f1ba957e4717d667e2195c537f242
--- /dev/null
+++ b/tests/TC_FXMainWindow.rb
@@ -0,0 +1,19 @@
+require 'test/unit'
+require 'fox16'
+
+include Fox
+
+class TC_FXMainWindow < Test::Unit::TestCase
+  def test_nil_app_raises_argument_error
+    assert_raise ArgumentError do
+      FXMainWindow.new(nil, "title")
+    end
+  end
+  
+  def test_non_created_app_raises_runtime_error
+    app = FXApp.new
+    assert_raise RuntimeError do
+      FXMainWindow.new(app, "title").create
+    end
+  end
+end
\ No newline at end of file
diff --git a/tests/TC_FXMessageBox.rb b/tests/TC_FXMessageBox.rb
new file mode 100755
index 0000000000000000000000000000000000000000..f926d29a66f7ee0253dff79f6bf773b067f4586e
--- /dev/null
+++ b/tests/TC_FXMessageBox.rb
@@ -0,0 +1,25 @@
+require 'test/unit'
+require 'testcase'
+require 'fox16'
+
+include Fox
+
+class TC_FXMessageBox < TestCase
+  def setup
+    super(self.class.name)
+  end
+  
+  def test_construct_with_save_cancel_dontsave
+    assert_nothing_raised(RangeError) do
+      FXMessageBox.new(mainWindow, "Save?", "Save?", :opts => MBOX_SAVE_CANCEL_DONTSAVE)
+    end
+  end
+  
+  def test_mbox_clicked_dontsave_defined
+    assert(Fox.const_defined?(:MBOX_CLICKED_DONTSAVE))
+  end
+  
+  def test_mbox_clicked_dontsave_equal_to_mbox_clicked_no
+    assert_equal(MBOX_CLICKED_NO, MBOX_CLICKED_DONTSAVE)
+  end
+end
diff --git a/tests/TC_FXQuatf.rb b/tests/TC_FXQuatf.rb
index c9b99e0800e9960bc017af1d766e7044c57412d7..d2a5b62c4790bf40eac6c7bd176c70b4810c7693 100755
--- a/tests/TC_FXQuatf.rb
+++ b/tests/TC_FXQuatf.rb
@@ -7,67 +7,83 @@ class TC_FXQuatf < Test::Unit::TestCase
   def setup
     @quat = FXQuatf.new
   end
+
   def test_default_constructor
     q = FXQuatf.new
   end
+
   def test_construct_from_axis_and_angle
     axis = FXVec3f.new(1.0, 1.0, 1.0)
     q = FXQuatf.new(axis)
     q = FXQuatf.new(axis, 0.0)
   end
+
   def test_construct_from_components
     x, y, z, w = 1.0, 1.0, 1.0, 1.0
     q = FXQuatf.new(x, y, z, w)
   end
+
   def test_construct_from_roll_pitch_yaw
     roll, pitch, yaw = 45.0, 45.0, 45.0
     q = FXQuatf.new(roll, pitch, yaw)
   end
+
   def test_adjust!
     adjusted = @quat.adjust!
     assert_same(@quat, adjusted)
   end
-  def test_setAxisAngle
-  end
-  def test_getAxisAngle
-  end
+
   def test_setRollPitchYaw
     roll, pitch, yaw = 0.0, 0.0, 0.0
     @quat.setRollPitchYaw(roll, pitch, yaw)
   end
+
   def test_getRollPitchYaw
     rpy = @quat.getRollPitchYaw()
     assert_instance_of(Array, rpy)
     assert_equal(3, rpy.length)
   end
+
   def test_exp
     expQuat = @quat.exp
     assert_instance_of(FXQuatf, expQuat)
   end
+
   def test_log
     logQuat = @quat.log
     assert_instance_of(FXQuatf, logQuat)
   end
+
   def test_invert
     invertQuat = @quat.invert
     assert_instance_of(FXQuatf, invertQuat)
   end
+
   def test_conj
     conjQuat = @quat.conj
     assert_instance_of(FXQuatf, conjQuat)
   end
-  def test_mul
-    anotherQuat = FXQuatf.new
-    product = @quat*anotherQuat
+
+  def test_multiplication_result_is_another_quat
+    q1 = FXQuatf.new(1, 2, 3, 4)
+    q2 = FXQuatf.new(1, 2, 3, 4)
+    product = q1*q2
     assert_instance_of(FXQuatf, product)
-    assert_equal(product, anotherQuat*@quat)
   end
+
+  def test_multiplication_is_commutative
+    q1 = FXQuatf.new(1, 2, 3, 4)
+    q2 = FXQuatf.new(1, 2, 3, 4)
+    assert_equal(q1*q2, q2*q1)
+  end
+
   def test_arc
     a = FXVec3f.new(0.0, 0.0, 0.0)
     b = FXVec3f.new(0.0, 0.0, 0.0)
     q = FXQuatf.arc(a, b)
     assert_instance_of(FXQuatf, q)
   end
+
   def test_lerp
     u = FXQuatf.new
     v = FXQuatf.new
diff --git a/tests/TC_FXRanged.rb b/tests/TC_FXRanged.rb
new file mode 100755
index 0000000000000000000000000000000000000000..1cf193cca9c72b37c8e0884543188a59c4450bcc
--- /dev/null
+++ b/tests/TC_FXRanged.rb
@@ -0,0 +1,42 @@
+require 'test/unit'
+
+require 'fox16'
+
+include Fox
+
+class TC_FXRanged < Test::Unit::TestCase
+
+  WIDTH, HEIGHT, DEPTH = 2, 4, 6
+
+  def setup
+    @range = FXRanged.new(0, WIDTH, 0, HEIGHT, 0, DEPTH)
+  end
+  
+  def test_lower_is_a_vector
+    assert_instance_of(FXVec3d, @range.lower)
+  end
+  
+  def test_upper_is_a_vector
+    assert_instance_of(FXVec3d, @range.upper)
+  end
+
+  def test_width
+    assert_equal(@range.width, WIDTH)
+  end
+  
+  def test_height
+    assert_equal(@range.height, HEIGHT)
+  end
+
+  def test_depth
+    assert_equal(@range.depth, DEPTH)
+  end
+
+  def test_longest
+    assert_equal([@range.width, @range.height, @range.depth].max, @range.longest)
+  end
+
+  def test_shortest
+    assert_equal([@range.width, @range.height, @range.depth].min, @range.shortest)
+  end
+end
diff --git a/tests/TC_FXRangef.rb b/tests/TC_FXRangef.rb
index 307f9dfabd800e3c71515ae908687f4d4048d5e5..f302d95408d091545422de35fd29e25a1a1881c2 100755
--- a/tests/TC_FXRangef.rb
+++ b/tests/TC_FXRangef.rb
@@ -12,37 +12,31 @@ class TC_FXRangef < Test::Unit::TestCase
     @range = FXRangef.new(0, WIDTH, 0, HEIGHT, 0, DEPTH)
   end
   
+  def test_lower_is_a_vector
+    assert_instance_of(FXVec3f, @range.lower)
+  end
+  
+  def test_upper_is_a_vector
+    assert_instance_of(FXVec3f, @range.upper)
+  end
+
   def test_width
     assert_equal(@range.width, WIDTH)
   end
+  
   def test_height
     assert_equal(@range.height, HEIGHT)
   end
+
   def test_depth
     assert_equal(@range.depth, DEPTH)
   end
+
   def test_longest
     assert_equal([@range.width, @range.height, @range.depth].max, @range.longest)
   end
+
   def test_shortest
     assert_equal([@range.width, @range.height, @range.depth].min, @range.shortest)
   end
-  def test_empty?
-  end
-  def test_overlaps?
-  end
-  def test_contains?
-  end
-  def test_include
-  end
-  def test_clipTo
-  end
-  def test_corners
-  end
-  def test_intersects?
-  end
-  def test_center
-  end
-  def test_diagonal
-  end
 end
diff --git a/tests/TC_FXTable.rb b/tests/TC_FXTable.rb
index 067d7225a9db75693c14b71da2d174c926f60632..8cfb16938a3ae6dfb8b62fc91e130f25931e10e0 100755
--- a/tests/TC_FXTable.rb
+++ b/tests/TC_FXTable.rb
@@ -365,4 +365,197 @@ public
     assert_equal("(1, 0)", @table.getItemText(1, 0))
     assert_equal("(1, 1)", @table.getItemText(1, 1))
   end
+  
+  def test_set_column_icon_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnIcon(-1, nil) 
+    }
+  end
+
+  def test_set_column_icon_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnIcon(@table.numColumns, nil) 
+    }
+  end
+
+  def test_get_column_icon_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnIcon(-1) 
+    }
+  end
+
+  def test_get_column_icon_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnIcon(@table.numColumns) 
+    }
+  end
+
+  def test_set_column_icon_position_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnIconPosition(-1, 0) 
+    }
+  end
+
+  def test_set_column_icon_position_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnIconPosition(@table.numColumns, 0) 
+    }
+  end
+
+  def test_get_column_icon_position_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnIconPosition(-1) 
+    }
+  end
+
+  def test_get_column_icon_position_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnIconPosition(@table.numColumns) 
+    }
+  end
+
+  def test_set_column_justify_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnJustify(-1, 0) 
+    }
+  end
+
+  def test_set_column_justify_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnJustify(@table.numColumns, 0) 
+    }
+  end
+
+  def test_get_column_justify_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnJustify(-1) 
+    }
+  end
+
+  def test_get_column_justify_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnJustify(@table.numColumns) 
+    }
+  end
+
+  def test_set_column_text_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnText(-1, "") 
+    }
+  end
+
+  def test_set_column_text_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setColumnText(@table.numColumns, "") 
+    }
+  end
+
+  def test_get_column_text_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnText(-1) 
+    }
+  end
+
+  def test_get_column_text_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getColumnText(@table.numColumns) 
+    }
+  end
+
+  def test_set_row_icon_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowIcon(-1, nil) 
+    }
+  end
+
+  def test_set_row_icon_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowIcon(@table.numRows, nil) 
+    }
+  end
+
+  def test_get_row_icon_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowIcon(-1) 
+    }
+  end
+
+  def test_get_row_icon_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowIcon(@table.numRows) 
+    }
+  end
+
+  def test_set_row_icon_position_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowIconPosition(-1, 0) 
+    }
+  end
+
+  def test_set_row_icon_position_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowIconPosition(@table.numRows, 0) 
+    }
+  end
+
+  def test_get_row_icon_position_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowIconPosition(-1) 
+    }
+  end
+
+  def test_get_row_icon_position_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowIconPosition(@table.numRows) 
+    }
+  end
+
+  def test_set_row_justify_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowJustify(-1, 0) 
+    }
+  end
+
+  def test_set_row_justify_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowJustify(@table.numRows, 0) 
+    }
+  end
+
+  def test_get_row_justify_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowJustify(-1) 
+    }
+  end
+
+  def test_get_row_justify_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowJustify(@table.numRows) 
+    }
+  end
+
+  def test_set_row_text_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowText(-1, "") 
+    }
+  end
+
+  def test_set_row_text_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.setRowText(@table.numRows, "") 
+    }
+  end
+
+  def test_get_row_text_negative_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowText(-1) 
+    }
+  end
+
+  def test_get_row_text_large_index_raises_index_error
+    assert_raises(IndexError) {
+      @table.getRowText(@table.numRows) 
+    }
+  end
+
 end
diff --git a/tests/TC_FXText.rb b/tests/TC_FXText.rb
index 4edb6df398cac2ffe4d1445cef6d0382cbe56196..bd38766f20adb847891521bb2dcc8810ebee7121 100755
--- a/tests/TC_FXText.rb
+++ b/tests/TC_FXText.rb
@@ -72,10 +72,25 @@ public
     assert_equal(SAMPLE, @text.text)
   end
   
-  def test_findText
+  def test_find_text
     @text.text = "99 bottles of beer"
     startIndex, endIndex = @text.findText("bottles")
     assert_equal([3], startIndex)
     assert_equal([10], endIndex)
   end
+
+  def test_find_text_with_startpos
+    @text.text = "I came, I saw, I conquered"
+    startIndex, endIndex = @text.findText("I ", 5)
+    assert_equal([8], startIndex)
+    assert_equal([10], endIndex)
+  end
+
+  def test_find_text_with_groups
+    @text.text = "I came, I saw, I conquered"
+    startIndex, endIndex = @text.findText("I ([a-z]+)(, )?", 0, SEARCH_REGEX)
+    assert_equal([0, 2, 6], startIndex)
+    assert_equal([8, 6, 8], endIndex)
+  end
+
 end
diff --git a/tests/TC_FXTreeList.rb b/tests/TC_FXTreeList.rb
index 6a959f413bf1b250ab10f43b77d66f6669e3b067..ef5543cd8e1c081a4e994897ac9b4311e94ddbca 100755
--- a/tests/TC_FXTreeList.rb
+++ b/tests/TC_FXTreeList.rb
@@ -14,27 +14,27 @@ class TC_FXTreeList < TestCase
   
   def test_firstItem
     assert_nil(@treeList.firstItem)
-    item = @treeList.addItemFirst(nil, "first")
+    item = @treeList.prependItem(nil, "first")
     assert_same(item, @treeList.firstItem)
   end
 
   def test_lastItem
     assert_nil(@treeList.lastItem)
-    item = @treeList.addItemFirst(nil, "first")
+    item = @treeList.prependItem(nil, "first")
     assert_same(item, @treeList.lastItem)
   end
 
   def test_reparentItem
-    rootItem = @treeList.addItemFirst(nil, "Root Item")
-    childItem = @treeList.addItemFirst(@treeList.firstItem, "Child Item")
+    rootItem = @treeList.prependItem(nil, "Root Item")
+    childItem = @treeList.prependItem(@treeList.firstItem, "Child Item")
     @treeList.reparentItem(childItem, nil)
     assert_same(rootItem, @treeList.firstItem)
     assert_same(childItem, @treeList.lastItem)
   end
 
   def test_moveItemBefore
-    first  = @treeList.addItemLast(nil, "first")
-    second = @treeList.addItemLast(nil, "second")
+    first  = @treeList.appendItem(nil, "first")
+    second = @treeList.appendItem(nil, "second")
     assert_same(second, first.next)
     assert_same(first,  second.prev)
     assert_same(second, @treeList.moveItemBefore(first, second))
@@ -43,8 +43,8 @@ class TC_FXTreeList < TestCase
   end
 
   def test_moveItemAfter
-    first  = @treeList.addItemLast(nil, "first")
-    second = @treeList.addItemLast(nil, "second")
+    first  = @treeList.appendItem(nil, "first")
+    second = @treeList.appendItem(nil, "second")
     assert_same(second, first.next)
     assert_same(first,  second.prev)
     assert_same(first, @treeList.moveItemAfter(second, first))
@@ -53,9 +53,9 @@ class TC_FXTreeList < TestCase
   end
 
   def test_sortRootItems
-    @treeList.addItemLast(nil, "B")
-    @treeList.addItemLast(nil, "A")
-    @treeList.addItemLast(nil, "C")
+    @treeList.appendItem(nil, "B")
+    @treeList.appendItem(nil, "A")
+    @treeList.appendItem(nil, "C")
     @treeList.sortRootItems
     assert_equal("A", @treeList.firstItem.text)
     assert_equal("B", @treeList.firstItem.next.text)
@@ -67,12 +67,12 @@ class TC_FXTreeList < TestCase
     @treeList.connect(SEL_INSERTED) { |sender, sel, ptr|
       anItem = ptr
     }
-    theItem = @treeList.addItemLast(nil, "", nil, nil, nil, true)
+    theItem = @treeList.appendItem(nil, "", nil, nil, nil, true)
     assert_same(theItem, anItem)
   end
   
   def test_SEL_DELETED
-    theItem = @treeList.addItemLast(nil, "")
+    theItem = @treeList.appendItem(nil, "")
     anItem = nil
     @treeList.connect(SEL_DELETED) { |sender, sel, ptr|
       anItem = ptr
@@ -80,4 +80,21 @@ class TC_FXTreeList < TestCase
     @treeList.removeItem(theItem, true)
     assert_same(theItem, anItem)
   end
+
+  def test_each_for_empty_list
+    count = 0
+    @treeList.each { |item| count += 1 }
+    assert_equal(0, count, "count for empty list should be zero")
+  end
+  
+  def test_each
+    @treeList.appendItem(nil, "1")
+    @treeList.appendItem(nil, "2")
+    @treeList.appendItem(nil, "3")
+    @treeList.appendItem(nil, "4")
+    count = 0
+    @treeList.each { |item| count += 1 }
+    assert_equal(4, count, "count didn't match expected number of items")
+  end
+  
 end
diff --git a/tests/TC_FXTreeListBox.rb b/tests/TC_FXTreeListBox.rb
index 9c921802cdfa3d94a9219635b3053d5c5a368344..b54dbaf31562d46a7b0f52a07fcf151da67b8215 100755
--- a/tests/TC_FXTreeListBox.rb
+++ b/tests/TC_FXTreeListBox.rb
@@ -5,19 +5,37 @@ require 'fox16'
 include Fox
 
 class TC_FXTreeListBox < TestCase
+  
   def setup
     super(self.class.name)
     @treeListBox = FXTreeListBox.new(mainWindow)
   end
 
   def test_sortRootItems
-    @treeListBox.addItemLast(nil, "B")
-    @treeListBox.addItemLast(nil, "A")
-    @treeListBox.addItemLast(nil, "C")
+    @treeListBox.appendItem(nil, "B")
+    @treeListBox.appendItem(nil, "A")
+    @treeListBox.appendItem(nil, "C")
     @treeListBox.sortRootItems
     assert_equal("A", @treeListBox.firstItem.text)
     assert_equal("B", @treeListBox.firstItem.next.text)
     assert_equal("C", @treeListBox.lastItem.text)
   end
+
+  def test_each_for_empty_list
+    count = 0
+    @treeListBox.each { |item| count += 1 }
+    assert_equal(0, count, "count for empty list should be zero")
+  end
+  
+  def test_each
+    @treeListBox.appendItem(nil, "1")
+    @treeListBox.appendItem(nil, "2")
+    @treeListBox.appendItem(nil, "3")
+    @treeListBox.appendItem(nil, "4")
+    count = 0
+    @treeListBox.each { |item| count += 1 }
+    assert_equal(4, count, "count didn't match expected number of items")
+  end
+  
 end
 
diff --git a/tests/stress1.rb b/tests/stress1.rb
index 4c1a71d76043c8db2d71d8ab6034e902d5901d91..405ac2e726e03189ce20dcbf9ecb109f317f6a69 100755
--- a/tests/stress1.rb
+++ b/tests/stress1.rb
@@ -14,13 +14,13 @@ RESTART_FREQUENCY = 20
 # Tree
 # =======================================================================
 class DirTree < FXTreeList
-  def initialize(parent, nvis, tgt = nil, sel = 0, opts = 0, x = 0, y = 0, w = 0, h = 0)
-    super
+  def initialize(p)
+    super(p, :opts => TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y)
   end
 
   def create
     super
-    item = addItemLast(nil, "root")
+    item = appendItem(nil, "root")
     @currentItem = item
     expand
   end
@@ -34,7 +34,7 @@ class DirTree < FXTreeList
   def listSubDir(parentItem)
     entries = (1..NUMBER_OF_ITEMS).collect { |i| i.to_s }
     entries.each do |entry|
-      item = addItemLast(parentItem, entry)
+      item = appendItem(parentItem, entry)
       @currentItem = item if entry == "1"
     end
   end
@@ -57,9 +57,7 @@ class Application < FXApp
     init(ARGV)
 
     @mainWindow = FXMainWindow.new(self, appName, nil, nil, DECOR_ALL, 0, 0, 400, 600)
-    @dirTree = DirTree.new(@mainWindow, 0, nil, 0,
-      (TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|
-       LAYOUT_FILL_X|LAYOUT_FILL_Y))
+    @dirTree = DirTree.new(@mainWindow) 
 
     @count = 0
   end 
diff --git a/tests/testcase.rb b/tests/testcase.rb
index 8d95f8cf0b4a674132640660f3d08b1009f5d0bb..3220e251cc058999ec0b14452a9c4798e1505a75 100755
--- a/tests/testcase.rb
+++ b/tests/testcase.rb
@@ -10,13 +10,13 @@ module Fox
     def setup(*args)
       unless args.empty?
         appName = args[0]
-	if FXApp.instance.nil?
-	  @theApp = FXApp.new(appName, 'FXRuby')
-	  @theApp.init([])
-	else
-	  @theApp = FXApp.instance
-	end
-	@theMainWindow = FXMainWindow.new(@theApp, appName)
+      	if FXApp.instance.nil?
+      	  @theApp = FXApp.new(appName, 'FXRuby')
+      	  @theApp.init([])
+      	else
+      	  @theApp = FXApp.instance
+      	end
+      	@theMainWindow = FXMainWindow.new(@theApp, appName)
       end      
     end
     
diff --git a/web/community.html b/web/community.html
new file mode 100644
index 0000000000000000000000000000000000000000..04e6abba28b5944f940846e43b372fb39a5d2399
--- /dev/null
+++ b/web/community.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="css/style.css" type="text/css" />
+  <link rel="meta" title="DOAP" type="application/rdf+xml" href="http://www.fxruby.org/doap.rdf" />
+  <title>Community</title>
+</head>
+
+<body>
+<!-- wrap starts here -->
+<div id="wrap">
+		
+		<!--header -->
+		<div id="header">			
+			
+			<h1 id="logo-text"><a href="index.html">FXRuby</a></h1>		
+			<p id="slogan">Graphical User Interface Development for Ruby</p>		
+			
+		</div>
+		
+		<!-- menu -->	
+		<div  id="menu">
+			<ul>
+				<li  ><a href=/ >Home</a></li>
+				<li id='current'><a href=# >Community</a></li>
+				<li ><a href=/downloads.html >Downloads</a></li>
+				<li ><a href=/documentation.html >Documentation</a></li>
+			</ul>
+		</div>					
+			
+		<!-- content-wrap starts here -->
+		<div id="content-wrap">
+				
+			<div id="sidebar">
+			
+				<h3>Get the Book!</h3>
+				<a href="http://www.pragprog.com/titles/fxruby"><img src="images/fxruby-book.jpg" alt="FXRuby: Create Lean and Mean GUIs with Ruby" width="175" height="210" /></a>
+
+				<h3>Links</h3>
+				<ul class="sidemenu">
+					<li><a href="http://rubyforge.org/news/?group_id=300">News</a></li>
+					<li><a href="http://www.fxruby.org/doc/book.html">User's Guide</a></li>
+					<li><a href="http://www.fxruby.org/doc/api">API Docs</a></li>					
+					<li><a href="http://www.fxruby.org/doc/examples.html">Screenshots</a></li>
+					<li><a href="http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse">Report Bugs</a></li>
+					<li><a href="http://www.gnu.org/copyleft/lesser.html">License</a></li>
+				</ul>
+			
+			</div>
+				
+			<div id="main">
+				
+				<h1>Mailing Lists</h1>
+
+
+	<h2>Announcements</h2>
+
+
+	<p>The announcements list is a low-traffic list on which new releases of FXRuby, as well as software based on FXRuby, will be
+announced. Discussions on various topics however should preferably take place in the users list, to prevent swamping people&#8217;s
+mailboxes. To subscribe, fill out the <a href="http://rubyforge.org/mailman/listinfo/fxruby-announce" title="Announcements List Subscription
+Form">web-based subscription form</a>.</p>
+
+
+	<h2>General Discussion</h2>
+
+
+	<p>The users list is intended for discussion on various FOX and FXRuby topics between developers and/or users of FXRuby and
+applications based on it. If you have questions, feel free to post your questions here, as many people are only too happy to
+answer them. To subscribe, fill out the <a href="http://rubyforge.org/mailman/listinfo/fxruby-users" title="General Discussion List Subscription
+Form">web-based subscription form</a>.</p>
+
+			</div>
+		
+		<!-- content-wrap ends here -->	
+		</div>
+					
+		<!--footer starts here-->
+		<div id="footer">
+			
+			<p>
+			  &copy; 2008 Lyle Johnson<br />
+			  Web Site Generated Using <a href="http://webby.rubyforge.org/" title="Webby">Webby</a>
+			</p>
+				
+  </div>	
+
+<!-- wrap ends here -->
+</div>
+
+</body>
+</html>
diff --git a/web/css/style.css b/web/css/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..36c1a1b1a58c8d053524037a3a530abac5ffa603
--- /dev/null
+++ b/web/css/style.css
@@ -0,0 +1,407 @@
+/********************************************
+   AUTHOR:  			Erwin Aligam 
+   WEBSITE:   			http://www.styleshout.com/
+	TEMPLATE NAME:		Envision
+   TEMPLATE CODE: 	S-0013
+   VERSION:          1.1
+	LAST MODIFIED     Nov-14-2007 	
+ *******************************************/
+ 
+/********************************************
+   HTML ELEMENTS
+********************************************/ 
+
+/* Top Elements */
+* { margin: 0; padding: 0; outline: 0 }
+
+body {
+	background: #CCC;
+	font: 80%/1.5em Verdana, Tahoma, arial, sans-serif;
+	color: #555; 
+	text-align: center;
+}
+
+/* links */
+a, a:visited {
+	text-decoration: none;
+	color: #2180BC;
+	background: inherit;
+}
+a:hover {
+	color: #88ac0b;
+	background: inherit;
+	text-decoration: underline;
+}
+
+/* headers */
+h1, h2, h3 {
+	font-family: 'Trebuchet MS', Tahoma, Sans-serif;	 		
+}
+h1 {
+	font-size: 150%;	
+	font-weight: normal;
+	color: #006699;
+}
+h2 {
+	font-size: 140%;
+	text-transform: uppercase;
+	color: #88ac0b;
+}
+h3 {
+	font-size: 120%;
+	color: #666666; 
+}
+
+/* images */
+img {
+	background: #FAFAFA;
+   border: 1px solid #E5E5E5;
+	padding: 5px;
+}
+img.float-right {
+  margin: 5px 0px 10px 10px;  
+}
+img.float-left {
+  margin: 5px 10px 10px 0px;
+}
+
+h1, h2, h3, p {
+	padding: 10px;		
+	margin: 0;
+}
+ul, ol {
+	margin: 5px 20px;
+	padding: 0 20px;
+}
+
+code {
+  margin: 5px 0;
+  padding: 10px;
+  text-align: left;
+  display: block;
+  overflow: auto;  
+  font: 500 1em/1.5em 'Lucida Console', 'courier new', monospace ;
+  /* white-space: pre; */
+  background: #FAFAFA;
+  border: 1px solid #f2f2f2;  
+}
+acronym {
+  cursor: help;
+  border-bottom: 1px dotted #777;
+}
+blockquote {
+	margin: 10px;
+ 	padding: 0 0 0 28px;  
+   border: 1px solid #f2f2f2; 
+  	background: #FAFAFA url(../images/quote.gif) no-repeat 5px 5px;    
+}
+
+/* start - table */
+table {
+	border-collapse: collapse;
+	margin: 10px;	
+}
+th strong {
+	color: #fff;
+}
+th {
+	background: #93BC0C;
+	height: 29px;
+	padding-left: 12px;
+	padding-right: 12px;
+	color: #FFF;
+	text-align: left;
+	border-left: 1px solid #B6D59A;
+	border-bottom: solid 2px #FFF;
+}
+tr {
+	height: 30px;
+}
+td {
+	padding-left: 11px;
+	padding-right: 11px;
+	border-left: 1px solid #FFF;
+	border-bottom: solid 1px #ffffff;
+}
+td.first,th.first {
+	border-left: 0px;
+}
+tr.row-a {
+	background: #F8F8F8;
+}
+tr.row-b {
+	background: #EFEFEF;
+}
+/* end - table */
+
+/* form elements */
+form {
+	margin:10px; padding: 0 5px;
+	border: 1px solid #f2f2f2; 
+	background-color: #FAFAFA; 	
+}
+label {
+	display:block;
+	font-weight:bold;
+	margin:5px 0;
+}
+input {
+	padding:2px;
+	border:1px solid #eee;
+	font: normal 1em Verdana, sans-serif;
+	color:#777;
+}
+textarea {
+	width:400px;
+	padding:2px;
+	font: normal 1em Verdana, sans-serif;
+	border:1px solid #eee;
+	height:100px;
+	display:block;
+	color:#777;
+}
+input.button { 
+	font: bold 12px Arial, Sans-serif; 
+	height: 24px;
+	margin: 0;
+	padding: 2px 3px; 
+	color: #FFF;
+	background: #8EB50C url(../images/button-bg.jpg) repeat-x 0 0;
+	border: none;
+}
+
+/* search form */
+.searchform {
+	background-color: transparent;
+	border: none;	
+	margin: 0; padding: 5px 0 15px 0;	
+	width: 190px;	
+}
+.searchform p { margin: 0; padding: 0; }
+.searchform input.textbox { 
+	width: 120px;
+	color: #777; 
+	height: 18px;
+	padding: 2px;	
+	border: 1px solid #E5E5E5;
+	vertical-align: top;
+}
+.searchform input.button { 
+	width: 60px;
+	height: 24px;
+	padding: 2px 5px;
+	vertical-align: top;
+}
+
+/********************************************
+   LAYOUT
+********************************************/ 
+#wrap {
+	width: 820px;
+	background: #CCC url(../images/content.jpg) repeat-y center top;
+	margin: 0 auto;
+	text-align: left;
+}
+#content-wrap {
+	clear: both;
+	width: 760px;
+	padding: 0; 
+	margin: 10px auto;
+}
+#header {
+	width: 820px;
+	position: relative;
+	height: 103px;
+	background: #CCC url(../images/header.png) no-repeat center top;
+	padding: 0;	
+	color: #FFF;	
+}
+#header h1#logo-text a {
+	position: absolute;
+	margin: 0; padding: 0;
+	font: bolder 44px 'Trebuchet MS', Arial, Sans-serif;
+	letter-spacing: -2px;
+	color: #FFF;
+	text-transform: none;
+	text-decoration: none;
+	background: transparent;
+	
+	/* change the values of top and left to adjust the position of the logo*/
+	top: 20px; left: 110px;	
+}
+#header p#slogan {
+	position: absolute;
+	margin: 0; padding: 0;
+	font: normal 12px 'Trebuchet MS', Arial, Sans-serif;
+	text-transform: none;
+	color: #FFF;
+	
+	/* change the values of top and left to adjust the position of the slogan*/
+	top: 70px; left: 110px;		
+}
+
+/* header links */
+#header #header-links {
+	position: absolute;
+	top: 20px; right: 30px;	
+	color: #C6DDEE;
+	font-size: 10px;	
+}
+#header #header-links a {	
+	color: #FFF;
+	text-decoration: none;	
+}
+#header #header-links a:hover {
+	color: #D4E59F;	
+}
+
+/* Menu */
+#menu {
+	clear: both;	
+	margin: 0 auto; padding: 0;
+	background: url(../images/menu.jpg) repeat-x 0 0;	
+	font: bold 12px/37px Verdana, Arial, Tahoma, Sans-serif;
+	height: 37px;
+	width: 780px;	
+}
+#menu ul {
+	float: right;
+	list-style: none;
+	margin:0; padding: 0;
+}
+#menu ul li {
+	display: inline;
+}
+#menu ul li a {
+	display: block;
+	float: left;
+	padding: 0 12px;
+	color: #FFF;	
+	text-decoration: none;
+}
+#menu ul li.last a {
+	padding-right: 20px;	
+}
+#menu ul li a:hover {
+	color: #D4E59F;	
+}
+#menu ul li#current a {	
+	color: #D4E59F;
+}
+
+/* Main Column */
+#main {
+	float: left;
+	width: 70%;
+	padding: 0; margin: 5px 0 0 5px;
+	display: inline;
+}
+#main h2 {
+	margin-top: 10px;
+	font: Bold 140% 'Trebuchet MS', Tahoma, Sans-serif;
+	color: #88ac0b; 
+	padding: 5px 0 5px 25px; 	
+	border-bottom: 1px solid #EFF0F1;
+	background: #FFF url(../images/square-green.png) no-repeat 3px 50%;	
+	text-transform: none;
+}
+#main h2 a {
+	background: none;
+	color: #88ac0b;
+	text-decoration: none;
+}
+
+#main ul li {
+	list-style-image: url(../images/bullet.gif);
+}
+
+.post-footer {
+	background-color: #FAFAFA;
+	padding: 5px; margin: 20px 10px 10px 10px;
+	border: 1px solid #f2f2f2;
+	font-size: 95%;	
+}
+.post-footer .date {
+	background: url(../images/clock.gif) no-repeat left center;
+	padding-left: 20px; margin: 0 10px 0 5px;
+}
+.post-footer .comments {
+	background: url(../images/comment.gif) no-repeat left center;
+	padding-left: 20px; margin: 0 10px 0 5px;
+}
+.post-footer .readmore {
+	background: url(../images/page.gif) no-repeat left center;
+	padding-left: 20px; margin: 0 10px 0 5px;
+}
+
+/* Sidebar */	
+#sidebar {
+	float: right;
+	width: 26.5%;
+	padding: 0; margin: 0;	
+	color: #68774A;	
+}
+#sidebar img {
+	text-align: center;
+}	
+#sidebar h3 {
+	margin-top: 10px;
+	/* padding: 5px 5px; */
+	text-align: center;
+	font: bold 1.4em 'Trebuchet MS', Tahoma, Sans-serif;
+	color: #728D26;	
+}
+#sidebar ul.sidemenu {
+	list-style: none;
+	text-align: left;
+	margin: 7px 4px 8px 0; padding: 0;
+	text-decoration: none;		
+	background: url(../images/dots.jpg) repeat-x left top;
+}
+#sidebar ul.sidemenu li {
+	list-style: none;
+	background: url(../images/dots.jpg) repeat-x left bottom;
+	padding: 4px 0 4px 5px;
+	margin: 0 2px;	
+	color: #68774A;	
+}
+* html body #sidebar ul.sidemenu li {
+	height: 1%;
+}
+#sidebar ul.sidemenu li a {
+	text-decoration: none;	
+	background-image: none;	
+	color: #666666;			
+}
+#sidebar ul.sidemenu li a:hover {	
+	color: #1773BC;	
+}
+#sidebar ul.sidemenu ul { margin: 0 0 0 5px; padding: 0; }
+#sidebar ul.sidemenu ul li { background: none; }
+
+
+/* Footer */	
+#footer {
+	color: #C6DDEE;
+	background: #CCC url(../images/footer.jpg) no-repeat center top;
+	clear: both;
+	width: 820px;
+	height: 65px;
+	text-align: center;	
+	font-size: 92%;	
+}
+#footer a { 
+	color: #FFF;
+	text-decoration: none; 
+}
+
+/* alignment classes */
+.float-left  { float: left; }
+.float-right { float: right; }
+.align-left  { text-align: left; }
+.align-right { text-align: right; }
+
+/* display and additional classes */
+.clear { clear: both; }
+
+
diff --git a/web/documentation.html b/web/documentation.html
new file mode 100644
index 0000000000000000000000000000000000000000..9f570fdc33f8c93fe75aee1b5feea9d9547f6686
--- /dev/null
+++ b/web/documentation.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="css/style.css" type="text/css" />
+  <link rel="meta" title="DOAP" type="application/rdf+xml" href="http://www.fxruby.org/doap.rdf" />
+  <title>Documentation</title>
+</head>
+
+<body>
+<!-- wrap starts here -->
+<div id="wrap">
+		
+		<!--header -->
+		<div id="header">			
+			
+			<h1 id="logo-text"><a href="index.html">FXRuby</a></h1>		
+			<p id="slogan">Graphical User Interface Development for Ruby</p>		
+			
+		</div>
+		
+		<!-- menu -->	
+		<div  id="menu">
+			<ul>
+				<li  ><a href=/ >Home</a></li>
+				<li ><a href=/community.html >Community</a></li>
+				<li ><a href=/downloads.html >Downloads</a></li>
+				<li id='current'><a href=# >Documentation</a></li>
+			</ul>
+		</div>					
+			
+		<!-- content-wrap starts here -->
+		<div id="content-wrap">
+				
+			<div id="sidebar">
+			
+				<h3>Get the Book!</h3>
+				<a href="http://www.pragprog.com/titles/fxruby"><img src="images/fxruby-book.jpg" alt="FXRuby: Create Lean and Mean GUIs with Ruby" width="175" height="210" /></a>
+
+				<h3>Links</h3>
+				<ul class="sidemenu">
+					<li><a href="http://rubyforge.org/news/?group_id=300">News</a></li>
+					<li><a href="http://www.fxruby.org/doc/book.html">User's Guide</a></li>
+					<li><a href="http://www.fxruby.org/doc/api">API Docs</a></li>					
+					<li><a href="http://www.fxruby.org/doc/examples.html">Screenshots</a></li>
+					<li><a href="http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse">Report Bugs</a></li>
+					<li><a href="http://www.gnu.org/copyleft/lesser.html">License</a></li>
+				</ul>
+			
+			</div>
+				
+			<div id="main">
+				
+				<h1>Books</h1>
+
+
+	<p>The book <cite>FXRuby: Create Lean and Mean GUIs with Ruby</cite> (available from the <a href="http://www.pragmaticprogrammer.com/titles/fxruby/">Pragmatic
+Programmers</a> and other booksellers) is the best print source of documentation
+for FXRuby. It&#8217;s also available as a PDF.</p>
+
+
+	<p>Several other books, including <cite>Ruby Developer&#8217;s Guide</cite> and <cite>The Ruby Way</cite>, include chapters or sections
+on GUI development with FXRuby.</p>
+
+
+	<h1>Online</h1>
+
+
+	<p>The <a href="http://www.fxruby.org/doc/book.html">FXRuby User&#8217;s Guide</a> provides detailed installation instructions as well
+as a handful of tutorial exercises to get you started with FXRuby development.</p>
+
+
+	<p>If you&#8217;re looking for API reference documentation, all of the classes and methods for FXRuby are documented
+<a href="http://www.fxruby.org/doc/api/">here</a>.</p>
+
+
+	<p>Other good sources of documentation include the <a href="http://www.fox-toolkit.org/">FOX home page</a> and the <a href="http://www.fox-toolkit.net/">FOX Community
+Wiki</a> site.</p>
+
+			</div>
+		
+		<!-- content-wrap ends here -->	
+		</div>
+					
+		<!--footer starts here-->
+		<div id="footer">
+			
+			<p>
+			  &copy; 2008 Lyle Johnson<br />
+			  Web Site Generated Using <a href="http://webby.rubyforge.org/" title="Webby">Webby</a>
+			</p>
+				
+  </div>	
+
+<!-- wrap ends here -->
+</div>
+
+</body>
+</html>
diff --git a/web/downloads.html b/web/downloads.html
old mode 100755
new mode 100644
index 688eac69dd8bbc24511da8e218244406ba1ab54d..80610f52f04d5bf410127598870843084e085b97
--- a/web/downloads.html
+++ b/web/downloads.html
@@ -1,93 +1,114 @@
-<html>
-<head>
-<link rel="stylesheet" href="page.css" type="text/css">
-<title>Downloads</title>
-</head>
-<body bgcolor=#ffffff link=#990033 vlink=#990033 alink=#990033 text=#000000>
-
-
-<!--- TOPIC TITLE -->
-<p>
-<table width=100% cellpadding=0 cellspacing=2><tr><td width=100% valign=bottom id="HEADLINE"><b>
-Downloads
-<br><img src='art/line.gif' width='100%' height=1></b></td></tr></table>
-</p>
-<!--- TOPIC TITLE -->
-<blockquote>
-The latest version of FXRuby is always available
-from the <a href="http://rubyforge.org/projects/fxruby" target=_top>RubyForge
-project page</a>. The RubyForge releases should always have accompanying
-release notes describing the changes for that release. A cumulative
-<tt>ChangeLog</tt> file is also included in the FXRuby source code distribution.
-
-As of the FOX 1.0 release, any FXRuby version 1.0.x release should be compatible with any FOX 1.0.x release.
-Similarly, any FXRuby 1.2.x release should be compatible with any FOX 1.2.x release, and
-any FXRuby 1.4.x release should be compatible with any FOX 1.4.x release.<p>
-</blockquote>
-
-<!--- TOPIC TITLE -->
-<p>
-<table width=100% cellpadding=0 cellspacing=2><tr><td width=100% valign=bottom id="HEADLINE"><b>
-Source Code
-<br><img src='art/line.gif' width='100%' height=1></b></td></tr></table>
-</p>
-<!--- TOPIC TITLE -->
-<blockquote>
-The FXRuby source code is distributed as a gzipped tar archive, and is available for
-download from the <a href="http://rubyforge.org/projects/fxruby" target=_top>RubyForge
-project page</a>.
-</blockquote>
-
-<!--- TOPIC TITLE -->
-<p>
-<table width=100% cellpadding=0 cellspacing=2><tr><td width=100% valign=bottom id="HEADLINE"><b>
-Binaries for Unix/Linux
-<br><img src='art/line.gif' width='100%' height=1></b></td></tr></table>
-</p>
-<!--- TOPIC TITLE -->
-<blockquote>
-Precompiled binaries for FOX, FXScintilla and FXRuby are available for various Unix/Linux platforms,
-but not in any centralized way.<p>
-Both the <a href="http://www.fox-toolkit.net">FOX
-Community Wiki site</a> and the <a href="http://www.fox-toolkit.com">main FOX web site</a>
-list a number of independent sources for package downloads for various Linux distributions, but
-many of these are for older FOX releases. You may have better luck using a RPM search engine like
-<a href="http://rpmfind.net">rpmfind.net</a> to find the most recent packages for your distribution.
-</blockquote>
-
-<!--- TOPIC TITLE -->
-<p>
-<table width=100% cellpadding=0 cellspacing=2><tr><td width=100% valign=bottom id="HEADLINE"><b>
-Binaries for Microsoft Windows
-<br><img src='art/line.gif' width='100%' height=1></b></td></tr></table>
-</p>
-<!--- TOPIC TITLE -->
-<blockquote>
-Windows installers for FXRuby are available for download from
-the <a href="http://rubyforge.org/projects/fxruby" target=_top>RubyForge
-project page</a>.
-<b>The FOX and FXScintilla libraries are built into the Windows installers for FXRuby, and
-you should not need to download and install those packages separately.</b>
-These binaries are also compatible with the standard Ruby
-installers for Windows that are available for download from
-<a href="http://rubyforge.org/projects/rubyinstaller" target=_top>RubyForge</a>.<p>
-Note that the precompiled binaries for Windows are built with OpenGL support, and
-thus depend on the OpenGL runtime libraries (<tt>opengl32.dll</tt> and
-<tt>glu32.dll</tt>). These libraries were <i>not</i> included with Windows 95
-(earlier than OSR2), so if you're using Ruby and FXRuby on a Windows 95 machine,
-you may need to download the <a href="http://download.microsoft.com/download/win95upg/info/1/W95/EN-US/Opengl95.exe">OpenGL runtime libraries</a>.
-You must have these libraries installed even if you don't plan to do anything
-OpenGL-related with FXRuby.
-</blockquote>
-
-<!--- COPYRIGHT -->
-<p>
-<table width=100% cellpadding=0 cellspacing=0><tr><td width=100% valign=top id=HEADLINE align=right>
-<img src='art/line.gif' width=100% height=1><font size=-1>
-Copyright &copy; 2001-2004 Lyle Johnson</font>
-</td></tr></table>
-</p>
-<!--- COPYRIGHT -->
-
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <link rel="stylesheet" href="css/style.css" type="text/css" />
+  <link rel="meta" title="DOAP" type="application/rdf+xml" href="http://www.fxruby.org/doap.rdf" />
+  <title>Downloads</title>
+</head>
+
+<body>
+<!-- wrap starts here -->
+<div id="wrap">
+		
+		<!--header -->
+		<div id="header">			
+			
+			<h1 id="logo-text"><a href="index.html">FXRuby</a></h1>		
+			<p id="slogan">Graphical User Interface Development for Ruby</p>		
+			
+		</div>
+		
+		<!-- menu -->	
+		<div  id="menu">
+			<ul>
+				<li  ><a href=/ >Home</a></li>
+				<li ><a href=/community.html >Community</a></li>
+				<li id='current'><a href=# >Downloads</a></li>
+				<li ><a href=/documentation.html >Documentation</a></li>
+			</ul>
+		</div>					
+			
+		<!-- content-wrap starts here -->
+		<div id="content-wrap">
+				
+			<div id="sidebar">
+			
+				<h3>Get the Book!</h3>
+				<a href="http://www.pragprog.com/titles/fxruby"><img src="images/fxruby-book.jpg" alt="FXRuby: Create Lean and Mean GUIs with Ruby" width="175" height="210" /></a>
+
+				<h3>Links</h3>
+				<ul class="sidemenu">
+					<li><a href="http://rubyforge.org/news/?group_id=300">News</a></li>
+					<li><a href="http://www.fxruby.org/doc/book.html">User's Guide</a></li>
+					<li><a href="http://www.fxruby.org/doc/api">API Docs</a></li>					
+					<li><a href="http://www.fxruby.org/doc/examples.html">Screenshots</a></li>
+					<li><a href="http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse">Report Bugs</a></li>
+					<li><a href="http://www.gnu.org/copyleft/lesser.html">License</a></li>
+				</ul>
+			
+			</div>
+				
+			<div id="main">
+				
+				<p>The latest version of FXRuby is always available from the <a href="http://rubyforge.org/projects/fxruby/">RubyForge project page</a>. The
+RubyForge releases should always have accompanying release notes describing the changes for that release. A cumulative ChangeLog
+file is also included in the FXRuby source code distribution. Note that any FXRuby 1.6.x release should be compatible with any
+FOX 1.6.x release, but won&#8217;t be compatible with earlier (or later) versions of FOX.</p>
+
+
+	<h1>Source Code</h1>
+
+
+	<p>The FXRuby source code is distributed as a gzipped tar archive, and is available for download from the <a href="http://rubyforge.org/projects/fxruby/">RubyForge project
+page</a>.</p>
+
+
+	<h1>Binaries for Unix/Linux</h1>
+
+
+	<p>Precompiled binaries for FOX, FXScintilla and FXRuby are available for various Unix/Linux platforms, but not in any
+centralized way.</p>
+
+
+	<p>Both the <a href="http://www.fox-toolkit.net/">FOX Community Wiki</a> site and the main <a href="http://www.fox-toolkit.org/">FOX web site</a> list a
+number of independent sources for package downloads for various Linux distributions, but many of these are for older FOX
+releases. You may have better luck using a RPM search engine like <a href="http://rpmfind.net/">rpmfind.net</a> to find the most recent
+packages for your distribution.</p>
+
+
+	<h1>Binaries for Microsoft Windows</h1>
+
+
+	<p>Windows installers for FXRuby are available for download from the <a href="http://rubyforge.org/projects/fxruby/">RubyForge project
+page</a>. The FOX and FXScintilla libraries are built into the Windows installers for FXRuby,
+and you should not need to download and install those packages separately. These binaries are also compatible with the standard
+Ruby installer for Windows that are available for download from RubyForge.</p>
+
+
+	<p>Note that the precompiled binaries for Windows are built with OpenGL support, and thus depend on the OpenGL runtime libraries
+(opengl32.dll and glu32.dll). These libraries were not included with Windows 95 (earlier than OSR2), so if you&#8217;re using Ruby and
+FXRuby on a Windows 95 machine, you may need to download the OpenGL runtime libraries. You must have these libraries installed
+even if you don&#8217;t plan to do anything OpenGL-related with FXRuby.</p>
+
+			</div>
+		
+		<!-- content-wrap ends here -->	
+		</div>
+					
+		<!--footer starts here-->
+		<div id="footer">
+			
+			<p>
+			  &copy; 2008 Lyle Johnson<br />
+			  Web Site Generated Using <a href="http://webby.rubyforge.org/" title="Webby">Webby</a>
+			</p>
+				
+  </div>	
+
+<!-- wrap ends here -->
+</div>
+
+</body>
+</html>
diff --git a/web/images/bullet.gif b/web/images/bullet.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0ba2421a9240d1b20d8a383d3f63dff3864dbf3d
Binary files /dev/null and b/web/images/bullet.gif differ
diff --git a/web/images/button-bg.jpg b/web/images/button-bg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1c59ae2faa7c6ccf31cb83555c44599138161ad6
Binary files /dev/null and b/web/images/button-bg.jpg differ
diff --git a/web/images/comment.gif b/web/images/comment.gif
new file mode 100644
index 0000000000000000000000000000000000000000..951082f93a4bb0b7401e9cabdaaea9606cadb3f2
Binary files /dev/null and b/web/images/comment.gif differ
diff --git a/web/images/content.jpg b/web/images/content.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..23b605f8a1017c479a6f095c0d84c2753ece9e2c
Binary files /dev/null and b/web/images/content.jpg differ
diff --git a/web/images/dots.jpg b/web/images/dots.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e7f082d2ae29cf5f9b68abf3b6974a04ad001eec
Binary files /dev/null and b/web/images/dots.jpg differ
diff --git a/web/images/footer.jpg b/web/images/footer.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..097d99a9803609f67e65288e8d35af0248db3f19
Binary files /dev/null and b/web/images/footer.jpg differ
diff --git a/web/images/fxruby-book.jpg b/web/images/fxruby-book.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f53e20707ff02cd5350c062219a78e8332838a1b
Binary files /dev/null and b/web/images/fxruby-book.jpg differ
diff --git a/web/images/header.png b/web/images/header.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f79ed3735b6ac9a50b9eff96bd880a79bdfc128
Binary files /dev/null and b/web/images/header.png differ
diff --git a/web/images/menu.jpg b/web/images/menu.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..daaa8bb3a6129ed037d33f9e34b001bdbf232843
Binary files /dev/null and b/web/images/menu.jpg differ
diff --git a/web/images/page.gif b/web/images/page.gif
new file mode 100644
index 0000000000000000000000000000000000000000..0c49ba877f0cdd497b308ee97f14aea8a7ea2448
Binary files /dev/null and b/web/images/page.gif differ
diff --git a/web/images/quote.gif b/web/images/quote.gif
new file mode 100644
index 0000000000000000000000000000000000000000..43cbdb3fa50f973d5a45a1686545758168ebaf0b
Binary files /dev/null and b/web/images/quote.gif differ
diff --git a/web/images/square-green.png b/web/images/square-green.png
new file mode 100644
index 0000000000000000000000000000000000000000..82f2dd357b8c5b180aa157fcf4ed611018ff8baa
Binary files /dev/null and b/web/images/square-green.png differ
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..ca245b8dfa04f01b6ffd83a0daae891d1bba7043
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+  <meta name="verify-v1" content="oJj9+cXtpch0MSVjYgtyvC+Y57yYC6Cz9zFOd1+FXSw=" />
+  <link rel="stylesheet" href="css/style.css" type="text/css" />
+  <link rel="meta" title="DOAP" type="application/rdf+xml" href="http://www.fxruby.org/doap.rdf" />
+  <title>FXRuby</title>
+</head>
+
+<body>
+<!-- wrap starts here -->
+<div id="wrap">
+		
+		<!--header -->
+		<div id="header">			
+			
+			<h1 id="logo-text"><a href="index.html">FXRuby</a></h1>		
+			<p id="slogan">Graphical User Interface Development for Ruby</p>		
+			
+		</div>
+		
+		<!-- menu -->	
+		<div  id="menu">
+			<ul>
+				<li id='current' ><a href=# >Home</a></li>
+				<li ><a href=/community.html >Community</a></li>
+				<li ><a href=/downloads.html >Downloads</a></li>
+				<li ><a href=/documentation.html >Documentation</a></li>
+			</ul>
+		</div>					
+			
+		<!-- content-wrap starts here -->
+		<div id="content-wrap">
+				
+			<div id="sidebar">
+			
+				<h3>Get the Book!</h3>
+				<a href="http://www.pragprog.com/titles/fxruby"><img src="images/fxruby-book.jpg" alt="FXRuby: Create Lean and Mean GUIs with Ruby" width="175" height="210" /></a>
+
+				<h3>Links</h3>
+				<ul class="sidemenu">
+					<li><a href="http://rubyforge.org/news/?group_id=300">News</a></li>
+					<li><a href="http://www.fxruby.org/doc/book.html">User's Guide</a></li>
+					<li><a href="http://www.fxruby.org/doc/api">API Docs</a></li>					
+					<li><a href="http://www.fxruby.org/doc/examples.html">Screenshots</a></li>
+					<li><a href="http://rubyforge.org/tracker/?atid=1223&group_id=300&func=browse">Report Bugs</a></li>
+					<li><a href="http://www.gnu.org/copyleft/lesser.html">License</a></li>
+				</ul>
+			
+			</div>
+				
+			<div id="main">
+				
+				<p>FXRuby is a library for developing powerful and sophisticated cross-platform graphical user interfaces (GUIs) for your Ruby
+applications. It&#8217;s based on the <a href="http://www.fox-toolkit.org/" title="FOX Home Page">FOX Toolkit</a>, a popular open source
+C++ library developed by Jeroen van der Zijp. What that means for you as an application developer is that you&#8217;re able to
+write code in the <a href="http://www.ruby-lang.org/" title="Ruby Home Page">Ruby</a> programming language that you already know and love,
+while at the same time taking advantage of the performance and functionality of a featureful, highly optimized C++ toolkit.</p>
+
+
+	<h1>Projects Using FXRuby</h1>
+
+
+	<p>Projects using FXRuby include:</p>
+
+
+	<ul>
+	<li><a href="http://www.insula.cz/dbtalk">DbTalk</a> is an interactive GUI-based tool for database querying, programming, administration, etc. It is developed by Dalibor Sramek.</li>
+		<li><a href="http://freeride.rubyforge.org/wiki/wiki.pl">FreeRIDE</a> is an IDE for the Ruby programming language.</li>
+		<li><a href="http://www.fisica.uniud.it/~glast/FRED">FRED</a> is a high energy physics event display built out of Ruby and FOX by Riccardo Giannitrapani and Marco Frailis.</li>
+		<li><a href="http://www.mondrian-ide.com/">Mondrian</a> is a cross-platform project-manager and editor for the Ruby language. Written in 100% native Ruby using the FOX GUI toolkit, Mondrian has the familiar look and feel of a modern IDE while remaining dedicated to the uniqueness of the Ruby language and its community.</li>
+		<li><a href="http://fox-tool.rubyforge.org/">foxGUIb</a> is an interactive gui builder and codegenerator for FXRuby. This tool makes it easy to quickly build complex and good looking graphical user interfaces for Ruby.
+If your project uses FXRuby for its user interface, and you&#8217;d like to see it listed here, please send me an e-mail with the information.</li>
+	</ul>
+
+			</div>
+		
+		<!-- content-wrap ends here -->	
+		</div>
+					
+		<!--footer starts here-->
+		<div id="footer">
+			
+			<p>
+			  &copy; 2008 Lyle Johnson<br />
+			  Web Site Generated Using <a href="http://webby.rubyforge.org/" title="Webby">Webby</a>
+			</p>
+				
+  </div>	
+
+<!-- wrap ends here -->
+</div>
+
+</body>
+</html>