[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gnash-commit
Subject:    [Gnash-commit] gnash ./ChangeLog backend/Makefile.am backend/r...
From:       Rob Savoye <rob () welcomehome ! org>
Date:       2006-02-26 15:49:30
Message-ID: E1FDO9K-0006Rc-VY () savannah ! gnu ! org
[Download RAW message or body]

CVSROOT:	/sources/gnash
Module name:	gnash
Branch: 	
Changes by:	Rob Savoye <rsavoye@savannah.gnu.org>	06/02/26 15:49:30

Modified files:
	.              : ChangeLog 
	backend        : Makefile.am render_handler_ogl.cpp 
	doc            : omf.make 
	libamf         : Makefile.am 
	libbase        : Makefile.am component_hackery.cpp config.cpp 
	                 container.cpp container.h demo.cpp demo.h 
	                 dlmalloc.c dlmalloc.h file_util.cpp file_util.h 
	                 image.cpp image_filters.cpp jpeg.cpp membuf.cpp 
	                 membuf.h ogl.cpp png_helper.cpp postscript.cpp 
	                 test_ogl.cpp triangulate_float.cpp 
	                 triangulate_sint32.cpp tu_file.cpp 
	                 tu_file_SDL.cpp tu_random.cpp tu_swap.h 
	                 tu_timer.cpp tu_types.cpp utf8.cpp utility.cpp 
	                 utility.h zlib_adapter.cpp 
	libgeometry    : Makefile.am axial_box.cpp axial_box.h 
	                 collision.cpp collision.h kd_tree_dynamic.cpp 
	                 kd_tree_dynamic.h 
	macros         : jpeg.m4 opengl.m4 png.m4 pthreads.m4 sdl.m4 
	server         : Makefile.am 
	utilities      : Makefile.am 

Log message:
	* libbase/dlmalloc.h: Include stdlib.h instead of the depreciated
	malloc.h.
	* libbase/tu_swap.h: OpenBSD defines swap macros with the same
	name as these functions, so use our implementation intead.
	* macros/pthread.h: Reqwrite to handle weird NetBSD pth versus
	Pthread problem.
	* macros/sdl.m4: Throw out compile test for something simpler and
	more portable.
	* utilities/Makefile.am: Add pthread header and library.
	* server/Makefile.am: Add pthread header and library.
	* backend/Makefile.am: Add pthread header and library.
	* libbase/container.h: Add ugly NetBSD specific hack so it'll use
	pthread, not Pth if both are installed.
	* libgeometry/kd_tree_dynamic.cp: Include stdio so __sputc() is
	defined on NetBSD.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/ChangeLog.diff?tr1=1.159&tr2=1.160&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/backend/Makefile.am.diff?tr1=1.14&tr2=1.15&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/backend/render_handler_ogl.cpp.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/doc/omf.make.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libamf/Makefile.am.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/Makefile.am.diff?tr1=1.11&tr2=1.12&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/component_hackery.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/config.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/container.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/container.h.diff?tr1=1.6&tr2=1.7&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/demo.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/demo.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/dlmalloc.c.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/dlmalloc.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/file_util.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/file_util.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/image.cpp.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/image_filters.cpp.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/jpeg.cpp.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/membuf.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/membuf.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/ogl.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/png_helper.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/postscript.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/test_ogl.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/triangulate_float.cpp.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/triangulate_sint32.cpp.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_file.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_file_SDL.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_random.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_swap.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_timer.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/tu_types.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/utf8.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/utility.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/utility.h.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libbase/zlib_adapter.cpp.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/Makefile.am.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/axial_box.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/axial_box.h.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/collision.cpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/collision.h.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/kd_tree_dynamic.cpp.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/libgeometry/kd_tree_dynamic.h.diff?tr1=1.3&tr2=1.4&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/macros/jpeg.m4.diff?tr1=1.7&tr2=1.8&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/macros/opengl.m4.diff?tr1=1.10&tr2=1.11&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/macros/png.m4.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/macros/pthreads.m4.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/macros/sdl.m4.diff?tr1=1.9&tr2=1.10&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/server/Makefile.am.diff?tr1=1.21&tr2=1.22&r1=text&r2=text
 http://cvs.savannah.gnu.org/viewcvs/gnash/gnash/utilities/Makefile.am.diff?tr1=1.9&tr2=1.10&r1=text&r2=text


Patches:
Index: gnash/ChangeLog
diff -u gnash/ChangeLog:1.159 gnash/ChangeLog:1.160
--- gnash/ChangeLog:1.159	Sat Feb 25 15:27:35 2006
+++ gnash/ChangeLog	Sun Feb 26 15:49:29 2006
@@ -1,9 +1,27 @@
+2006-02-26  Rob Savoye  <rob@wharfrat.welcomehome.org>
+
+	* libbase/dlmalloc.h: Include stdlib.h instead of the depreciated
+	malloc.h.
+	* libbase/tu_swap.h: OpenBSD defines swap macros with the same
+	name as these functions, so use our implementation intead.
+	* macros/pthread.h: Reqwrite to handle weird NetBSD pth versus
+	Pthread problem.
+	* macros/sdl.m4: Throw out compile test for something simpler and
+	more portable.
+	* utilities/Makefile.am: Add pthread header and library.
+	* server/Makefile.am: Add pthread header and library.
+	* backend/Makefile.am: Add pthread header and library.
+	* libbase/container.h: Add ugly NetBSD specific hack so it'll use
+	pthread, not Pth if both are installed.
+	* libgeometry/kd_tree_dynamic.cp: Include stdio so __sputc() is
+	defined on NetBSD.
+
 2006-02-25  Jim Garrison  <garrison@users.sourceforge.net>
 
 	* backend/render_handler_d3d.cpp: substituted array<> with
-	std::vector<>
+	std::vector<>.
 	* backend/render_handler_xbox.cpp: substituted array<> with
-	std::vector<>
+	std::vector<>.
 	* libbase/container.cpp: substituted array<> with std::vector<>
 	* server/morph.cpp: substituted array<> with std::vector<>
 	* server/morph.h: substituted array<> with std::vector<>
Index: gnash/backend/Makefile.am
diff -u gnash/backend/Makefile.am:1.14 gnash/backend/Makefile.am:1.15
--- gnash/backend/Makefile.am:1.14	Fri Feb  3 19:26:51 2006
+++ gnash/backend/Makefile.am	Sun Feb 26 15:49:29 2006
@@ -33,12 +33,14 @@
         $(OGG_LIBS)		\
         $(LIBXML_LIBS)		\
         $(SDL_LIBS)		\
-        $(SDL_CFLAGS)		\
         $(SDL_MIXER_LIBS)	\
         $(OPENGL_LIBS)		\
+	$(GLEXT_LIBS)		\
+	$(GTK2_LIBS)		\
 	$(X_LIBS)		\
 	$(DMALLOC_LIBS)		\
-	$(MP3_LIBS)
+	$(MP3_LIBS)		\
+	$(PTHREAD_LIBS)
 
 INCLUDES = -I.. \
         -I$(top_srcdir) 	\
@@ -46,11 +48,16 @@
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)/backend \
         -I$(top_srcdir)/libgeometry \
-        $(SDL_CFLAGS)	\
+	$(PTHREAD_CFLAGS)	\
+        $(SDL_CFLAGS)		\
         $(SDL_MIXER_CFLAGS)	\
 	$(LIBXML_CFLAGS)        \
 	$(OPENGL_CFLAGS)	\
+	$(GLEXT_CFLAGS)		\
+	$(GTK2_CFLAGS)		\
 	$(DMALLOC_CFLAGS)	\
+	$(PNG_CFLAGS)		\
+	$(JPEG_CFLAGS)		\
 	$(MP3_CFLAGS)		\
 	$(OGG_CFLAGS)
 
Index: gnash/backend/render_handler_ogl.cpp
diff -u gnash/backend/render_handler_ogl.cpp:1.6 \
                gnash/backend/render_handler_ogl.cpp:1.7
--- gnash/backend/render_handler_ogl.cpp:1.6	Wed Feb 15 23:35:53 2006
+++ gnash/backend/render_handler_ogl.cpp	Sun Feb 26 15:49:29 2006
@@ -397,47 +397,47 @@
 		}
 
 		// Old unused code.  Might get revived someday.
-		#if 0
-				// See if we want to, and can, use multitexture
-				// antialiasing.
-				s_multitexture_antialias = false;
-				if (m_enable_antialias)
-				{
-					int	tex_units = 0;
-					glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &tex_units);
-					if (tex_units >= 2)
-					{
-						s_multitexture_antialias = true;
-					}
-
-					// Make sure we have an edge texture available.
-					if (s_multitexture_antialias == true
-						&& s_edge_texture_id == 0)
-					{
-						// Very simple texture: 2 texels wide, 1 texel high.
-						// Both texels are white; left texel is all clear, right texel is all opaque.
-						unsigned char	edge_data[8] = { 255, 255, 255, 0, 255, 255, 255, 255 };
-
-						ogl::active_texture(GL_TEXTURE1_ARB);
-						glEnable(GL_TEXTURE_2D);
-						glGenTextures(1, &s_edge_texture_id);
-						glBindTexture(GL_TEXTURE_2D, s_edge_texture_id);
-
-						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, \
                edge_data);
-
-						glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	// @@ should we \
                use a 1D texture???
-
-						glDisable(GL_TEXTURE_2D);
-						ogl::active_texture(GL_TEXTURE0_ARB);
-						glDisable(GL_TEXTURE_2D);
-					}
-				}
-		#endif // 0
+// #if 0
+// 				// See if we want to, and can, use multitexture
+// 				// antialiasing.
+// 				s_multitexture_antialias = false;
+// 				if (m_enable_antialias)
+// 				{
+// 					int	tex_units = 0;
+// 					glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &tex_units);
+// 					if (tex_units >= 2)
+// 					{
+// 						s_multitexture_antialias = true;
+// 					}
+
+// 					// Make sure we have an edge texture available.
+// 					if (s_multitexture_antialias == true
+// 						&& s_edge_texture_id == 0)
+// 					{
+// 						// Very simple texture: 2 texels wide, 1 texel high.
+// 						// Both texels are white; left texel is all clear, right texel is all \
opaque. +// 						unsigned char	edge_data[8] = { 255, 255, 255, 0, 255, 255, 255, 255 \
}; +
+// 						ogl::active_texture(GL_TEXTURE1_ARB);
+// 						glEnable(GL_TEXTURE_2D);
+// 						glGenTextures(1, &s_edge_texture_id);
+// 						glBindTexture(GL_TEXTURE_2D, s_edge_texture_id);
+
+// 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+// 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+// 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+// 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+// 						glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, \
edge_data); +
+// 						glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	// @@ should \
we use a 1D texture??? +
+// 						glDisable(GL_TEXTURE_2D);
+// 						ogl::active_texture(GL_TEXTURE0_ARB);
+// 						glDisable(GL_TEXTURE_2D);
+// 					}
+// 				}
+// #endif // 0
 	}
 
 
Index: gnash/doc/omf.make
diff -u gnash/doc/omf.make:1.6 gnash/doc/omf.make:1.7
--- gnash/doc/omf.make:1.6	Thu Feb  9 15:15:28 2006
+++ gnash/doc/omf.make	Sun Feb 26 15:49:29 2006
@@ -33,7 +33,7 @@
 
 omf_timestamp: $(omffile)
 	@for file in $(omffile); do \
-	    $(SCROLLINSTALL) $(docdir)/$(docname).xml $(srcdir)/$$file \
$(srcdir)/$$file.out; \ +	    $(SCROLLINSTALL) $(docdir)/$(docname).xml \
$(srcdir)/$$file $$file.out; \  done
 	touch omf_timestamp
 
@@ -41,7 +41,7 @@
 if GHELP
 	$(mkinstalldirs) $(DESTDIR)$(omf_dest_dir)
 	for file in $(omffile); do \
-	  $(INSTALL_DATA) $(srcdir)/$$file.out $(DESTDIR)$(omf_dest_dir)/$$file; \
+	  $(INSTALL_DATA) $$file.out $(DESTDIR)$(omf_dest_dir)/$$file; \
 	done
 	if test x"$(USER)" = x"root" ; then \
 	    $(SCROLLUPDATE) -v -p $(DESTDIR)$(scrollkeeper_localstate_dir) -o \
                $(DESTDIR)$(omf_dest_dir);\
Index: gnash/libamf/Makefile.am
diff -u gnash/libamf/Makefile.am:1.2 gnash/libamf/Makefile.am:1.3
--- gnash/libamf/Makefile.am:1.2	Mon Feb 13 17:48:28 2006
+++ gnash/libamf/Makefile.am	Sun Feb 26 15:49:29 2006
@@ -31,16 +31,15 @@
 	$(PNG_LIBS)	    \
         $(LIBXML_LIBS)      \
 	$(DMALLOC_LIBS)	    \
-	$(MP3_LIBS)	    \
+	$(MAD_LIBS)	    \
 	$(OGG_LIBS)
 
 
 # AM_LDFLAGS  = $(OPENGL_LIBNS) $(SDL_LIBS)
 
 lib_LTLIBRARIES = libgnashamf.la
-libgnashamf_la_SOURCES = amf.cpp
-
-noinst_HEADERS = amf.h
+libgnashamf_la_SOURCES = amf.cpp amfutf8.h amf.h
+# noinst_HEADERS = amf.h amfutf8.h
 
 INCLUDES = -I.. -I$(srcdir) \
 	-I$(top_srcdir)/server
Index: gnash/libbase/Makefile.am
diff -u gnash/libbase/Makefile.am:1.11 gnash/libbase/Makefile.am:1.12
--- gnash/libbase/Makefile.am:1.11	Fri Feb  3 20:50:27 2006
+++ gnash/libbase/Makefile.am	Sun Feb 26 15:49:29 2006
@@ -36,9 +36,10 @@
 endif
 
 INCLUDES = -I.. -I$(srcdir)	\
-        $(LIBPNG_INCLUDE)	\
-        $(ZLIB_INCLUDE)		\
-        $(JPEGLIB_INCLUDE)	\
+	$(PTHREAD_CFLAGS)	\
+        $(PNG_CFLAGS)		\
+        $(ZLIB_CFLAGS)		\
+        $(JPEG_CFLAGS)		\
         $(LIBXML_CFLAGS)	\
 	$(OPENGL_CFLAGS)	\
         -I$(top_srcdir)
Index: gnash/libbase/component_hackery.cpp
diff -u gnash/libbase/component_hackery.cpp:1.1 \
                gnash/libbase/component_hackery.cpp:1.2
--- gnash/libbase/component_hackery.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/component_hackery.cpp	Sun Feb 26 15:49:29 2006
@@ -1,47 +1,47 @@
-// Thatcher Ulrich <tu@tulrich.com> 2003 -*- coding: utf-8;-*-
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-
-#include <vector>
-
-
-class Component {
-//	typedef vector<Component>::iterator;
-
-	template< class interface >
-	class iterator {
-
-
-		operator++()
-		{
-		}
-	};
-};
-
-
-class SpecialInterface : public Component {
-	void	DoStuff()
-	{
-		printf( "doing stuff.\n" );
-	}
-};
-
-
-class Actor {
-	
-};
-
-
-#define foreach( _decl, _p, _actor )	\
-	for ( _decl _p, Component::iterator _i( _p ) = _actor.components.get_first( _p ); \
                _i != _actor.components.end(); ++ _i, _p = *_i )
-
-
-
-foreach(SpecialInterface*, p, actors)
-{
-	p->DoStuff();
-	some_list.push_back( p );
-}
-
+// Thatcher Ulrich <tu@tulrich.com> 2003 -*- coding: utf-8;-*-
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+
+#include <vector>
+
+
+class Component {
+//	typedef vector<Component>::iterator;
+
+	template< class interface >
+	class iterator {
+
+
+		operator++()
+		{
+		}
+	};
+};
+
+
+class SpecialInterface : public Component {
+	void	DoStuff()
+	{
+		printf( "doing stuff.\n" );
+	}
+};
+
+
+class Actor {
+	
+};
+
+
+#define foreach( _decl, _p, _actor )	\
+	for ( _decl _p, Component::iterator _i( _p ) = _actor.components.get_first( _p ); \
_i != _actor.components.end(); ++ _i, _p = *_i ) +
+
+
+foreach(SpecialInterface*, p, actors)
+{
+	p->DoStuff();
+	some_list.push_back( p );
+}
+
Index: gnash/libbase/config.cpp
diff -u gnash/libbase/config.cpp:1.1 gnash/libbase/config.cpp:1.2
--- gnash/libbase/config.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/config.cpp	Sun Feb 26 15:49:29 2006
@@ -1,449 +1,449 @@
-// config.cpp	-- by Thatcher Ulrich <tu@tulrich.com> 22 July 2001
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Configuration glue.  C++ interface to Lua scripting library.
-
-// @@ move/finish this later...
-#if 0
-
-
-#include "config.h"
-extern "C" {
-#include <lualib.h>
-}
-#include "utility.h"
-
-
-namespace config {
-
-
-static const int	LUA_STACK_SIZE = 2048;
-
-
-static bool	s_open = false;
-
-lua_State*	L = NULL;
-int	g_cfloat_tag = 0;
-
-
-static int	cfloat_get( lua_State* L )
-// Lua CFunction which returns the value of the cfloat passed in on
-// the top of the Lua stack.  Attach this to the "getglobal" event for
-// cfloats.
-{
-	// arg 1: varname
-	// arg 2: raw var value (in this case the cfloat*)
-
-	cfloat*	cf = static_cast<cfloat*>( lua_touserdata( L, 2 ) );
-	lua_pushnumber( L, float( *cf ) );
-
-	return 1;
-}
-
-
-static int	cfloat_set( lua_State* L )
-// Lua CFunction which sets the value of the given cfloat to the given lua
-// number.
-{
-	// arg 1: varname
-	// arg 2: previous var value (in this case the cfloat*)
-	// arg 3: new var value
-
-	cfloat*	cf = static_cast<cfloat*>( lua_touserdata( L, 2 ) );
-	*cf = float(lua_tonumber( L, 3 ));
-
-	return 0;
-}
-
-
-void	open()
-// Initialize the config subsystem.  ...
-{
-	if ( s_open == true ) return;
-
-	//
-	// Initialize Lua.
-	//
-	L = lua_open( LUA_STACK_SIZE );
-
-	// Init the standard Lua libs.
-	lua_baselibopen( L );
-	lua_iolibopen( L );
-	lua_strlibopen( L );
-	lua_mathlibopen( L );
-
-	//
-	// Attach the cfloat hooks
-	//
-
-	g_cfloat_tag = lua_newtag( config::L );
-
-	lua_pushcfunction( config::L, cfloat_get );
-	lua_settagmethod( config::L, config::g_cfloat_tag, "getglobal" );	// xxx is \
                "getglobal" right?
-
-	lua_pushcfunction( config::L, cfloat_set );
-	lua_settagmethod( config::L, config::g_cfloat_tag, "setglobal" );	// xxx is \
                "setglobal" right?
-
-	// set tag methods for add, sub, mul, div, pow, unm, lt
-
-	//	gettable{ min, max, default, comment }
-	//	settable{ min, max, default, comment }
-
-	s_open = true;
-}
-
-
-void	close()
-// Close the config subsystem.
-{
-	// Nothing really to do here.
-}
-
-
-}; // end namespace config
-
-
-
-//
-// cvar
-//
-
-
-void	cvar::init( const char* name )
-// Initializes a chain of references to Lua strings, for looking up
-// the value of the specified name.
-//
-// The name can contain embedded '.' separators, to refer to values
-// within nested tables.  For example, a name of
-// "player.spaceship.health" would refer to the "health" member of the
-// "player.spaceship" table (where the "player.spaceship" table is
-// found by looking up the "spaceship" member of the "player" table).
-{
-	config::open();
-
-	// Count the number of keys in the name (keys are separated by '.'
-	// chars).
-	m_lua_key_count = 1;
-	const char*	p = name;
-	while (*p) {
-		if (*p == '.') {
-			m_lua_key_count++;
-		}
-		p++;
-	}
-
-	// Allocate array for references.
-	m_lua_key_reference = new int[m_lua_key_count];
-
-	// Now initialize the keys.
-	const char*	varname = name;
-
-	int	key_index = 0;
-	p = name;
-	while (*p) {
-		if (*p == '.') {
-			if (varname == p) {
-				// null string for a key.
-				// warning("something or other");
-				assert(0);	// TODO: recover somehow.
-			}
-
-			// Reference the name of the table.
-			lua_pushlstring(config::L, varname, p - varname);
-			m_lua_key_reference[key_index] = lua_ref(config::L, 1);
-
-			key_index++;
-			varname = p + 1;
-		}
-		p++;
-	}
-
-	// Get a reference to the last key name.
-	assert(varname != p);	// else...
-	lua_pushlstring(config::L, varname, p - varname);
-	m_lua_key_reference[key_index] = lua_ref(config::L, 1);
-}
-
-
-void	cvar::push_table_and_key() const
-// Traverse our key names, and push the table and keyname of our value
-// onto the Lua stack.
-//
-// Creates empty tables if necessary to fill in missing links in the
-// chain.
-{
-	lua_getglobals(config::L);	// Start with the global table.
-
-	// Chain through additional tables.
-	int	i;
-	for (i = 0; i < m_lua_key_count - 1; i++) {
-		lua_getref(config::L, m_lua_key_reference[i]);
-		lua_gettable(config::L, -2);
-
-		if (lua_isnil(config::L, -1)) {
-			// Tablename is undefined, so create a new empty table for it.
-			lua_pop(config::L, 1);	// pop the nil.
-			lua_getref(config::L, m_lua_key_reference[i]);
-			lua_newtable(config::L);
-			lua_settable(config::L, -3);
-			
-			// Get the newly created table and put it on the top
-			// of stack.
-			lua_getref(config::L, m_lua_key_reference[i]);
-			lua_gettable(config::L, -2);
-		}
-
-		lua_remove(config::L, -2);	// previous table that we just chained from
-	}
-
-	// push the final key, on top of the table we just pushed.
-	lua_getref(config::L, m_lua_key_reference[i]);
-}
-
-
-cvar::cvar( const char* name )
-// Constructor; leaves existing value, if any (otherwise it's 'nil').
-{
-	init(name);
-}
-
-
-cvar::cvar( const char* name, const cvalue& val )
-// Constructor; initializes to given Lua value.
-{
-	init(name);
-	*this = val;	// invoke operator=(const cvalue& val)
-}
-
-
-cvar::cvar( const char* name, const char* val )
-// Constructor; initializes to given string value.
-{
-	init(name);
-	*this = val;	// invoke operator=(const char*)
-}
-
-
-cvar::cvar( const char* name, float val )
-// Constructor; initializes to given float value.
-{
-	init(name);
-	*this = val;	// invoke operator=(float f)
-}
-
-
-cvar::~cvar()
-// Destructor; make sure our references are released.
-{
-	// drop lua references, so table & name can be gc'd if not
-	// referenced elsewhere.
-
-	for (int i = 0; i < m_lua_key_count; i++) {
-		lua_unref(config::L, m_lua_key_reference[i]);
-	}
-
-	m_lua_key_count = 0;
-	m_lua_key_reference = NULL;
-}
-
-
-#if 0
-const char*	cvar::get_name() const
-// Return our name.  The char[] storage is valid at least as long
-// as this variable is alive.
-{
-	lua_getref( config::L, m_lua_name_reference );
-	return lua_tostring( config::L, -1 );
-}
-#endif // 0
-
-
-cvar::operator float() const
-// Convert the variable to a float and return it.
-{
-	push_table_and_key();
-	lua_gettable( config::L, -2 );	// get the value of our variable from the table.
-	float	f = float(lua_tonumber( config::L, -1 ));
-	lua_pop( config::L, 2 );	// pop table & the number result.
-
-	return f;
-}
-
-
-void	cvar::operator=( float f )
-// Assign a float to this lua variable.
-{
-	push_table_and_key();
-	lua_pushnumber( config::L, f );
-	lua_settable( config::L, -3 );
-	lua_pop( config::L, 1 );	// pop the table.
-}
-
-
-cvar::operator const char*() const
-// Convert to a string.
-//
-// xxx there are garbage-collection issues here!  Returned string
-// has no valid reference once stack is cleared!
-// Possible fixes:
-// - return some kind of proxy object that holds a locked Lua ref
-// - return a C++ "string" value; i.e. make a copy
-// - hold a locked reference in this instance; drop it on next call to this \
                conversion operator (blech).
-{
-	push_table_and_key();
-	lua_gettable( config::L, -2 );	// get the value of our variable from the table.
-	const char*	c = lua_tostring( config::L, -1 );
-	// TODO: grab a locked reference to the string!  Or copy it!
-	lua_pop( config::L, 2 );	// discard table & the string result.
-
-	return c;
-}
-
-
-void	cvar::operator=( const cvalue& val )
-// Assign a Lua value to this lua global variable.
-{
-	push_table_and_key();
-	val.lua_push();
-	lua_settable( config::L, -3 );
-	lua_pop( config::L, 1 );	// pop the table.
-}
-
-
-void	cvar::operator=( const char* s )
-// Assign a string to this lua variable.
-{
-	push_table_and_key();
-	lua_pushstring( config::L, s );
-	lua_settable( config::L, -3 );
-	lua_pop( config::L, 1 );	// pop the table.
-}
-
-
-cvar::operator cvalue() const
-// Return a reference to our value.
-{
-	push_table_and_key();
-	cvalue	c = cvalue::lua_stacktop_reference();
-	lua_pop( config::L, 1 );	// pop the table.
-
-	return c;
-}
-
-
-//	void	operator=( const cvar c );
-
-
-
-//
-// cvalue
-//
-
-
-cvalue::cvalue( const char* lua_constructor )
-// Evaluates the given code and takes a reference to the result.
-{
-	config::open();
-
-	lua_dostring( config::L, lua_constructor );	// @@ could check for error return \
                codes, presence of return value, etc.
-	m_lua_ref = lua_ref( config::L, 1 );
-}
-
-
-cvalue::cvalue( const cvalue& c )
-{
-	lua_getref( config::L, c.m_lua_ref );
-	m_lua_ref = lua_ref( config::L, 1 );
-}
-
-
-cvalue::cvalue()
-// Creates an reference to nothing.  Use this only in special
-// circumstances; i.e. when you're about to set m_lua_ref manually.
-{
-	config::open();
-	m_lua_ref = LUA_NOREF;
-}
-
-
-cvalue	cvalue::lua_stacktop_reference()
-// Factory function; pops the value off the top of the Lua stack, and
-// return a cvalue that references the popped value.
-{
-	cvalue	c;
-	c.m_lua_ref = lua_ref( config::L, 1 );
-	return c;
-}
-
-
-cvalue::~cvalue()
-// Drop our Lua reference, to allow our value to be gc'd.
-{
-	lua_unref( config::L, m_lua_ref );
-	m_lua_ref = LUA_NOREF;
-}
-
-
-void	cvalue::lua_push() const
-// Push our value onto the top of the Lua stack.
-{
-	assert( m_lua_ref != LUA_NOREF );
-	lua_getref( config::L, m_lua_ref );
-}
-
-
-void	cvalue::operator=( const char* str )
-// Transfer our reference to the given string.
-{
-	lua_unref( config::L, m_lua_ref );
-	lua_pushstring( config::L, str );
-	m_lua_ref = lua_ref( config::L, 1 );
-}
-
-
-void	cvalue::operator=( const cvalue& c )
-// Reference the thing that c references.
-{
-	lua_unref( config::L, m_lua_ref );
-	lua_getref( config::L, c.m_lua_ref );
-	m_lua_ref = lua_ref( config::L, 1 );
-}
-
-
-cvalue::operator float() const
-// Converts this Lua value to a number, and returns it.
-{
-	lua_getref( config::L, m_lua_ref );
-	float	f = float(lua_tonumber( config::L, -1 ));
-	lua_pop( config::L, 1 );
-	return f;
-}
-
-
-cvalue::operator const char*() const
-// Converts this Lua value to a string, and returns it.
-{
-	lua_getref( config::L, m_lua_ref );
-	const char*	str = lua_tostring( config::L, -1 );
-	lua_pop( config::L, 1 );	// @@ I'm pretty sure this imperils the string, if we just \
                had to do a tostring() conversion!  Look into this, and/or make a \
                copy of the string.
-	return str;
-}
-
-
-cvalue	cvalue::get( const char* index )
-// Does a table lookup.  *this should be a Lua table, and index is its
-// key.
-{
-	lua_getref( config::L, m_lua_ref );
-	lua_pushstring( config::L, index );
-	lua_gettable( config::L, -2 );
-	cvalue	c = cvalue::lua_stacktop_reference();	// references the value on the top of \
                the Lua stack.
-	lua_pop( config::L, 1 );
-
-	return c;
-}
-
-
-#endif // 0
+// config.cpp	-- by Thatcher Ulrich <tu@tulrich.com> 22 July 2001
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Configuration glue.  C++ interface to Lua scripting library.
+
+// @@ move/finish this later...
+#if 0
+
+
+#include "config.h"
+extern "C" {
+#include <lualib.h>
+}
+#include "utility.h"
+
+
+namespace config {
+
+
+static const int	LUA_STACK_SIZE = 2048;
+
+
+static bool	s_open = false;
+
+lua_State*	L = NULL;
+int	g_cfloat_tag = 0;
+
+
+static int	cfloat_get( lua_State* L )
+// Lua CFunction which returns the value of the cfloat passed in on
+// the top of the Lua stack.  Attach this to the "getglobal" event for
+// cfloats.
+{
+	// arg 1: varname
+	// arg 2: raw var value (in this case the cfloat*)
+
+	cfloat*	cf = static_cast<cfloat*>( lua_touserdata( L, 2 ) );
+	lua_pushnumber( L, float( *cf ) );
+
+	return 1;
+}
+
+
+static int	cfloat_set( lua_State* L )
+// Lua CFunction which sets the value of the given cfloat to the given lua
+// number.
+{
+	// arg 1: varname
+	// arg 2: previous var value (in this case the cfloat*)
+	// arg 3: new var value
+
+	cfloat*	cf = static_cast<cfloat*>( lua_touserdata( L, 2 ) );
+	*cf = float(lua_tonumber( L, 3 ));
+
+	return 0;
+}
+
+
+void	open()
+// Initialize the config subsystem.  ...
+{
+	if ( s_open == true ) return;
+
+	//
+	// Initialize Lua.
+	//
+	L = lua_open( LUA_STACK_SIZE );
+
+	// Init the standard Lua libs.
+	lua_baselibopen( L );
+	lua_iolibopen( L );
+	lua_strlibopen( L );
+	lua_mathlibopen( L );
+
+	//
+	// Attach the cfloat hooks
+	//
+
+	g_cfloat_tag = lua_newtag( config::L );
+
+	lua_pushcfunction( config::L, cfloat_get );
+	lua_settagmethod( config::L, config::g_cfloat_tag, "getglobal" );	// xxx is \
"getglobal" right? +
+	lua_pushcfunction( config::L, cfloat_set );
+	lua_settagmethod( config::L, config::g_cfloat_tag, "setglobal" );	// xxx is \
"setglobal" right? +
+	// set tag methods for add, sub, mul, div, pow, unm, lt
+
+	//	gettable{ min, max, default, comment }
+	//	settable{ min, max, default, comment }
+
+	s_open = true;
+}
+
+
+void	close()
+// Close the config subsystem.
+{
+	// Nothing really to do here.
+}
+
+
+}; // end namespace config
+
+
+
+//
+// cvar
+//
+
+
+void	cvar::init( const char* name )
+// Initializes a chain of references to Lua strings, for looking up
+// the value of the specified name.
+//
+// The name can contain embedded '.' separators, to refer to values
+// within nested tables.  For example, a name of
+// "player.spaceship.health" would refer to the "health" member of the
+// "player.spaceship" table (where the "player.spaceship" table is
+// found by looking up the "spaceship" member of the "player" table).
+{
+	config::open();
+
+	// Count the number of keys in the name (keys are separated by '.'
+	// chars).
+	m_lua_key_count = 1;
+	const char*	p = name;
+	while (*p) {
+		if (*p == '.') {
+			m_lua_key_count++;
+		}
+		p++;
+	}
+
+	// Allocate array for references.
+	m_lua_key_reference = new int[m_lua_key_count];
+
+	// Now initialize the keys.
+	const char*	varname = name;
+
+	int	key_index = 0;
+	p = name;
+	while (*p) {
+		if (*p == '.') {
+			if (varname == p) {
+				// null string for a key.
+				// warning("something or other");
+				assert(0);	// TODO: recover somehow.
+			}
+
+			// Reference the name of the table.
+			lua_pushlstring(config::L, varname, p - varname);
+			m_lua_key_reference[key_index] = lua_ref(config::L, 1);
+
+			key_index++;
+			varname = p + 1;
+		}
+		p++;
+	}
+
+	// Get a reference to the last key name.
+	assert(varname != p);	// else...
+	lua_pushlstring(config::L, varname, p - varname);
+	m_lua_key_reference[key_index] = lua_ref(config::L, 1);
+}
+
+
+void	cvar::push_table_and_key() const
+// Traverse our key names, and push the table and keyname of our value
+// onto the Lua stack.
+//
+// Creates empty tables if necessary to fill in missing links in the
+// chain.
+{
+	lua_getglobals(config::L);	// Start with the global table.
+
+	// Chain through additional tables.
+	int	i;
+	for (i = 0; i < m_lua_key_count - 1; i++) {
+		lua_getref(config::L, m_lua_key_reference[i]);
+		lua_gettable(config::L, -2);
+
+		if (lua_isnil(config::L, -1)) {
+			// Tablename is undefined, so create a new empty table for it.
+			lua_pop(config::L, 1);	// pop the nil.
+			lua_getref(config::L, m_lua_key_reference[i]);
+			lua_newtable(config::L);
+			lua_settable(config::L, -3);
+			
+			// Get the newly created table and put it on the top
+			// of stack.
+			lua_getref(config::L, m_lua_key_reference[i]);
+			lua_gettable(config::L, -2);
+		}
+
+		lua_remove(config::L, -2);	// previous table that we just chained from
+	}
+
+	// push the final key, on top of the table we just pushed.
+	lua_getref(config::L, m_lua_key_reference[i]);
+}
+
+
+cvar::cvar( const char* name )
+// Constructor; leaves existing value, if any (otherwise it's 'nil').
+{
+	init(name);
+}
+
+
+cvar::cvar( const char* name, const cvalue& val )
+// Constructor; initializes to given Lua value.
+{
+	init(name);
+	*this = val;	// invoke operator=(const cvalue& val)
+}
+
+
+cvar::cvar( const char* name, const char* val )
+// Constructor; initializes to given string value.
+{
+	init(name);
+	*this = val;	// invoke operator=(const char*)
+}
+
+
+cvar::cvar( const char* name, float val )
+// Constructor; initializes to given float value.
+{
+	init(name);
+	*this = val;	// invoke operator=(float f)
+}
+
+
+cvar::~cvar()
+// Destructor; make sure our references are released.
+{
+	// drop lua references, so table & name can be gc'd if not
+	// referenced elsewhere.
+
+	for (int i = 0; i < m_lua_key_count; i++) {
+		lua_unref(config::L, m_lua_key_reference[i]);
+	}
+
+	m_lua_key_count = 0;
+	m_lua_key_reference = NULL;
+}
+
+
+#if 0
+const char*	cvar::get_name() const
+// Return our name.  The char[] storage is valid at least as long
+// as this variable is alive.
+{
+	lua_getref( config::L, m_lua_name_reference );
+	return lua_tostring( config::L, -1 );
+}
+#endif // 0
+
+
+cvar::operator float() const
+// Convert the variable to a float and return it.
+{
+	push_table_and_key();
+	lua_gettable( config::L, -2 );	// get the value of our variable from the table.
+	float	f = float(lua_tonumber( config::L, -1 ));
+	lua_pop( config::L, 2 );	// pop table & the number result.
+
+	return f;
+}
+
+
+void	cvar::operator=( float f )
+// Assign a float to this lua variable.
+{
+	push_table_and_key();
+	lua_pushnumber( config::L, f );
+	lua_settable( config::L, -3 );
+	lua_pop( config::L, 1 );	// pop the table.
+}
+
+
+cvar::operator const char*() const
+// Convert to a string.
+//
+// xxx there are garbage-collection issues here!  Returned string
+// has no valid reference once stack is cleared!
+// Possible fixes:
+// - return some kind of proxy object that holds a locked Lua ref
+// - return a C++ "string" value; i.e. make a copy
+// - hold a locked reference in this instance; drop it on next call to this \
conversion operator (blech). +{
+	push_table_and_key();
+	lua_gettable( config::L, -2 );	// get the value of our variable from the table.
+	const char*	c = lua_tostring( config::L, -1 );
+	// TODO: grab a locked reference to the string!  Or copy it!
+	lua_pop( config::L, 2 );	// discard table & the string result.
+
+	return c;
+}
+
+
+void	cvar::operator=( const cvalue& val )
+// Assign a Lua value to this lua global variable.
+{
+	push_table_and_key();
+	val.lua_push();
+	lua_settable( config::L, -3 );
+	lua_pop( config::L, 1 );	// pop the table.
+}
+
+
+void	cvar::operator=( const char* s )
+// Assign a string to this lua variable.
+{
+	push_table_and_key();
+	lua_pushstring( config::L, s );
+	lua_settable( config::L, -3 );
+	lua_pop( config::L, 1 );	// pop the table.
+}
+
+
+cvar::operator cvalue() const
+// Return a reference to our value.
+{
+	push_table_and_key();
+	cvalue	c = cvalue::lua_stacktop_reference();
+	lua_pop( config::L, 1 );	// pop the table.
+
+	return c;
+}
+
+
+//	void	operator=( const cvar c );
+
+
+
+//
+// cvalue
+//
+
+
+cvalue::cvalue( const char* lua_constructor )
+// Evaluates the given code and takes a reference to the result.
+{
+	config::open();
+
+	lua_dostring( config::L, lua_constructor );	// @@ could check for error return \
codes, presence of return value, etc. +	m_lua_ref = lua_ref( config::L, 1 );
+}
+
+
+cvalue::cvalue( const cvalue& c )
+{
+	lua_getref( config::L, c.m_lua_ref );
+	m_lua_ref = lua_ref( config::L, 1 );
+}
+
+
+cvalue::cvalue()
+// Creates an reference to nothing.  Use this only in special
+// circumstances; i.e. when you're about to set m_lua_ref manually.
+{
+	config::open();
+	m_lua_ref = LUA_NOREF;
+}
+
+
+cvalue	cvalue::lua_stacktop_reference()
+// Factory function; pops the value off the top of the Lua stack, and
+// return a cvalue that references the popped value.
+{
+	cvalue	c;
+	c.m_lua_ref = lua_ref( config::L, 1 );
+	return c;
+}
+
+
+cvalue::~cvalue()
+// Drop our Lua reference, to allow our value to be gc'd.
+{
+	lua_unref( config::L, m_lua_ref );
+	m_lua_ref = LUA_NOREF;
+}
+
+
+void	cvalue::lua_push() const
+// Push our value onto the top of the Lua stack.
+{
+	assert( m_lua_ref != LUA_NOREF );
+	lua_getref( config::L, m_lua_ref );
+}
+
+
+void	cvalue::operator=( const char* str )
+// Transfer our reference to the given string.
+{
+	lua_unref( config::L, m_lua_ref );
+	lua_pushstring( config::L, str );
+	m_lua_ref = lua_ref( config::L, 1 );
+}
+
+
+void	cvalue::operator=( const cvalue& c )
+// Reference the thing that c references.
+{
+	lua_unref( config::L, m_lua_ref );
+	lua_getref( config::L, c.m_lua_ref );
+	m_lua_ref = lua_ref( config::L, 1 );
+}
+
+
+cvalue::operator float() const
+// Converts this Lua value to a number, and returns it.
+{
+	lua_getref( config::L, m_lua_ref );
+	float	f = float(lua_tonumber( config::L, -1 ));
+	lua_pop( config::L, 1 );
+	return f;
+}
+
+
+cvalue::operator const char*() const
+// Converts this Lua value to a string, and returns it.
+{
+	lua_getref( config::L, m_lua_ref );
+	const char*	str = lua_tostring( config::L, -1 );
+	lua_pop( config::L, 1 );	// @@ I'm pretty sure this imperils the string, if we just \
had to do a tostring() conversion!  Look into this, and/or make a copy of the string. \
+	return str; +}
+
+
+cvalue	cvalue::get( const char* index )
+// Does a table lookup.  *this should be a Lua table, and index is its
+// key.
+{
+	lua_getref( config::L, m_lua_ref );
+	lua_pushstring( config::L, index );
+	lua_gettable( config::L, -2 );
+	cvalue	c = cvalue::lua_stacktop_reference();	// references the value on the top of \
the Lua stack. +	lua_pop( config::L, 1 );
+
+	return c;
+}
+
+
+#endif // 0
Index: gnash/libbase/container.cpp
diff -u gnash/libbase/container.cpp:1.2 gnash/libbase/container.cpp:1.3
--- gnash/libbase/container.cpp:1.2	Sat Feb 25 15:27:35 2006
+++ gnash/libbase/container.cpp	Sun Feb 26 15:49:29 2006
@@ -1,700 +1,700 @@
-// container.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Some non-inline implementation help for generic containers.
-
-
-#include "container.h"
-#include "utf8.h"
-#include "tu_random.h"
-#include <stdarg.h>
-
-
-void tu_string::append_wide_char(uint16 c)
-{
-	char buf[8];
-	int index = 0;
-	utf8::encode_unicode_character(buf, &index, (uint32) c);
-	buf[index] = 0;
-
-	*this += buf;
-}
-
-
-void tu_string::append_wide_char(uint32 c)
-{
-	char buf[8];
-	int index = 0;
-	utf8::encode_unicode_character(buf, &index, c);
-	buf[index] = 0;
-
-	*this += buf;
-}
-
-
-void	tu_string::resize(int new_size)
-{
-	assert(new_size >= 0);
-
-	if (using_heap() == false)
-	{
-		if (new_size < 15)
-		{
-			// Stay with internal storage.
-			m_local.m_size = (char) (new_size + 1);
-			m_local.m_buffer[new_size] = 0;	// terminate
-		}
-		else
-		{
-			// need to allocate heap buffer.
-			int	capacity = new_size + 1;
-			// round up.
-			capacity = (capacity + 15) & ~15;
-			char*	buf = (char*) tu_malloc(capacity);
-                        memset(buf, 0, capacity);
-
-			// Copy existing data.
-			strcpy(buf, m_local.m_buffer);
-
-			// Set the heap state.
-			m_heap.m_buffer = buf;
-			m_heap.m_all_ones = char(~0);
-			m_heap.m_size = new_size + 1;
-			m_heap.m_capacity = capacity;
-		}
-	}
-	else
-	{
-		// Currently using heap storage.
-		if (new_size < 15)
-		{
-			// Switch to local storage.
-
-			// Be sure to get stack copies of m_heap info, before we overwrite it.
-			char*	old_buffer = m_heap.m_buffer;
-			int	old_capacity = m_heap.m_capacity;
-			UNUSED(old_capacity);
-
-			// Copy existing string info.
-			m_local.m_size = (char) (new_size + 1);
-			strncpy(m_local.m_buffer, old_buffer, 15);
-			m_local.m_buffer[new_size] = 0;	// ensure termination.
-
-			tu_free(old_buffer, old_capacity);
-		}
-		else
-		{
-			// Changing size of heap buffer.
-			int	capacity = new_size + 1;
-			// Round up.
-			capacity = (capacity + 15) & ~15;
-			if (capacity != m_heap.m_capacity)	// @@ TODO should use hysteresis when resizing
-			{
-				m_heap.m_buffer = (char*) tu_realloc(m_heap.m_buffer, capacity, \
                m_heap.m_capacity);
-				m_heap.m_capacity = capacity;
-			}
-			// else we're OK with existing buffer.
-
-			m_heap.m_size = new_size + 1;
-
-			// Ensure termination.
-			m_heap.m_buffer[new_size] = 0;
-		}
-	}
-}
-
-
-template<class char_type>
-/*static*/ void	encode_utf8_from_wchar_generic(tu_string* result, const char_type* \
                wstr)
-{
-	const char_type*	in = wstr;
-
-	// First pass: compute the necessary string length.
-	int	bytes_needed = 0;
-	char	dummy[10];
-	int	offset;
-	for (;;)
-	{
-		Uint32	uc = *in++;
-		offset = 0;
-		utf8::encode_unicode_character(dummy, &offset, uc);
-		bytes_needed += offset;
-
-		assert(offset <= 6);
-
-		if (uc == 0)
-		{
-			break;
-		}
-	}
-
-	// Second pass: transfer the data.
-	result->resize(bytes_needed - 1);	// resize() adds 1 for the \0 terminator
-	in = wstr;
-	char*	out = &((*result)[0]);
-	offset = 0;
-	for (;;)
-	{
-		assert(offset < bytes_needed);
-
-		Uint32	uc = *in++;
-		utf8::encode_unicode_character(out, &offset, uc);
-
-		assert(offset <= bytes_needed);
-
-		if (uc == 0)
-		{
-			break;
-		}
-	}
-
-	assert(offset == bytes_needed);
-	assert((*result)[offset - 1] == 0);
-	assert(result->length() == (int) strlen(result->c_str()));
-}
-
-
-void tu_string::encode_utf8_from_wchar(tu_string* result, const uint32* wstr)
-{
-	encode_utf8_from_wchar_generic<uint32>(result, wstr);
-}
-
-
-void tu_string::encode_utf8_from_wchar(tu_string* result, const uint16* wstr)
-{
-	encode_utf8_from_wchar_generic<uint16>(result, wstr);
-}
-
-
-/*static*/ int	tu_string::stricmp(const char* a, const char* b)
-{
-#ifdef _WIN32
-	return ::stricmp(a, b);
-#else
-	return strcasecmp(a, b);
-#endif
-}
-
-
-uint32	tu_string::utf8_char_at(int index) const
-{
-	const char*	buf = get_buffer();
-	uint32	c;
-
-	do
-	{
-		c = utf8::decode_next_unicode_character(&buf);
-		index--;
-
-		if (c == 0)
-		{
-			// We've hit the end of the string; don't go further.
-			assert(index == 0);
-			return c;
-		}
-	}
-	while (index >= 0);
-
-	return c;
-}
-
-
-tu_string	tu_string::utf8_to_upper() const
-{
-	const char*	buf = get_buffer();
-	tu_string str;
-	for (;;)
-	{
-		uint32 c = utf8::decode_next_unicode_character(&buf);
-          
-		if (c == 0)
-		{
-			// We've hit the end of the string; don't go further.
-			return str;
-		}
-		str += toupper(c);
-	}
-  
-	return str;
-}
-
-
-tu_string	tu_string::utf8_to_lower() const
-{
-	const char*	buf = get_buffer();
-	tu_string str;
-	for (;;)
-	{
-		uint32 c = utf8::decode_next_unicode_character(&buf);
-    
-		if (c == 0) {
-			// We've hit the end of the string; don't go further.
-			return str;
-		}
-		str += tolower(c);
-	}
-  
-	return str;
-}
-
-
-/*static*/ int	tu_string::utf8_char_count(const char* buf, int buflen)
-{
-	const char*	p = buf;
-	int	length = 0;
-
-	while (p - buf < buflen)
-	{
-		uint32	c = utf8::decode_next_unicode_character(&p);
-		if (c == 0)
-		{
-			break;
-		}
-
-		length++;
-	}
-
-	return length;
-}
-
-
-tu_string	tu_string::utf8_substring(int start, int end) const
-{
-	assert(start <= end);
-
-	if (start == end)
-	{
-		// Special case, always return empty string.
-		return tu_string();
-	}
-
-	const char*	p = get_buffer();
-	int	index = 0;
-	const char*	start_pointer = p;
-	const char*	end_pointer = p;
-
-	for (;;)
-	{
-		if (index == start)
-		{
-			start_pointer = p;
-		}
-
-		uint32	c = utf8::decode_next_unicode_character(&p);
-		index++;
-
-		if (index == end)
-		{
-			end_pointer = p;
-			break;
-		}
-
-		if (c == 0)
-		{
-			if (index < end)
-			{
-				assert(0);
-				end_pointer = p;
-			}
-			break;
-		}
-	}
-
-	if (end_pointer < start_pointer)
-	{
-		end_pointer = start_pointer;
-	}
-
-	return tu_string(start_pointer, end_pointer - start_pointer);
-}
-
-
-#ifdef _WIN32
-#define vsnprintf	_vsnprintf
-#endif // _WIN32
-
-tu_string string_printf(const char* fmt, ...)
-// Handy sprintf wrapper.
-{
-	static const int	BUFFER_SIZE = 500;
-	char	s_buffer[BUFFER_SIZE];
-
-	va_list ap;
-	va_start(ap, fmt);
-	vsnprintf(s_buffer, BUFFER_SIZE, fmt, ap);
-	va_end(ap);
-
-	return s_buffer;
-}
-
-
-
-#ifdef CONTAINER_UNIT_TEST
-
-
-// Compile this test case with something like:
-//
-// gcc container.cpp utf8.cpp tu_random.cpp -g -I.. -DCONTAINER_UNIT_TEST -lstdc++ \
                -o container_test
-//
-//    or
-//
-// cl container.cpp utf8.cpp tu_random.cpp -Zi -Od -DCONTAINER_UNIT_TEST -I..
-
-
-void	test_hash()
-{
-	// Collect a bunch of random key/value pairs.
-	std::vector<Uint32>	data;
-	for (int i = 0; i < 1000; i++)
-	{
-		data.push_back(tu_random::next_random());
-	}
-
-	// Push into hash.
-	hash<Uint32, Uint32>	h;
-	{for (int i = 0; i < data.size() / 2; i++)
-	{
-		h.add(data[i*2], data[i*2 + 1]);
-
-		// Verify the contents of the hash so far.
-		for (int j = 0; j < i; j++)
-		{
-			Uint32	key = data[j*2];
-			Uint32	val;
-			bool	got = h.get(key, &val);
-			assert(got);
-			assert(val == data[j*2 + 1]);
-		}
-	}}
-
-	// Manually copy stuff over to h2, using iterator interface.
-	hash<Uint32, Uint32>	h2;
-	{for (hash<Uint32, Uint32>::iterator it = h.begin(); it != h.end(); ++it)
-	{
-		//printf("first = 0x%X, second = 0x%X\n", it->first, it->second);//xxxxx
-		assert(h.get(it->first, NULL) == true);
-
-		h2.add(it->first, it->second);
-
-		Uint32	val;
-		bool	got = h2.get(it->first, &val);
-		assert(got);
-		assert(val == it->second);
-	}}
-
-	// Verify the contents of h2.
-	{for (int i = 0; i < data.size() / 2; i++)
-	{
-		Uint32	key = data[i*2];
-		Uint32	val;
-		bool	got = h.get(key, &val);
-		assert(got);
-		assert(val == data[i*2 + 1]);
-	}}
-
-	h.clear();
-	assert(h.size() == 0);
-
-	// Verify that h really is missing the stuff it had before, and h2 really has it.
-	{for (hash<Uint32, Uint32>::iterator it = h2.begin(); it != h2.end(); ++it)
-	{
-		assert(h.get(it->first, NULL) == false);
-		assert(h2.get(it->first, NULL) == true);
-		assert(h.find(it->first) == h.end());
-		assert(h2.find(it->first) != h2.end());
-	}}
-}
-
-
-//#include <ext/hash_map>
-//#include <hash_map>
-//#include <map>
-
-void	test_hash_speed()
-// Test function for hash performance of adding keys and doing lookup.
-{
-
-// Hash type, for doing comparative tests.
-//
-// tu_hash tests faster than the map and hash_map included with GCC
-// 3.3 as well as map and hash_map from MSVC7.  In some cases, several
-// times faster.  GCC's hash_map is the closest to tu_hash, but is
-// still 33% slower in my tests.
-
-// // tu's hash
-#define HASH hash<uint32, uint32 >
-#define HASH_ADD(h, k, v) h.add(k, v)
-
-// STL's hash
-//#define HASH __gnu_cxx::hash_map<uint32, uint32>
-//#define HASH std::hash_map<uint32, uint32>
-//#define HASH_ADD(h, k, v) h[k] = v
-
-// STL's map
-//#define HASH std::map<uint32, uint32>
-//#define HASH_ADD(h, k, v) h[k] = v
-
-//	const int	SIZE = 10000000;
-	const int	SIZE = 1000000;
-
-	// Make an array of random numbers.
-	std::vector<uint32>	numbers;
-	numbers.resize(SIZE);
-
-	for (int i = 0, n = numbers.size(); i < n; i++)
-	{
-		numbers[i] = tu_random::next_random();
-	}
-
-	// Uniquify the array.
-	HASH	new_index;
-	int	next_new_index = 0;
-	{for (int i = 0, n = numbers.size(); i < n; i++)
-	{
-		HASH::iterator	it = new_index.find(numbers[i]);
-		if (it == new_index.end())
-		{
-			// First time this number has been seen.
-			HASH_ADD(new_index, numbers[i], next_new_index);
-			next_new_index++;
-		}
-		else
-		{
-			// This number already appears in the list.
-// 			printf("duplicate entry %x, prev new index %d, current array index %d\n",
-// 				   numbers[i],
-// 				   it->second,
-// 				   i);
-		}
-	}}
-
-	printf("next_new_index = %d\n", next_new_index);
-}
-
-
-void	test_stringi()
-{
-	tu_stringi	a, b;
-
-	// Equality.
-	a = "this is a test";
-	b = "This is a test";
-	assert(a == b);
-
-	b = "tHiS Is a tEsT";
-	assert(a == b);
-
-	a += "Hello";
-	b += "hellO";
-	assert(a == b);
-
-	tu_string	c(b);
-	assert(a.to_tu_string() != c);
-
-	// Ordering.
-	a = "a";
-	b = "B";
-	assert(a < b);
-
-	a = "b";
-	b = "A";
-	assert(a > b);
-}
-
-
-void	test_stringi_hash()
-{
-	stringi_hash<int>	a;
-
-	assert(a.is_empty());
-
-	a.add("bobo", 1);
-
-	assert(a.is_empty() == false);
-
-	a.add("hello", 2);
-	a.add("it's", 3);
-	a.add("a", 4);
-	a.add("beautiful day!", 5);
-
-	int	result = 0;
-	a.get("boBO", &result);
-	assert(result == 1);
-
-	a.set("BObo", 2);
-	a.get("bObO", &result);
-	assert(result == 2);
-
-	assert(a.is_empty() == false);
-	a.clear();
-	assert(a.is_empty() == true);
-
-	// Hammer on one key that differs only by case.
-	tu_stringi	original_key("thisisatest");
-	tu_stringi	key(original_key);
-	a.add(key, 1234567);
-
-	int	variations = 1 << key.length();
-	for (int i = 0; i < variations; i++)
-	{
-		// Twiddle the case of the key.
-		for (int c = 0; c < key.length(); c++)
-		{
-			if (i & (1 << c))
-			{
-				key[c] = toupper(key[c]);
-			}
-			else
-			{
-				key[c] = tolower(key[c]);
-			}
-		}
-
-		a.set(key, 7654321);
-
-		// Make sure original entry was modified.
-		int	value = 0;
-		a.get(original_key, &value);
-		assert(value == 7654321);
-
-		// Make sure hash keys are preserving case.
-		assert(a.find(key)->first.to_tu_string() == original_key.to_tu_string());
-
-		// Make sure they're actually the same entry.
-		assert(a.find(original_key) == a.find(key));
-		
-		a.set(original_key, 1234567);
-		assert(a.find(key)->second == 1234567);
-	}
-}
-
-
-void test_unicode()
-{
-	tu_string a;
-
-	tu_string::encode_utf8_from_wchar(&a, L"19 character string");
-	assert(a.length() == 19);
-
-	// TODO add some more tests; should test actual UTF-8 conversions.
-}
-
-
-
-int	main()
-{
-#if 1
-	printf("sizeof(tu_string) == %d\n", sizeof(tu_string));
-
-	std::vector<tu_string>	storage;
-	storage.resize(2);
-
-	tu_string&	a = storage[0];
-	tu_string&	b = storage[1];
-	a = "test1";
-	
-	printf("&a = 0x%X, &b = 0x%X\n", int(&a), int(&b));
-
-	printf("%s\n", a.c_str());
-
-	assert(a == "test1");
-	assert(a.length() == 5);
-
-	a += "2";
-	assert(a == "test12");
-
-	a += "this is some more text";
-	assert(a.length() == 28);
-
-	assert(a[2] == 's');
-	assert(a[3] == 't');
-	assert(a[4] == '1');
-	assert(a[5] == '2');
-	assert(a[7] == 'h');
-	assert(a[28] == 0);
-
-	assert(b.length() == 0);
-	assert(b[0] == 0);
-	assert(b.c_str()[0] == 0);
-
-	tu_string c = a + b;
-
-	assert(c.length() == a.length());
-
-	c.resize(2);
-	assert(c == "te");
-	assert(c == tu_string("te"));
-
-	assert(tu_string("fourscore and sevent") == "fourscore and sevent");
-
-	b = "#sacrificial lamb";
-
-	// Test growing & shrinking.
-	a = "";
-	for (int i = 0; i < 1000; i++)
-	{
-		assert(a.length() == i);
-
-		if (i == 8)
-		{
-			assert(a == "01234567");
-		}
-		else if (i == 27)
-		{
-			assert(a == "012345678901234567890123456");
-		}
-
-		a.resize(a.length() + 1);
-		a[a.length() - 1] = '0' + (i % 10);
-	}
-
-	{for (int i = 999; i >= 0; i--)
-	{
-		a.resize(a.length() - 1);
-		assert(a.length() == i);
-
-		if (i == 8)
-		{
-			assert(a == "01234567");
-		}
-		else if (i == 27)
-		{
-			assert(a == "012345678901234567890123456");
-		}
-	}}
-
-	// Test larger shrinking across heap/local boundary.
-	a = "this is a string longer than 16 characters";
-	a = "short";
-
-	// Test larger expand across heap/local boundary.
-	a = "another longer string...";
-
-	assert(b == "#sacrificial lamb");
-
-	test_hash();
-	test_stringi();
-	test_stringi_hash();
-
-	test_unicode();
-
-	// TODO: unit tests for std::vector<>, string_hash<>
-#endif
-
-	test_hash_speed();
-
-	return 0;
-}
-
-
-#endif // CONTAINER_UNIT_TEST
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// container.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Some non-inline implementation help for generic containers.
+
+
+#include "container.h"
+#include "utf8.h"
+#include "tu_random.h"
+#include <stdarg.h>
+
+
+void tu_string::append_wide_char(uint16 c)
+{
+	char buf[8];
+	int index = 0;
+	utf8::encode_unicode_character(buf, &index, (uint32) c);
+	buf[index] = 0;
+
+	*this += buf;
+}
+
+
+void tu_string::append_wide_char(uint32 c)
+{
+	char buf[8];
+	int index = 0;
+	utf8::encode_unicode_character(buf, &index, c);
+	buf[index] = 0;
+
+	*this += buf;
+}
+
+
+void	tu_string::resize(int new_size)
+{
+	assert(new_size >= 0);
+
+	if (using_heap() == false)
+	{
+		if (new_size < 15)
+		{
+			// Stay with internal storage.
+			m_local.m_size = (char) (new_size + 1);
+			m_local.m_buffer[new_size] = 0;	// terminate
+		}
+		else
+		{
+			// need to allocate heap buffer.
+			int	capacity = new_size + 1;
+			// round up.
+			capacity = (capacity + 15) & ~15;
+			char*	buf = (char*) tu_malloc(capacity);
+                        memset(buf, 0, capacity);
+
+			// Copy existing data.
+			strcpy(buf, m_local.m_buffer);
+
+			// Set the heap state.
+			m_heap.m_buffer = buf;
+			m_heap.m_all_ones = char(~0);
+			m_heap.m_size = new_size + 1;
+			m_heap.m_capacity = capacity;
+		}
+	}
+	else
+	{
+		// Currently using heap storage.
+		if (new_size < 15)
+		{
+			// Switch to local storage.
+
+			// Be sure to get stack copies of m_heap info, before we overwrite it.
+			char*	old_buffer = m_heap.m_buffer;
+			int	old_capacity = m_heap.m_capacity;
+			UNUSED(old_capacity);
+
+			// Copy existing string info.
+			m_local.m_size = (char) (new_size + 1);
+			strncpy(m_local.m_buffer, old_buffer, 15);
+			m_local.m_buffer[new_size] = 0;	// ensure termination.
+
+			tu_free(old_buffer, old_capacity);
+		}
+		else
+		{
+			// Changing size of heap buffer.
+			int	capacity = new_size + 1;
+			// Round up.
+			capacity = (capacity + 15) & ~15;
+			if (capacity != m_heap.m_capacity)	// @@ TODO should use hysteresis when resizing
+			{
+				m_heap.m_buffer = (char*) tu_realloc(m_heap.m_buffer, capacity, \
m_heap.m_capacity); +				m_heap.m_capacity = capacity;
+			}
+			// else we're OK with existing buffer.
+
+			m_heap.m_size = new_size + 1;
+
+			// Ensure termination.
+			m_heap.m_buffer[new_size] = 0;
+		}
+	}
+}
+
+
+template<class char_type>
+/*static*/ void	encode_utf8_from_wchar_generic(tu_string* result, const char_type* \
wstr) +{
+	const char_type*	in = wstr;
+
+	// First pass: compute the necessary string length.
+	int	bytes_needed = 0;
+	char	dummy[10];
+	int	offset;
+	for (;;)
+	{
+		Uint32	uc = *in++;
+		offset = 0;
+		utf8::encode_unicode_character(dummy, &offset, uc);
+		bytes_needed += offset;
+
+		assert(offset <= 6);
+
+		if (uc == 0)
+		{
+			break;
+		}
+	}
+
+	// Second pass: transfer the data.
+	result->resize(bytes_needed - 1);	// resize() adds 1 for the \0 terminator
+	in = wstr;
+	char*	out = &((*result)[0]);
+	offset = 0;
+	for (;;)
+	{
+		assert(offset < bytes_needed);
+
+		Uint32	uc = *in++;
+		utf8::encode_unicode_character(out, &offset, uc);
+
+		assert(offset <= bytes_needed);
+
+		if (uc == 0)
+		{
+			break;
+		}
+	}
+
+	assert(offset == bytes_needed);
+	assert((*result)[offset - 1] == 0);
+	assert(result->length() == (int) strlen(result->c_str()));
+}
+
+
+void tu_string::encode_utf8_from_wchar(tu_string* result, const uint32* wstr)
+{
+	encode_utf8_from_wchar_generic<uint32>(result, wstr);
+}
+
+
+void tu_string::encode_utf8_from_wchar(tu_string* result, const uint16* wstr)
+{
+	encode_utf8_from_wchar_generic<uint16>(result, wstr);
+}
+
+
+/*static*/ int	tu_string::stricmp(const char* a, const char* b)
+{
+#ifdef _WIN32
+	return ::stricmp(a, b);
+#else
+	return strcasecmp(a, b);
+#endif
+}
+
+
+uint32	tu_string::utf8_char_at(int index) const
+{
+	const char*	buf = get_buffer();
+	uint32	c;
+
+	do
+	{
+		c = utf8::decode_next_unicode_character(&buf);
+		index--;
+
+		if (c == 0)
+		{
+			// We've hit the end of the string; don't go further.
+			assert(index == 0);
+			return c;
+		}
+	}
+	while (index >= 0);
+
+	return c;
+}
+
+
+tu_string	tu_string::utf8_to_upper() const
+{
+	const char*	buf = get_buffer();
+	tu_string str;
+	for (;;)
+	{
+		uint32 c = utf8::decode_next_unicode_character(&buf);
+          
+		if (c == 0)
+		{
+			// We've hit the end of the string; don't go further.
+			return str;
+		}
+		str += toupper(c);
+	}
+  
+	return str;
+}
+
+
+tu_string	tu_string::utf8_to_lower() const
+{
+	const char*	buf = get_buffer();
+	tu_string str;
+	for (;;)
+	{
+		uint32 c = utf8::decode_next_unicode_character(&buf);
+    
+		if (c == 0) {
+			// We've hit the end of the string; don't go further.
+			return str;
+		}
+		str += tolower(c);
+	}
+  
+	return str;
+}
+
+
+/*static*/ int	tu_string::utf8_char_count(const char* buf, int buflen)
+{
+	const char*	p = buf;
+	int	length = 0;
+
+	while (p - buf < buflen)
+	{
+		uint32	c = utf8::decode_next_unicode_character(&p);
+		if (c == 0)
+		{
+			break;
+		}
+
+		length++;
+	}
+
+	return length;
+}
+
+
+tu_string	tu_string::utf8_substring(int start, int end) const
+{
+	assert(start <= end);
+
+	if (start == end)
+	{
+		// Special case, always return empty string.
+		return tu_string();
+	}
+
+	const char*	p = get_buffer();
+	int	index = 0;
+	const char*	start_pointer = p;
+	const char*	end_pointer = p;
+
+	for (;;)
+	{
+		if (index == start)
+		{
+			start_pointer = p;
+		}
+
+		uint32	c = utf8::decode_next_unicode_character(&p);
+		index++;
+
+		if (index == end)
+		{
+			end_pointer = p;
+			break;
+		}
+
+		if (c == 0)
+		{
+			if (index < end)
+			{
+				assert(0);
+				end_pointer = p;
+			}
+			break;
+		}
+	}
+
+	if (end_pointer < start_pointer)
+	{
+		end_pointer = start_pointer;
+	}
+
+	return tu_string(start_pointer, end_pointer - start_pointer);
+}
+
+
+#ifdef _WIN32
+#define vsnprintf	_vsnprintf
+#endif // _WIN32
+
+tu_string string_printf(const char* fmt, ...)
+// Handy sprintf wrapper.
+{
+	static const int	BUFFER_SIZE = 500;
+	char	s_buffer[BUFFER_SIZE];
+
+	va_list ap;
+	va_start(ap, fmt);
+	vsnprintf(s_buffer, BUFFER_SIZE, fmt, ap);
+	va_end(ap);
+
+	return s_buffer;
+}
+
+
+
+#ifdef CONTAINER_UNIT_TEST
+
+
+// Compile this test case with something like:
+//
+// gcc container.cpp utf8.cpp tu_random.cpp -g -I.. -DCONTAINER_UNIT_TEST -lstdc++ \
-o container_test +//
+//    or
+//
+// cl container.cpp utf8.cpp tu_random.cpp -Zi -Od -DCONTAINER_UNIT_TEST -I..
+
+
+void	test_hash()
+{
+	// Collect a bunch of random key/value pairs.
+	std::vector<Uint32>	data;
+	for (int i = 0; i < 1000; i++)
+	{
+		data.push_back(tu_random::next_random());
+	}
+
+	// Push into hash.
+	hash<Uint32, Uint32>	h;
+	{for (int i = 0; i < data.size() / 2; i++)
+	{
+		h.add(data[i*2], data[i*2 + 1]);
+
+		// Verify the contents of the hash so far.
+		for (int j = 0; j < i; j++)
+		{
+			Uint32	key = data[j*2];
+			Uint32	val;
+			bool	got = h.get(key, &val);
+			assert(got);
+			assert(val == data[j*2 + 1]);
+		}
+	}}
+
+	// Manually copy stuff over to h2, using iterator interface.
+	hash<Uint32, Uint32>	h2;
+	{for (hash<Uint32, Uint32>::iterator it = h.begin(); it != h.end(); ++it)
+	{
+		//printf("first = 0x%X, second = 0x%X\n", it->first, it->second);//xxxxx
+		assert(h.get(it->first, NULL) == true);
+
+		h2.add(it->first, it->second);
+
+		Uint32	val;
+		bool	got = h2.get(it->first, &val);
+		assert(got);
+		assert(val == it->second);
+	}}
+
+	// Verify the contents of h2.
+	{for (int i = 0; i < data.size() / 2; i++)
+	{
+		Uint32	key = data[i*2];
+		Uint32	val;
+		bool	got = h.get(key, &val);
+		assert(got);
+		assert(val == data[i*2 + 1]);
+	}}
+
+	h.clear();
+	assert(h.size() == 0);
+
+	// Verify that h really is missing the stuff it had before, and h2 really has it.
+	{for (hash<Uint32, Uint32>::iterator it = h2.begin(); it != h2.end(); ++it)
+	{
+		assert(h.get(it->first, NULL) == false);
+		assert(h2.get(it->first, NULL) == true);
+		assert(h.find(it->first) == h.end());
+		assert(h2.find(it->first) != h2.end());
+	}}
+}
+
+
+//#include <ext/hash_map>
+//#include <hash_map>
+//#include <map>
+
+void	test_hash_speed()
+// Test function for hash performance of adding keys and doing lookup.
+{
+
+// Hash type, for doing comparative tests.
+//
+// tu_hash tests faster than the map and hash_map included with GCC
+// 3.3 as well as map and hash_map from MSVC7.  In some cases, several
+// times faster.  GCC's hash_map is the closest to tu_hash, but is
+// still 33% slower in my tests.
+
+// // tu's hash
+#define HASH hash<uint32, uint32 >
+#define HASH_ADD(h, k, v) h.add(k, v)
+
+// STL's hash
+//#define HASH __gnu_cxx::hash_map<uint32, uint32>
+//#define HASH std::hash_map<uint32, uint32>
+//#define HASH_ADD(h, k, v) h[k] = v
+
+// STL's map
+//#define HASH std::map<uint32, uint32>
+//#define HASH_ADD(h, k, v) h[k] = v
+
+//	const int	SIZE = 10000000;
+	const int	SIZE = 1000000;
+
+	// Make an array of random numbers.
+	std::vector<uint32>	numbers;
+	numbers.resize(SIZE);
+
+	for (int i = 0, n = numbers.size(); i < n; i++)
+	{
+		numbers[i] = tu_random::next_random();
+	}
+
+	// Uniquify the array.
+	HASH	new_index;
+	int	next_new_index = 0;
+	{for (int i = 0, n = numbers.size(); i < n; i++)
+	{
+		HASH::iterator	it = new_index.find(numbers[i]);
+		if (it == new_index.end())
+		{
+			// First time this number has been seen.
+			HASH_ADD(new_index, numbers[i], next_new_index);
+			next_new_index++;
+		}
+		else
+		{
+			// This number already appears in the list.
+// 			printf("duplicate entry %x, prev new index %d, current array index %d\n",
+// 				   numbers[i],
+// 				   it->second,
+// 				   i);
+		}
+	}}
+
+	printf("next_new_index = %d\n", next_new_index);
+}
+
+
+void	test_stringi()
+{
+	tu_stringi	a, b;
+
+	// Equality.
+	a = "this is a test";
+	b = "This is a test";
+	assert(a == b);
+
+	b = "tHiS Is a tEsT";
+	assert(a == b);
+
+	a += "Hello";
+	b += "hellO";
+	assert(a == b);
+
+	tu_string	c(b);
+	assert(a.to_tu_string() != c);
+
+	// Ordering.
+	a = "a";
+	b = "B";
+	assert(a < b);
+
+	a = "b";
+	b = "A";
+	assert(a > b);
+}
+
+
+void	test_stringi_hash()
+{
+	stringi_hash<int>	a;
+
+	assert(a.is_empty());
+
+	a.add("bobo", 1);
+
+	assert(a.is_empty() == false);
+
+	a.add("hello", 2);
+	a.add("it's", 3);
+	a.add("a", 4);
+	a.add("beautiful day!", 5);
+
+	int	result = 0;
+	a.get("boBO", &result);
+	assert(result == 1);
+
+	a.set("BObo", 2);
+	a.get("bObO", &result);
+	assert(result == 2);
+
+	assert(a.is_empty() == false);
+	a.clear();
+	assert(a.is_empty() == true);
+
+	// Hammer on one key that differs only by case.
+	tu_stringi	original_key("thisisatest");
+	tu_stringi	key(original_key);
+	a.add(key, 1234567);
+
+	int	variations = 1 << key.length();
+	for (int i = 0; i < variations; i++)
+	{
+		// Twiddle the case of the key.
+		for (int c = 0; c < key.length(); c++)
+		{
+			if (i & (1 << c))
+			{
+				key[c] = toupper(key[c]);
+			}
+			else
+			{
+				key[c] = tolower(key[c]);
+			}
+		}
+
+		a.set(key, 7654321);
+
+		// Make sure original entry was modified.
+		int	value = 0;
+		a.get(original_key, &value);
+		assert(value == 7654321);
+
+		// Make sure hash keys are preserving case.
+		assert(a.find(key)->first.to_tu_string() == original_key.to_tu_string());
+
+		// Make sure they're actually the same entry.
+		assert(a.find(original_key) == a.find(key));
+		
+		a.set(original_key, 1234567);
+		assert(a.find(key)->second == 1234567);
+	}
+}
+
+
+void test_unicode()
+{
+	tu_string a;
+
+	tu_string::encode_utf8_from_wchar(&a, L"19 character string");
+	assert(a.length() == 19);
+
+	// TODO add some more tests; should test actual UTF-8 conversions.
+}
+
+
+
+int	main()
+{
+#if 1
+	printf("sizeof(tu_string) == %d\n", sizeof(tu_string));
+
+	std::vector<tu_string>	storage;
+	storage.resize(2);
+
+	tu_string&	a = storage[0];
+	tu_string&	b = storage[1];
+	a = "test1";
+	
+	printf("&a = 0x%X, &b = 0x%X\n", int(&a), int(&b));
+
+	printf("%s\n", a.c_str());
+
+	assert(a == "test1");
+	assert(a.length() == 5);
+
+	a += "2";
+	assert(a == "test12");
+
+	a += "this is some more text";
+	assert(a.length() == 28);
+
+	assert(a[2] == 's');
+	assert(a[3] == 't');
+	assert(a[4] == '1');
+	assert(a[5] == '2');
+	assert(a[7] == 'h');
+	assert(a[28] == 0);
+
+	assert(b.length() == 0);
+	assert(b[0] == 0);
+	assert(b.c_str()[0] == 0);
+
+	tu_string c = a + b;
+
+	assert(c.length() == a.length());
+
+	c.resize(2);
+	assert(c == "te");
+	assert(c == tu_string("te"));
+
+	assert(tu_string("fourscore and sevent") == "fourscore and sevent");
+
+	b = "#sacrificial lamb";
+
+	// Test growing & shrinking.
+	a = "";
+	for (int i = 0; i < 1000; i++)
+	{
+		assert(a.length() == i);
+
+		if (i == 8)
+		{
+			assert(a == "01234567");
+		}
+		else if (i == 27)
+		{
+			assert(a == "012345678901234567890123456");
+		}
+
+		a.resize(a.length() + 1);
+		a[a.length() - 1] = '0' + (i % 10);
+	}
+
+	{for (int i = 999; i >= 0; i--)
+	{
+		a.resize(a.length() - 1);
+		assert(a.length() == i);
+
+		if (i == 8)
+		{
+			assert(a == "01234567");
+		}
+		else if (i == 27)
+		{
+			assert(a == "012345678901234567890123456");
+		}
+	}}
+
+	// Test larger shrinking across heap/local boundary.
+	a = "this is a string longer than 16 characters";
+	a = "short";
+
+	// Test larger expand across heap/local boundary.
+	a = "another longer string...";
+
+	assert(b == "#sacrificial lamb");
+
+	test_hash();
+	test_stringi();
+	test_stringi_hash();
+
+	test_unicode();
+
+	// TODO: unit tests for std::vector<>, string_hash<>
+#endif
+
+	test_hash_speed();
+
+	return 0;
+}
+
+
+#endif // CONTAINER_UNIT_TEST
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/container.h
diff -u gnash/libbase/container.h:1.6 gnash/libbase/container.h:1.7
--- gnash/libbase/container.h:1.6	Sat Feb 25 03:54:03 2006
+++ gnash/libbase/container.h	Sun Feb 26 15:49:29 2006
@@ -12,12 +12,26 @@
 #ifndef CONTAINER_H
 #define CONTAINER_H
 
+// FIXME: This ugly hack is for NetBSD, which seems to have a
+// preprocessor problem, and won't define anything sensible like
+// NETBSD we can use. Basically the problem is NetBSD has two thread
+// implementations. One if the older pth library in /usr/pkg, and the
+// other (the one we want to use) is /usr/pkg/phtread. Even with the
+// corrent paths supplied, this one file barfs with GCC 3.3.3 on
+// NetBSD, so screw it, and just hack it for now. We hope this entire
+// file will be gond soon anyway.
+#define _LIB_PTHREAD_ 1
+#define _LIB_PTHREAD_TYPES_H 1
+#include <sys/types.h>
+#include <pthread.h>
+clock_t clock __P((void));
+size_t strftime __P((char *, size_t, const char *, const struct tm *));
 
 #include "tu_config.h"
 #include "utility.h"
 #include <stdlib.h>
-#include <string.h>	// for strcmp and friends
-#include <new>	// for placement new
+#include <cstring>	// for strcmp and friends
+//#include <new>	// for placement new
 #include <vector>
 
 
Index: gnash/libbase/demo.cpp
diff -u gnash/libbase/demo.cpp:1.1 gnash/libbase/demo.cpp:1.2
--- gnash/libbase/demo.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/demo.cpp	Sun Feb 26 15:49:29 2006
@@ -1,127 +1,127 @@
-// demo.cpp  -- Thatcher Ulrich <http://tulrich.com> 2005
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Some helper code for making graphical demos.  Covers OpenGL/SDL
-// initialization, and some basic viewport navigation.
-
-
-#include "tu_config.h"
-#include "demo.h"
-#include "ogl.h"
-#include "SDL.h"
-
-
-namespace demo
-{
-	void init_video(int width, int height, int depth)
-	{
-		// Display.
-		// Initialize the SDL subsystems we're using.
-		if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | \
                SDL_INIT_AUDIO*/))
-		{
-			fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
-			exit(1);
-		}
-		atexit(SDL_Quit);
-
-		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-
-		// Set the video mode.
-		if (SDL_SetVideoMode(width, height, depth, SDL_OPENGL) == 0)
-		{
-			fprintf(stderr, "SDL_SetVideoMode() failed.");
-			exit(1);
-		}
-
-		ogl::open();
-	}
-
-
-	bool update_nav2d(nav2d_state* state)
-	{
-		// Handle input.
-		SDL_Event	event;
-		while (SDL_PollEvent(&event))
-		{
-			switch (event.type)
-			{
-			case SDL_KEYDOWN:
-			{
-				int	key = event.key.keysym.sym;
-
-				if (key == SDLK_q || key == SDLK_ESCAPE)
-				{
-					return true;
-				} else if (key == SDLK_EQUALS) {
-					state->m_scale *= 0.5f;
-				} else if (key == SDLK_MINUS) {
-					state->m_scale *= 2.0f;
-				}
-				break;
-			}
-
-			case SDL_MOUSEMOTION:
-			{
-				int new_x = (int) (event.motion.x);
-				int new_y = (int) (event.motion.y);
-				state->m_mouse_dx = new_x - state->m_mouse_x;
-				state->m_mouse_dy = new_y - state->m_mouse_y;
-				if (state->m_mouse_buttons & 2) {
-					// Left drag: move.
-					state->m_center_x -= state->m_mouse_dx * state->m_scale;
-					state->m_center_y += state->m_mouse_dy * state->m_scale;
-				}
-				state->m_mouse_x = new_x;
-				state->m_mouse_y = new_y;
-				break;
-			}
-
-			case SDL_MOUSEBUTTONDOWN:
-			case SDL_MOUSEBUTTONUP:
-			{
-				int	mask = 1 << (event.button.button);
-				if (event.button.state == SDL_PRESSED)
-				{
-					state->m_mouse_buttons |= mask;
-				}
-				else
-				{
-					state->m_mouse_buttons &= ~mask;
-				}
-				break;
-			}
-
-			case SDL_QUIT:
-				return true;
-				break;
-
-			default:
-				break;
-			}
-		}
-
-		return false;
-	}
-
-
-	void set_nav2d_viewport(const nav2d_state& state)
-	{
-		glMatrixMode(GL_PROJECTION);
-		glLoadIdentity();
-		glOrtho(state.m_center_x - 500 * state.m_scale, state.m_center_x + 500 * \
                state.m_scale,
-			state.m_center_y - 500 * state.m_scale, state.m_center_y + 500 * state.m_scale, \
                -1, 1);
-		glMatrixMode(GL_MODELVIEW);
-		glLoadIdentity();
-	}
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
-
+// demo.cpp  -- Thatcher Ulrich <http://tulrich.com> 2005
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Some helper code for making graphical demos.  Covers OpenGL/SDL
+// initialization, and some basic viewport navigation.
+
+
+#include "tu_config.h"
+#include "demo.h"
+#include "ogl.h"
+#include "SDL.h"
+
+
+namespace demo
+{
+	void init_video(int width, int height, int depth)
+	{
+		// Display.
+		// Initialize the SDL subsystems we're using.
+		if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | \
SDL_INIT_AUDIO*/)) +		{
+			fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
+			exit(1);
+		}
+		atexit(SDL_Quit);
+
+		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+		// Set the video mode.
+		if (SDL_SetVideoMode(width, height, depth, SDL_OPENGL) == 0)
+		{
+			fprintf(stderr, "SDL_SetVideoMode() failed.");
+			exit(1);
+		}
+
+		ogl::open();
+	}
+
+
+	bool update_nav2d(nav2d_state* state)
+	{
+		// Handle input.
+		SDL_Event	event;
+		while (SDL_PollEvent(&event))
+		{
+			switch (event.type)
+			{
+			case SDL_KEYDOWN:
+			{
+				int	key = event.key.keysym.sym;
+
+				if (key == SDLK_q || key == SDLK_ESCAPE)
+				{
+					return true;
+				} else if (key == SDLK_EQUALS) {
+					state->m_scale *= 0.5f;
+				} else if (key == SDLK_MINUS) {
+					state->m_scale *= 2.0f;
+				}
+				break;
+			}
+
+			case SDL_MOUSEMOTION:
+			{
+				int new_x = (int) (event.motion.x);
+				int new_y = (int) (event.motion.y);
+				state->m_mouse_dx = new_x - state->m_mouse_x;
+				state->m_mouse_dy = new_y - state->m_mouse_y;
+				if (state->m_mouse_buttons & 2) {
+					// Left drag: move.
+					state->m_center_x -= state->m_mouse_dx * state->m_scale;
+					state->m_center_y += state->m_mouse_dy * state->m_scale;
+				}
+				state->m_mouse_x = new_x;
+				state->m_mouse_y = new_y;
+				break;
+			}
+
+			case SDL_MOUSEBUTTONDOWN:
+			case SDL_MOUSEBUTTONUP:
+			{
+				int	mask = 1 << (event.button.button);
+				if (event.button.state == SDL_PRESSED)
+				{
+					state->m_mouse_buttons |= mask;
+				}
+				else
+				{
+					state->m_mouse_buttons &= ~mask;
+				}
+				break;
+			}
+
+			case SDL_QUIT:
+				return true;
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		return false;
+	}
+
+
+	void set_nav2d_viewport(const nav2d_state& state)
+	{
+		glMatrixMode(GL_PROJECTION);
+		glLoadIdentity();
+		glOrtho(state.m_center_x - 500 * state.m_scale, state.m_center_x + 500 * \
state.m_scale, +			state.m_center_y - 500 * state.m_scale, state.m_center_y + 500 * \
state.m_scale, -1, 1); +		glMatrixMode(GL_MODELVIEW);
+		glLoadIdentity();
+	}
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
+
Index: gnash/libbase/demo.h
diff -u gnash/libbase/demo.h:1.1 gnash/libbase/demo.h:1.2
--- gnash/libbase/demo.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/demo.h	Sun Feb 26 15:49:29 2006
@@ -1,75 +1,75 @@
-// demo.h  -- Thatcher Ulrich <http://tulrich.com> 2005
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Some helper code for making graphical demos.  Covers OpenGL/SDL
-// initialization, and some basic viewport navigation.
-
-
-#ifndef DEMO_H
-#define DEMO_H
-
-
-#include "tu_config.h"
-
-
-namespace demo
-{
-	// Open an OpenGL window with the given dimensions.
-	void init_video(int width, int height, int depth);
-
-	// A state object you can use to manage 2D scrolling & zooming.
-	struct nav2d_state
-	{
-		// 2d viewport state.
-		float m_center_x;
-		float m_center_y;
-		float m_scale;
-
-		// Current mouse state.
-		int m_mouse_x;
-		int m_mouse_y;
-		int m_mouse_buttons;
-		
-		// Change in mouse position in pixels, this frame.
-		int m_mouse_dx;
-		int m_mouse_dy;
-
-		nav2d_state()
-			:
-			m_center_x(0),
-			m_center_y(0),
-			m_scale(1),
-			m_mouse_x(0),
-			m_mouse_y(0),
-			m_mouse_buttons(0),
-			m_mouse_dx(0),
-			m_mouse_dy(0)
-		{
-		}
-	};
-
-	// Checks and processes the SDL message queue.  Returns true
-	// if the user wants to exit.
-	//
-	// TODO: do some kind of callback registry for handling misc
-	// app-specific inputs
-	bool update_nav2d(nav2d_state* state);
-
-	// Sets the OpenGL projection & modelview according to the 2d
-	// view state.
-	void set_nav2d_viewport(const nav2d_state& state);
-}
-
-
-#endif // DEMO_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
-
+// demo.h  -- Thatcher Ulrich <http://tulrich.com> 2005
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Some helper code for making graphical demos.  Covers OpenGL/SDL
+// initialization, and some basic viewport navigation.
+
+
+#ifndef DEMO_H
+#define DEMO_H
+
+
+#include "tu_config.h"
+
+
+namespace demo
+{
+	// Open an OpenGL window with the given dimensions.
+	void init_video(int width, int height, int depth);
+
+	// A state object you can use to manage 2D scrolling & zooming.
+	struct nav2d_state
+	{
+		// 2d viewport state.
+		float m_center_x;
+		float m_center_y;
+		float m_scale;
+
+		// Current mouse state.
+		int m_mouse_x;
+		int m_mouse_y;
+		int m_mouse_buttons;
+		
+		// Change in mouse position in pixels, this frame.
+		int m_mouse_dx;
+		int m_mouse_dy;
+
+		nav2d_state()
+			:
+			m_center_x(0),
+			m_center_y(0),
+			m_scale(1),
+			m_mouse_x(0),
+			m_mouse_y(0),
+			m_mouse_buttons(0),
+			m_mouse_dx(0),
+			m_mouse_dy(0)
+		{
+		}
+	};
+
+	// Checks and processes the SDL message queue.  Returns true
+	// if the user wants to exit.
+	//
+	// TODO: do some kind of callback registry for handling misc
+	// app-specific inputs
+	bool update_nav2d(nav2d_state* state);
+
+	// Sets the OpenGL projection & modelview according to the 2d
+	// view state.
+	void set_nav2d_viewport(const nav2d_state& state);
+}
+
+
+#endif // DEMO_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
+
Index: gnash/libbase/dlmalloc.c
diff -u gnash/libbase/dlmalloc.c:1.1 gnash/libbase/dlmalloc.c:1.2
--- gnash/libbase/dlmalloc.c:1.1	Tue Dec 20 21:13:18 2005
+++ gnash/libbase/dlmalloc.c	Sun Feb 26 15:49:29 2006
@@ -1470,7 +1470,7 @@
   ========================================================================
 */
 
-/* #include "malloc.h" */
+/* #include "stdlib.h" */
 
 /* --------------------- public wrappers ---------------------- */
 
Index: gnash/libbase/dlmalloc.h
diff -u gnash/libbase/dlmalloc.h:1.1 gnash/libbase/dlmalloc.h:1.2
--- gnash/libbase/dlmalloc.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/dlmalloc.h	Sun Feb 26 15:49:29 2006
@@ -35,7 +35,7 @@
 #ifdef __MACH__
 #include <memory.h>
 #else
-#include <malloc.h>	/* tulrich */
+#include <stdlib.h>	/* tulrich */
 #endif
 
 #ifdef USE_DL_MALLOC
Index: gnash/libbase/file_util.cpp
diff -u gnash/libbase/file_util.cpp:1.1 gnash/libbase/file_util.cpp:1.2
--- gnash/libbase/file_util.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/file_util.cpp	Sun Feb 26 15:49:29 2006
@@ -1,54 +1,54 @@
-// file_util.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2005
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// A file class that can be customized with callbacks.
-
-
-#include "file_util.h"
-#include "utility.h"
-#include <string.h>
-
-
-static const char* reverse_scan(const char* begin, const char* end, char c)
-// Scans in reverse, from *(end-1) through *begin, until it finds a
-// character matching c.  If none is found, returns end, else returns
-// a pointer to the char.
-{
-	assert(begin <= end);
-	
-	const char* p = end;
-	while (p > begin) {
-		p--;
-		if (*p == c) {
-			return p;
-		}
-	}
-
-	return end;
-}
-
-
-const char* file_util::get_extension(const char* path)
-{
-	int len = strlen(path);
-	const char* last_dot = reverse_scan(path, path + len, '.');
-	const char* last_slash = reverse_scan(last_dot, path + len, '/');
-
-	if (last_dot[0] && last_slash[0] == 0) {
-		return last_dot + 1;
-	}
-
-	// No apparent file extension, return an empty string.
-	return path + len;
-}
-
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// file_util.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2005
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// A file class that can be customized with callbacks.
+
+
+#include "file_util.h"
+#include "utility.h"
+#include <string.h>
+
+
+static const char* reverse_scan(const char* begin, const char* end, char c)
+// Scans in reverse, from *(end-1) through *begin, until it finds a
+// character matching c.  If none is found, returns end, else returns
+// a pointer to the char.
+{
+	assert(begin <= end);
+	
+	const char* p = end;
+	while (p > begin) {
+		p--;
+		if (*p == c) {
+			return p;
+		}
+	}
+
+	return end;
+}
+
+
+const char* file_util::get_extension(const char* path)
+{
+	int len = strlen(path);
+	const char* last_dot = reverse_scan(path, path + len, '.');
+	const char* last_slash = reverse_scan(last_dot, path + len, '/');
+
+	if (last_dot[0] && last_slash[0] == 0) {
+		return last_dot + 1;
+	}
+
+	// No apparent file extension, return an empty string.
+	return path + len;
+}
+
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/file_util.h
diff -u gnash/libbase/file_util.h:1.1 gnash/libbase/file_util.h:1.2
--- gnash/libbase/file_util.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/file_util.h	Sun Feb 26 15:49:29 2006
@@ -1,36 +1,36 @@
-// file_util.h	-- Thatcher Ulrich 2005
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Misc file-handling utilities.
-
-
-#ifndef FILE_UTIL_H
-#define FILE_UTIL_H
-
-
-#include "tu_config.h"
-
-
-namespace file_util {
-	// Return a pointer to the file extension.  This is the last
-	// bit of the filename after the last '.'.  If there's no '.',
-	// or it appears before the last '/', then the return value
-	// points to an empty string.
-	//
-	// Does not point to the '.' itself;
-	// i.e. get_extension("test.txt") will return "txt".
-	const char* get_extension(const char* path);
-}
-
-
-#endif // FILE_UTIL_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// file_util.h	-- Thatcher Ulrich 2005
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Misc file-handling utilities.
+
+
+#ifndef FILE_UTIL_H
+#define FILE_UTIL_H
+
+
+#include "tu_config.h"
+
+
+namespace file_util {
+	// Return a pointer to the file extension.  This is the last
+	// bit of the filename after the last '.'.  If there's no '.',
+	// or it appears before the last '/', then the return value
+	// points to an empty string.
+	//
+	// Does not point to the '.' itself;
+	// i.e. get_extension("test.txt") will return "txt".
+	const char* get_extension(const char* path);
+}
+
+
+#endif // FILE_UTIL_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/image.cpp
diff -u gnash/libbase/image.cpp:1.4 gnash/libbase/image.cpp:1.5
--- gnash/libbase/image.cpp:1.4	Wed Feb 15 13:53:27 2006
+++ gnash/libbase/image.cpp	Sun Feb 26 15:49:29 2006
@@ -1,528 +1,528 @@
-// image.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2002
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Handy image utilities for RGB surfaces.
-
-#include "image.h"
-
-#include "container.h"
-#include "utility.h"
-#include "jpeg.h"
-#include "tu_file.h"
-#include <stdlib.h>
-#include <string.h>
-
-
-namespace image
-{
-	//
-	// image_base
-	//
-	image_base::image_base(Uint8* data, int width, int height, int pitch)
-		:
-		m_data(data),
-		m_width(width),
-		m_height(height),
-		m_pitch(pitch)
-	{
-	}
-
-
-	Uint8*	scanline(image_base* surf, int y)
-	{
-		assert(surf);
-		assert(y >= 0 && y < surf->m_height);
-		return ((Uint8*) surf->m_data) + surf->m_pitch * y;
-	}
-
-
-	const Uint8*	scanline(const image_base* surf, int y)
-	{
-		assert(surf);
-		assert(y >= 0 && y < surf->m_height);
-		return ((const Uint8*) surf->m_data) + surf->m_pitch * y;
-	}
-
-
-	//
-	// rgb
-	//
-
-	rgb::rgb(int width, int height)
-		:
-		image_base(
-			0,
-			width,
-			height,
-			(width * 3 + 3) & ~3)	// round pitch up to nearest 4-byte boundary
-	{
-		assert(width > 0);
-		assert(height > 0);
-		assert(m_pitch >= m_width * 3);
-		assert((m_pitch & 3) == 0);
-
-//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
-		m_data = new Uint8[m_pitch * m_height];
-	}
-
-	rgb::~rgb()
-	{
-		if (m_data) {
-//			dlfree(m_data);
-			delete [] m_data;
-			m_data = 0;
-		}
-	}
-
-
-	rgb*	create_rgb(int width, int height)
-	// Create an system-memory rgb surface.  The data order is
-	// packed 24-bit, RGBRGB..., regardless of the endian-ness of
-	// the CPU.
-	{
-		rgb*	s = new rgb(width, height);
-
-		return s;
-	}
-
-
-	//
-	// rgba
-	//
-
-
-	rgba::rgba(int width, int height)
-		:
-		image_base(0, width, height, width * 4)
-	{
-		assert(width > 0);
-		assert(height > 0);
-		assert(m_pitch >= m_width * 4);
-		assert((m_pitch & 3) == 0);
-
-//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
-		m_data = new Uint8[m_pitch * m_height];
-	}
-
-	rgba::~rgba()
-	{
-		if (m_data) {
-//			dlfree(m_data);
-			delete [] m_data;
-			m_data = 0;
-		}
-	}
-
-
-	rgba*	create_rgba(int width, int height)
-	// Create an system-memory rgb surface.  The data order is
-	// packed 32-bit, RGBARGBA..., regardless of the endian-ness
-	// of the CPU.
-	{
-		rgba*	s = new rgba(width, height);
-
-		return s;
-	}
-
-
-	void	rgba::set_pixel(int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
-	// Set the pixel at the given position.
-	{
-		assert(x >= 0 && x < m_width);
-		assert(y >= 0 && y < m_height);
-
-		Uint8*	data = scanline(this, y) + 4 * x;
-
-		data[0] = r;
-		data[1] = g;
-		data[2] = b;
-		data[3] = a;
-	}
-
-
-	//
-	// alpha
-	//
-
-
-	alpha*	create_alpha(int width, int height)
-	// Create an system-memory 8-bit alpha surface.
-	{
-		alpha*	s = new alpha(width, height);
-
-		return s;
-	}
-
-
-	alpha::alpha(int width, int height)
-		:
-		image_base(0, width, height, width)
-	{
-		assert(width > 0);
-		assert(height > 0);
-
-//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
-		m_data = new Uint8[m_pitch * m_height];
-	}
-
-
-	alpha::~alpha()
-	{
-		if (m_data) {
-//			dlfree(m_data);
-			delete [] m_data;
-			m_data = 0;
-		}
-	}
-
-
-	void	alpha::set_pixel(int x, int y, Uint8 a)
-	// Set the pixel at the given position.
-	{
-		assert(x >= 0 && x < m_width);
-		assert(y >= 0 && y < m_height);
-
-		Uint8*	data = scanline(this, y) + x;
-
-		data[0] = a;
-	}
-
-
-	bool	alpha::operator==(const alpha& a) const
-	// Bitwise content comparison.
-	{
-		if (m_width != a.m_width
-		    || m_height != a.m_height)
-		{
-			return false;
-		}
-
-		for (int j = 0, n = m_height; j < n; j++)
-		{
-			if (memcmp(scanline(this, j), scanline(&a, j), m_width))
-			{
-				// Mismatch.
-				return false;
-			}
-		}
-
-		// Images are identical.
-		return true;
-	}
-
-
-	unsigned int	alpha::compute_hash() const
-	// Compute a hash code based on image contents.  Can be useful
-	// for comparing images.
-	{
-		unsigned int	h = bernstein_hash(&m_width, sizeof(m_width));
-		h = bernstein_hash(&m_height, sizeof(m_height), h);
-
-		for (int i = 0, n = m_height; i < n; i++)
-		{
-			h = bernstein_hash(scanline(this, i), m_width, h);
-		}
-
-		return h;
-	}
-
-
-	//
-	// utility
-	//
-
-
-	void	write_jpeg(tu_file* out, rgb* image, int quality)
-	// Write the given image to the given out stream, in jpeg format.
-	{
-		jpeg::output*	j_out = jpeg::output::create(out, image->m_width, image->m_height, \
                quality);
-
-		for (int y = 0; y < image->m_height; y++) {
-			j_out->write_scanline(scanline(image, y));
-		}
-
-		delete j_out;
-	}
-
-
-	rgb*	read_jpeg(const char* filename)
-	// Create and read a new image from the given filename, if possible.
-	{
-		tu_file	in(filename, "rb");	// file automatically closes when 'in' goes out of \
                scope.
-		if (! in.get_error())
-		{
-			rgb*	im = read_jpeg(&in);
-			return im;
-		}
-		else
-		{
-			return NULL;
-		}
-	}
-
-
-	rgb*	read_jpeg(tu_file* in)
-	// Create and read a new image from the stream.
-	{
-		jpeg::input*	j_in = jpeg::input::create(in);
-		if (j_in == NULL) return NULL;
-		
-		rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
-
-		for (int y = 0; y < j_in->get_height(); y++)
-		{
-			j_in->read_scanline(scanline(im, y));
-		}
-
-		delete j_in;
-
-		return im;
-	}
-
-
-	rgb*	read_swf_jpeg2(tu_file* in)
-	// Create and read a new image from the stream.  Image is in
-	// SWF JPEG2-style format (the encoding tables come first in a
-	// separate "stream" -- otherwise it's just normal JPEG).  The
-	// IJG documentation describes this as "abbreviated" format.
-	{
-		jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
-		if (j_in == NULL) return NULL;
+// image.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2002
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Handy image utilities for RGB surfaces.
+
+#include "image.h"
+
+#include "container.h"
+#include "utility.h"
+#include "jpeg.h"
+#include "tu_file.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+namespace image
+{
+	//
+	// image_base
+	//
+	image_base::image_base(Uint8* data, int width, int height, int pitch)
+		:
+		m_data(data),
+		m_width(width),
+		m_height(height),
+		m_pitch(pitch)
+	{
+	}
+
+
+	Uint8*	scanline(image_base* surf, int y)
+	{
+		assert(surf);
+		assert(y >= 0 && y < surf->m_height);
+		return ((Uint8*) surf->m_data) + surf->m_pitch * y;
+	}
+
+
+	const Uint8*	scanline(const image_base* surf, int y)
+	{
+		assert(surf);
+		assert(y >= 0 && y < surf->m_height);
+		return ((const Uint8*) surf->m_data) + surf->m_pitch * y;
+	}
+
+
+	//
+	// rgb
+	//
+
+	rgb::rgb(int width, int height)
+		:
+		image_base(
+			0,
+			width,
+			height,
+			(width * 3 + 3) & ~3)	// round pitch up to nearest 4-byte boundary
+	{
+		assert(width > 0);
+		assert(height > 0);
+		assert(m_pitch >= m_width * 3);
+		assert((m_pitch & 3) == 0);
+
+//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
+		m_data = new Uint8[m_pitch * m_height];
+	}
+
+	rgb::~rgb()
+	{
+		if (m_data) {
+//			dlfree(m_data);
+			delete [] m_data;
+			m_data = 0;
+		}
+	}
+
+
+	rgb*	create_rgb(int width, int height)
+	// Create an system-memory rgb surface.  The data order is
+	// packed 24-bit, RGBRGB..., regardless of the endian-ness of
+	// the CPU.
+	{
+		rgb*	s = new rgb(width, height);
+
+		return s;
+	}
+
+
+	//
+	// rgba
+	//
+
+
+	rgba::rgba(int width, int height)
+		:
+		image_base(0, width, height, width * 4)
+	{
+		assert(width > 0);
+		assert(height > 0);
+		assert(m_pitch >= m_width * 4);
+		assert((m_pitch & 3) == 0);
+
+//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
+		m_data = new Uint8[m_pitch * m_height];
+	}
+
+	rgba::~rgba()
+	{
+		if (m_data) {
+//			dlfree(m_data);
+			delete [] m_data;
+			m_data = 0;
+		}
+	}
+
+
+	rgba*	create_rgba(int width, int height)
+	// Create an system-memory rgb surface.  The data order is
+	// packed 32-bit, RGBARGBA..., regardless of the endian-ness
+	// of the CPU.
+	{
+		rgba*	s = new rgba(width, height);
+
+		return s;
+	}
+
+
+	void	rgba::set_pixel(int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+	// Set the pixel at the given position.
+	{
+		assert(x >= 0 && x < m_width);
+		assert(y >= 0 && y < m_height);
+
+		Uint8*	data = scanline(this, y) + 4 * x;
+
+		data[0] = r;
+		data[1] = g;
+		data[2] = b;
+		data[3] = a;
+	}
+
+
+	//
+	// alpha
+	//
+
+
+	alpha*	create_alpha(int width, int height)
+	// Create an system-memory 8-bit alpha surface.
+	{
+		alpha*	s = new alpha(width, height);
+
+		return s;
+	}
+
+
+	alpha::alpha(int width, int height)
+		:
+		image_base(0, width, height, width)
+	{
+		assert(width > 0);
+		assert(height > 0);
+
+//		m_data = (Uint8*) dlmalloc(m_pitch * m_height);
+		m_data = new Uint8[m_pitch * m_height];
+	}
+
+
+	alpha::~alpha()
+	{
+		if (m_data) {
+//			dlfree(m_data);
+			delete [] m_data;
+			m_data = 0;
+		}
+	}
+
+
+	void	alpha::set_pixel(int x, int y, Uint8 a)
+	// Set the pixel at the given position.
+	{
+		assert(x >= 0 && x < m_width);
+		assert(y >= 0 && y < m_height);
+
+		Uint8*	data = scanline(this, y) + x;
+
+		data[0] = a;
+	}
+
+
+	bool	alpha::operator==(const alpha& a) const
+	// Bitwise content comparison.
+	{
+		if (m_width != a.m_width
+		    || m_height != a.m_height)
+		{
+			return false;
+		}
+
+		for (int j = 0, n = m_height; j < n; j++)
+		{
+			if (memcmp(scanline(this, j), scanline(&a, j), m_width))
+			{
+				// Mismatch.
+				return false;
+			}
+		}
+
+		// Images are identical.
+		return true;
+	}
+
+
+	unsigned int	alpha::compute_hash() const
+	// Compute a hash code based on image contents.  Can be useful
+	// for comparing images.
+	{
+		unsigned int	h = bernstein_hash(&m_width, sizeof(m_width));
+		h = bernstein_hash(&m_height, sizeof(m_height), h);
+
+		for (int i = 0, n = m_height; i < n; i++)
+		{
+			h = bernstein_hash(scanline(this, i), m_width, h);
+		}
+
+		return h;
+	}
+
+
+	//
+	// utility
+	//
+
+
+	void	write_jpeg(tu_file* out, rgb* image, int quality)
+	// Write the given image to the given out stream, in jpeg format.
+	{
+		jpeg::output*	j_out = jpeg::output::create(out, image->m_width, image->m_height, \
quality); +
+		for (int y = 0; y < image->m_height; y++) {
+			j_out->write_scanline(scanline(image, y));
+		}
+
+		delete j_out;
+	}
+
+
+	rgb*	read_jpeg(const char* filename)
+	// Create and read a new image from the given filename, if possible.
+	{
+		tu_file	in(filename, "rb");	// file automatically closes when 'in' goes out of \
scope. +		if (! in.get_error())
+		{
+			rgb*	im = read_jpeg(&in);
+			return im;
+		}
+		else
+		{
+			return NULL;
+		}
+	}
+
+
+	rgb*	read_jpeg(tu_file* in)
+	// Create and read a new image from the stream.
+	{
+		jpeg::input*	j_in = jpeg::input::create(in);
+		if (j_in == NULL) return NULL;
+		
+		rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
+
+		for (int y = 0; y < j_in->get_height(); y++)
+		{
+			j_in->read_scanline(scanline(im, y));
+		}
+
+		delete j_in;
+
+		return im;
+	}
+
+
+	rgb*	read_swf_jpeg2(tu_file* in)
+	// Create and read a new image from the stream.  Image is in
+	// SWF JPEG2-style format (the encoding tables come first in a
+	// separate "stream" -- otherwise it's just normal JPEG).  The
+	// IJG documentation describes this as "abbreviated" format.
+	{
+		jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
+		if (j_in == NULL) return NULL;
 		
 		rgb* im = read_swf_jpeg2_with_tables(j_in);
-
-		delete j_in;
-
+
+		delete j_in;
+
 		return im;		
-	}
-
-
-	rgb*	read_swf_jpeg2_with_tables(jpeg::input* j_in)
-	// Create and read a new image, using a input object that
-	// already has tables loaded.
-	{
-		assert(j_in);
-
-		j_in->start_image();
-
-		rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
-
-		for (int y = 0; y < j_in->get_height(); y++) {
-			j_in->read_scanline(scanline(im, y));
-		}
-
-		j_in->finish_image();
-
-		return im;
-	}
-
-
-	rgba*	read_swf_jpeg3(tu_file* in)
-	// For reading SWF JPEG3-style image data, like ordinary JPEG, 
-	// but stores the data in rgba format.
-	{
-		jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
-		if (j_in == NULL) return NULL;
-		
-		j_in->start_image();
-
-		rgba*	im = image::create_rgba(j_in->get_width(), j_in->get_height());
-
-		Uint8*	line = new Uint8[3*j_in->get_width()];
-
-		for (int y = 0; y < j_in->get_height(); y++) 
-		{
-			j_in->read_scanline(line);
-
-			Uint8*	data = scanline(im, y);
-			for (int x = 0; x < j_in->get_width(); x++) 
-			{
-				data[4*x+0] = line[3*x+0];
-				data[4*x+1] = line[3*x+1];
-				data[4*x+2] = line[3*x+2];
-				data[4*x+3] = 255;
-			}
-		}
-
-		delete [] line;
-
-		j_in->finish_image();
-		delete j_in;
-
-		return im;
-	}
-
-
-	void	write_tga(tu_file* out, rgba* im)
-	// Write a 32-bit Targa format bitmap.  Dead simple, no compression.
-	{
-		out->write_byte(0);
-		out->write_byte(0);
-		out->write_byte(2);	/* uncompressed RGB */
-		out->write_le16(0);
-		out->write_le16(0);
-		out->write_byte(0);
-		out->write_le16(0);	/* X origin */
-		out->write_le16(0);	/* y origin */
-		out->write_le16(im->m_width);
-		out->write_le16(im->m_height);
-		out->write_byte(32);	/* 32 bit bitmap */
-		out->write_byte(0);
-
-		for (int y = 0; y < im->m_height; y++)
-		{
-			uint8*	p = scanline(im, y);
-			for (int x = 0; x < im->m_width; x++)
-			{
-				out->write_byte(p[x * 4]);
-				out->write_byte(p[x * 4 + 1]);
-				out->write_byte(p[x * 4 + 2]);
-				out->write_byte(p[x * 4 + 3]);
-			}
-		}
-	}
-
-
-#if 0
-	SDL_Surface*	create_SDL_Surface(rgb* image)
-	// Steal *image's data to create an SDL_Surface.
-	//
-	// DELETES image!!!
-	{
-		assert(image->m_pitch < 65536);	// SDL_Surface only uses Uint16 for pitch!!!
-
-		SDL_Surface*	s = SDL_CreateRGBSurfaceFrom(image->m_data,
-							     image->m_width, image->m_height, 24, image->m_pitch,
-							     SDL_SwapLE32(0x0FF),
-							     SDL_SwapLE32(0x0FF00),
-							     SDL_SwapLE32(0x0FF0000),
-							     0);
-
-		// s owns *image's data now -- invalidate *image.
-		image->m_data = 0;
-		image->m_height = 0;
-		image->m_width = 0;
-		image->m_pitch = 0;
-		delete image;
-
-		assert(s->pixels);
-		assert(s->format->BytesPerPixel == 3);
-		assert(s->format->BitsPerPixel == 24);
-
-		return s;
-	}
-#endif // 0
-
-	void	make_next_miplevel(rgb* image)
-	// Fast, in-place resample.  For making mip-maps.  Munges the
-	// input image to produce the output image.
-	{
-		assert(image->m_data);
-
-		int	new_w = image->m_width >> 1;
-		int	new_h = image->m_height >> 1;
-		if (new_w < 1) new_w = 1;
-		if (new_h < 1) new_h = 1;
-
-		int	new_pitch = new_w * 3;
-		// Round pitch up to the nearest 4-byte boundary.
-		new_pitch = (new_pitch + 3) & ~3;
-
-		if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
-		{
-			// Image can't be shrunk along (at least) one
-			// of its dimensions, so don't bother
-			// resampling.  Technically we should, but
-			// it's pretty useless at this point.  Just
-			// change the image dimensions and leave the
-			// existing pixels.
-		}
-		else
-		{
-			// Resample.  Simple average 2x2 --> 1, in-place.
-			int	pitch = image->m_pitch;
-			for (int j = 0; j < new_h; j++) {
-				Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
-				Uint8*	in = ((Uint8*) image->m_data) + (j << 1) * pitch;
-				for (int i = 0; i < new_w; i++) {
-					int	r, g, b;
-					r = (*(in + 0) + *(in + 3) + *(in + 0 + pitch) + *(in + 3 + pitch));
-					g = (*(in + 1) + *(in + 4) + *(in + 1 + pitch) + *(in + 4 + pitch));
-					b = (*(in + 2) + *(in + 5) + *(in + 2 + pitch) + *(in + 5 + pitch));
-					*(out + 0) = r >> 2;
-					*(out + 1) = g >> 2;
-					*(out + 2) = b >> 2;
-					out += 3;
-					in += 6;
-				}
-			}
-		}
-
-		// Munge image's members to reflect the shrunken image.
-		image->m_width = new_w;
-		image->m_height = new_h;
-		image->m_pitch = new_pitch;
-	}
-
-
-	void	make_next_miplevel(rgba* image)
-	// Fast, in-place resample.  For making mip-maps.  Munges the
-	// input image to produce the output image.
-	{
-		assert(image->m_data);
-
-		int	new_w = image->m_width >> 1;
-		int	new_h = image->m_height >> 1;
-		if (new_w < 1) new_w = 1;
-		if (new_h < 1) new_h = 1;
-
-		int	new_pitch = new_w * 4;
-
-		if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
-		{
-			// Image can't be shrunk along (at least) one
-			// of its dimensions, so don't bother
-			// resampling.  Technically we should, but
-			// it's pretty useless at this point.  Just
-			// change the image dimensions and leave the
-			// existing pixels.
-		}
-		else
-		{
-			// Resample.  Simple average 2x2 --> 1, in-place.
-			int	pitch = image->m_pitch;
-			for (int j = 0; j < new_h; j++) {
-				Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
-				Uint8*	in = ((Uint8*) image->m_data) + (j << 1) * pitch;
-				for (int i = 0; i < new_w; i++) {
-					int	r, g, b, a;
-					r = (*(in + 0) + *(in + 4) + *(in + 0 + pitch) + *(in + 4 + pitch));
-					g = (*(in + 1) + *(in + 5) + *(in + 1 + pitch) + *(in + 5 + pitch));
-					b = (*(in + 2) + *(in + 6) + *(in + 2 + pitch) + *(in + 6 + pitch));
-					a = (*(in + 3) + *(in + 7) + *(in + 3 + pitch) + *(in + 7 + pitch));
-					*(out + 0) = r >> 2;
-					*(out + 1) = g >> 2;
-					*(out + 2) = b >> 2;
-					*(out + 3) = a >> 2;
-					out += 4;
-					in += 8;
-				}
-			}
-		}
-
-		// Munge image's members to reflect the shrunken image.
-		image->m_width = new_w;
-		image->m_height = new_h;
-		image->m_pitch = new_pitch;
-	}
-};
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+	}
+
+
+	rgb*	read_swf_jpeg2_with_tables(jpeg::input* j_in)
+	// Create and read a new image, using a input object that
+	// already has tables loaded.
+	{
+		assert(j_in);
+
+		j_in->start_image();
+
+		rgb*	im = image::create_rgb(j_in->get_width(), j_in->get_height());
+
+		for (int y = 0; y < j_in->get_height(); y++) {
+			j_in->read_scanline(scanline(im, y));
+		}
+
+		j_in->finish_image();
+
+		return im;
+	}
+
+
+	rgba*	read_swf_jpeg3(tu_file* in)
+	// For reading SWF JPEG3-style image data, like ordinary JPEG, 
+	// but stores the data in rgba format.
+	{
+		jpeg::input*	j_in = jpeg::input::create_swf_jpeg2_header_only(in);
+		if (j_in == NULL) return NULL;
+		
+		j_in->start_image();
+
+		rgba*	im = image::create_rgba(j_in->get_width(), j_in->get_height());
+
+		Uint8*	line = new Uint8[3*j_in->get_width()];
+
+		for (int y = 0; y < j_in->get_height(); y++) 
+		{
+			j_in->read_scanline(line);
+
+			Uint8*	data = scanline(im, y);
+			for (int x = 0; x < j_in->get_width(); x++) 
+			{
+				data[4*x+0] = line[3*x+0];
+				data[4*x+1] = line[3*x+1];
+				data[4*x+2] = line[3*x+2];
+				data[4*x+3] = 255;
+			}
+		}
+
+		delete [] line;
+
+		j_in->finish_image();
+		delete j_in;
+
+		return im;
+	}
+
+
+	void	write_tga(tu_file* out, rgba* im)
+	// Write a 32-bit Targa format bitmap.  Dead simple, no compression.
+	{
+		out->write_byte(0);
+		out->write_byte(0);
+		out->write_byte(2);	/* uncompressed RGB */
+		out->write_le16(0);
+		out->write_le16(0);
+		out->write_byte(0);
+		out->write_le16(0);	/* X origin */
+		out->write_le16(0);	/* y origin */
+		out->write_le16(im->m_width);
+		out->write_le16(im->m_height);
+		out->write_byte(32);	/* 32 bit bitmap */
+		out->write_byte(0);
+
+		for (int y = 0; y < im->m_height; y++)
+		{
+			uint8*	p = scanline(im, y);
+			for (int x = 0; x < im->m_width; x++)
+			{
+				out->write_byte(p[x * 4]);
+				out->write_byte(p[x * 4 + 1]);
+				out->write_byte(p[x * 4 + 2]);
+				out->write_byte(p[x * 4 + 3]);
+			}
+		}
+	}
+
+
+#if 0
+	SDL_Surface*	create_SDL_Surface(rgb* image)
+	// Steal *image's data to create an SDL_Surface.
+	//
+	// DELETES image!!!
+	{
+		assert(image->m_pitch < 65536);	// SDL_Surface only uses Uint16 for pitch!!!
+
+		SDL_Surface*	s = SDL_CreateRGBSurfaceFrom(image->m_data,
+							     image->m_width, image->m_height, 24, image->m_pitch,
+							     SDL_SwapLE32(0x0FF),
+							     SDL_SwapLE32(0x0FF00),
+							     SDL_SwapLE32(0x0FF0000),
+							     0);
+
+		// s owns *image's data now -- invalidate *image.
+		image->m_data = 0;
+		image->m_height = 0;
+		image->m_width = 0;
+		image->m_pitch = 0;
+		delete image;
+
+		assert(s->pixels);
+		assert(s->format->BytesPerPixel == 3);
+		assert(s->format->BitsPerPixel == 24);
+
+		return s;
+	}
+#endif // 0
+
+	void	make_next_miplevel(rgb* image)
+	// Fast, in-place resample.  For making mip-maps.  Munges the
+	// input image to produce the output image.
+	{
+		assert(image->m_data);
+
+		int	new_w = image->m_width >> 1;
+		int	new_h = image->m_height >> 1;
+		if (new_w < 1) new_w = 1;
+		if (new_h < 1) new_h = 1;
+
+		int	new_pitch = new_w * 3;
+		// Round pitch up to the nearest 4-byte boundary.
+		new_pitch = (new_pitch + 3) & ~3;
+
+		if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
+		{
+			// Image can't be shrunk along (at least) one
+			// of its dimensions, so don't bother
+			// resampling.  Technically we should, but
+			// it's pretty useless at this point.  Just
+			// change the image dimensions and leave the
+			// existing pixels.
+		}
+		else
+		{
+			// Resample.  Simple average 2x2 --> 1, in-place.
+			int	pitch = image->m_pitch;
+			for (int j = 0; j < new_h; j++) {
+				Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
+				Uint8*	in = ((Uint8*) image->m_data) + (j << 1) * pitch;
+				for (int i = 0; i < new_w; i++) {
+					int	r, g, b;
+					r = (*(in + 0) + *(in + 3) + *(in + 0 + pitch) + *(in + 3 + pitch));
+					g = (*(in + 1) + *(in + 4) + *(in + 1 + pitch) + *(in + 4 + pitch));
+					b = (*(in + 2) + *(in + 5) + *(in + 2 + pitch) + *(in + 5 + pitch));
+					*(out + 0) = r >> 2;
+					*(out + 1) = g >> 2;
+					*(out + 2) = b >> 2;
+					out += 3;
+					in += 6;
+				}
+			}
+		}
+
+		// Munge image's members to reflect the shrunken image.
+		image->m_width = new_w;
+		image->m_height = new_h;
+		image->m_pitch = new_pitch;
+	}
+
+
+	void	make_next_miplevel(rgba* image)
+	// Fast, in-place resample.  For making mip-maps.  Munges the
+	// input image to produce the output image.
+	{
+		assert(image->m_data);
+
+		int	new_w = image->m_width >> 1;
+		int	new_h = image->m_height >> 1;
+		if (new_w < 1) new_w = 1;
+		if (new_h < 1) new_h = 1;
+
+		int	new_pitch = new_w * 4;
+
+		if (new_w * 2 != image->m_width  || new_h * 2 != image->m_height)
+		{
+			// Image can't be shrunk along (at least) one
+			// of its dimensions, so don't bother
+			// resampling.  Technically we should, but
+			// it's pretty useless at this point.  Just
+			// change the image dimensions and leave the
+			// existing pixels.
+		}
+		else
+		{
+			// Resample.  Simple average 2x2 --> 1, in-place.
+			int	pitch = image->m_pitch;
+			for (int j = 0; j < new_h; j++) {
+				Uint8*	out = ((Uint8*) image->m_data) + j * new_pitch;
+				Uint8*	in = ((Uint8*) image->m_data) + (j << 1) * pitch;
+				for (int i = 0; i < new_w; i++) {
+					int	r, g, b, a;
+					r = (*(in + 0) + *(in + 4) + *(in + 0 + pitch) + *(in + 4 + pitch));
+					g = (*(in + 1) + *(in + 5) + *(in + 1 + pitch) + *(in + 5 + pitch));
+					b = (*(in + 2) + *(in + 6) + *(in + 2 + pitch) + *(in + 6 + pitch));
+					a = (*(in + 3) + *(in + 7) + *(in + 3 + pitch) + *(in + 7 + pitch));
+					*(out + 0) = r >> 2;
+					*(out + 1) = g >> 2;
+					*(out + 2) = b >> 2;
+					*(out + 3) = a >> 2;
+					out += 4;
+					in += 8;
+				}
+			}
+		}
+
+		// Munge image's members to reflect the shrunken image.
+		image->m_width = new_w;
+		image->m_height = new_h;
+		image->m_pitch = new_pitch;
+	}
+};
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/image_filters.cpp
diff -u gnash/libbase/image_filters.cpp:1.3 gnash/libbase/image_filters.cpp:1.4
--- gnash/libbase/image_filters.cpp:1.3	Sat Feb 25 03:54:03 2006
+++ gnash/libbase/image_filters.cpp	Sun Feb 26 15:49:30 2006
@@ -1,825 +1,825 @@
-// image_filters.cpp	-- Original code by Dale Schumacher, public domain 1991
-
-// See _Graphics Gems III_ "General Filtered Image Rescaling", Dale A. Schumacher
-
-// Modifications by Thatcher Ulrich <tu@tulrich.com> 2002
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// A series of image rescaling functions.  tulrich: Mostly I just
-// converted from K&R C to C-like C++, changed the interfaces a bit,
-// etc.
-
-
-#include "image.h"
-#include "utility.h"
-#include "container.h"
-#include "tu_math.h"
-#include <stdio.h>
-#include <string.h>
-
-
-namespace {
-// anonymous namespace to hold local stuff.
-
-
-inline void* my_calloc(int count, int size)
-{
-	void*	mem = (void*) new char[count * size];
-	memset(mem, 0, count * size);
-	return mem;
-}
-
-
-inline void	my_cfree(void* mem)
-{
-	delete [] (char*) mem;
-}
-
-
-void	get_row(Uint8* row, image::rgb* image, int x0, int xsize, int y)
-// Copy RGB data from the specified row into the given buffer.
-{
-	y = iclamp(y, 0, image->m_height - 1);
-	int	x1 = x0 + xsize - 1;
-	if (x1 >= image->m_width) {
-		// clip, then extend.
-		int	extra_pixels = x1 - image->m_width + 1;
-		Uint8*	p = ((Uint8*) image->m_data) + (y * image->m_pitch);
-		memcpy(row, p + x0 * 3, (3 * (image->m_width - x0)));
-		// repeat last pixel
-		p = p + (image->m_width - 1) * 3;
-		Uint8*	q = row + (image->m_width - x0) * 3;
-		while (extra_pixels > 0) {
-			*(q + 0) = *(p + 0);
-			*(q + 1) = *(p + 1);
-			*(q + 2) = *(p + 2);
-			q += 3;
-			extra_pixels--;
-		}
-	}
-	else
-	{
-		memcpy(row, ((Uint8*) image->m_data) + (y * image->m_pitch) + x0 * 3, (3 * \
                xsize));
-	}
-}
-
-
-void	get_row(Uint8* row, image::rgba* image, int x0, int xsize, int y)
-// Copy RGBA data from the specified row into the given buffer.
-{
-	y = iclamp(y, 0, image->m_height - 1);
-	int	x1 = x0 + xsize - 1;
-	if (x1 >= image->m_width) {
-		// clip, then extend.
-		int	extra_pixels = x1 - image->m_width + 1;
-		Uint8*	p = ((Uint8*) image->m_data) + (y * image->m_pitch);
-		memcpy(row, p + x0 * 4, (4 * (image->m_width - x0)));
-		// repeat last pixel
-		p = p + (image->m_width - 1) * 4;
-		Uint8*	q = row + (image->m_width - x0) * 4;
-		while (extra_pixels > 0) {
-			*(q + 0) = *(p + 0);
-			*(q + 1) = *(p + 1);
-			*(q + 2) = *(p + 2);
-			*(q + 3) = *(p + 3);
-			q += 4;
-			extra_pixels--;
-		}
-	}
-	else
-	{
-		memcpy(row, ((Uint8*) image->m_data) + (y * image->m_pitch) + x0 * 4, (4 * \
                xsize));
-	}
-}
-
-
-void	get_column(Uint8* column, image::rgb* image, int x)
-// Copy RGB data from the specified column into the given buffer.
-{
-	int	i, d;
-	Uint8*	p;
-
-	if ((x < 0) || (x >= image->m_width)) {
-		assert(0);
-		x = iclamp(x, 0, image->m_width - 1);
-	}
-
-	d = image->m_pitch;
-	for (i = image->m_height, p = ((Uint8*) image->m_data) + x * 3; i-- > 0; p += d) {
-		*column++ = *p;
-		*column++ = *(p + 1);
-		*column++ = *(p + 2);
-	}
-}
-
-
-void	get_column(Uint8* column, image::rgba* image, int x)
-// Copy RGBA data from the specified column into the given buffer.
-{
-	int	i, d;
-	Uint8*	p;
-
-	if ((x < 0) || (x >= image->m_width)) {
-		assert(0);
-		x = iclamp(x, 0, image->m_width - 1);
-	}
-
-	d = image->m_pitch;
-	for (i = image->m_height, p = ((Uint8*) image->m_data) + x * 4; i-- > 0; p += d) {
-		*column++ = *p;
-		*column++ = *(p + 1);
-		*column++ = *(p + 2);
-		*column++ = *(p + 3);
-	}
-}
-
-
-void	put_pixel(image::rgb* image, int x, int y, float r, float g, float b)
-// Clamp {r, g, b} to [0,255], and write pixel data to the given image
-// at (x, y).
-{
-	static image::rgb*	im = NULL;
-	static int	yy = -1;
-	static Uint8*	p = NULL;
-
-	if ((x < 0) || (x >= image->m_width) || (y < 0) || (y >= image->m_height)) {
-		assert(0);
-		return;
-	}
-	if ((im != image) || (yy != y)) {
-		im = image;
-		yy = y;
-		p = ((Uint8*) image->m_data) + (y * image->m_pitch);
-	}
-	p[x * 3 + 0] = iclamp(frnd(r), 0, 255);
-	p[x * 3 + 1] = iclamp(frnd(g), 0, 255);
-	p[x * 3 + 2] = iclamp(frnd(b), 0, 255);
-}
-
-
-void	put_pixel(image::rgba* image, int x, int y, float r, float g, float b, float a)
-// Clamp {r, g, b, a} to [0,255], and write pixel data to the given image
-// at (x, y).
-{
-	static image::rgba*	im = NULL;
-	static int	yy = -1;
-	static Uint8*	p = NULL;
-
-	if ((x < 0) || (x >= image->m_width) || (y < 0) || (y >= image->m_height)) {
-		assert(0);
-		return;
-	}
-	if ((im != image) || (yy != y)) {
-		im = image;
-		yy = y;
-		p = ((Uint8*) image->m_data) + (y * image->m_pitch);
-	}
-	p[x * 4	+ 0] = iclamp(frnd(r), 0, 255);
-	p[x * 4	+ 1] = iclamp(frnd(g), 0, 255);
-	p[x * 4	+ 2] = iclamp(frnd(b), 0, 255);
-	p[x * 4	+ 3] = iclamp(frnd(a), 0, 255);
-}
-
-
-/*
- *	filter function definitions
- */
-
-
-// SOME_CUBIC
-
-#define	cubic_filter_support		(1.0f)
-
-float	cubic_filter(float t)
-// Cubix approximation to the central hump of Sinc.
-{
-	/* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
-	if(t < 0.0f) t = -t;
-	if(t < 1.0f) return((2.0f * t - 3.0f) * t * t + 1.0f);
-	return(0.0f);
-}
-
-
-// BOX
-
-#define	box_support		(0.5f)
-
-float	box_filter(float t)
-{
-	if((t > -0.5) && (t <= 0.5)) return(1.0);
-	return(0.0);
-}
-
-
-// TRIANGLE
-
-#define	triangle_support	(1.0)
-
-float	triangle_filter(float t)
-{
-	if(t < 0.0f) t = -t;
-	if(t < 1.0f) return(1.0f - t);
-	return(0.0f);
-}
-
-
-// BELL
-
-#define	bell_support		(1.5)
-
-float	bell_filter(float t)
-/* box (*) box (*) box */
-{
-	if(t < 0) t = -t;
-	if(t < 0.5f) return(0.75f - (t * t));
-	if(t < 1.5f) {
-		t = (t - 1.5f);
-		return(0.5f * (t * t));
-	}
-	return(0.0f);
-}
-
-
-// B_SPLINE
-
-#define	B_spline_support	(2.0f)
-
-float	B_spline_filter(float t)
-/* box (*) box (*) box (*) box */
-{
-	float	tt;
-
-	if(t < 0.0f) t = -t;
-	if(t < 1.0f) {
-		tt = t * t;
-		return((0.5f * tt * t) - tt + (2.0f / 3.0f));
-	} else if (t < 2.0f) {
-		t = 2.0f - t;
-		return((1.0f / 6.0f) * (t * t * t));
-	}
-	return(0.0f);
-}
-
-
-// LANCZOS3
-
-float	sinc(float x)
-{
-	x *= (float) M_PI;
-	if (x != 0.0f) return(sinf(x) / x);
-	return(1.0f);
-}
-
-#define	Lanczos3_support	(3.0f)
-
-float	Lanczos3_filter(float t)
-{
-	if (t < 0.0f) t = -t;
-	if (t < 3.0f) return(sinc(t) * sinc(t/3.0f));
-	return(0.0f);
-}
-
-
-// MITCHELL
-
-#define	Mitchell_support	(2.0f)
-
-#define	B	(1.0f / 3.0f)
-#define	C	(1.0f / 3.0f)
-
-float	Mitchell_filter(float t)
-{
-	float tt;
-
-	tt = t * t;
-	if (t < 0.0f) t = -t;
-	if (t < 1.0f) {
-		t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt))
-		   + ((-18.0f + 12.0f * B + 6.0f * C) * tt)
-		   + (6.0f - 2.0f * B));
-		return(t / 6.0f);
-	} else if(t < 2.0f) {
-		t = (((-1.0f * B - 6.0f * C) * (t * tt))
-		   + ((6.0f * B + 30.0f * C) * tt)
-		   + ((-12.0f * B - 48.0f * C) * t)
-		   + (8.0f * B + 24 * C));
-		return(t / 6.0f);
-	}
-	return(0.0f);
-}
-
-
-struct CONTRIB {
-	int	pixel;
-	float	weight;
-
-	CONTRIB()
-		: pixel(0), weight(0.f)
-	{
-	}
-
-	CONTRIB(int p, float w)
-		: pixel(p), weight(w)
-	{
-	}
-};
-
-
-};	// end anonymous namespace
-
-
-namespace image {
-
-
-enum filter_type {
-	FILTER0 = 0,
-	BOX = FILTER0,
-	TRIANGLE,
-	BELL,
-	B_SPLINE,
-	SOME_CUBIC,	// Cubic approximation of Sinc's hump (but no tails).
-	LANCZOS3,
-	MITCHELL,	// This one is alleged to be pretty nice.
-
-	FILTER_COUNT
-};
-
-struct {
-	float	(*filter_function)(float);
-	float	support;
-} filter_table[] =
-{
-	{ box_filter, box_support },
-	{ triangle_filter, triangle_support },
-	{ bell_filter, bell_support },
-	{ B_spline_filter, B_spline_support },
-	{ cubic_filter, cubic_filter_support },
-	{ Lanczos3_filter, Lanczos3_support },
-	{ Mitchell_filter, Mitchell_support },
-};
-
-
-// TODO: experiment with different filter functions.
-filter_type	default_type = TRIANGLE;
-
-
-void	resample(image::rgb* out, int out_x0, int out_y0, int out_x1, int out_y1,
-		 image::rgb* in, float in_x0, float in_y0, float in_x1, float in_y1)
-// Rescale the specified portion of the input image into the specified
-// portion of the output image.  Coordinates are *inclusive*.
-{
-	assert(out_x0 <= out_x1);
-	assert(out_y0 <= out_y1);
-	assert(out_x0 >= 0 && out_x0 < out->m_width);
-	assert(out_x1 >= 0 && out_x1 < out->m_width);
-	assert(out_y0 >= 0 && out_y0 < out->m_height);
-	assert(out_y1 >= 0 && out_y1 < out->m_height);
-
-	float	(*filter_function)(float);
-	float	support;
-
-	// Pick a filter function & support.
-	assert(default_type >= FILTER0 && default_type < FILTER_COUNT);
-	filter_function = filter_table[default_type].filter_function;
-	support = filter_table[default_type].support;
-
-
-	image::rgb*	tmp;		/* intermediate image */
-	float	xscale, yscale;		/* zoom scale factors */
-	int i, k;			/* loop variables */
-	unsigned int j;			/* loop variables */
-	int n;				/* pixel number */
-	float center; int left, right;	/* filter calculation variables */
-	float width, fscale, weight;	/* filter calculation variables */
-	Uint8*	raster;			/* a row or column of pixels */
-
-	std::vector< std::vector<CONTRIB> >	contrib;
-
-	int	out_width = out_x1 - out_x0 + 1;
-	int	out_height = out_y1 - out_y0 + 1;
-	assert(out_width > 0);
-	assert(out_height > 0);
-
-	float	in_width = in_x1 - in_x0;
-	float	in_height = in_y1 - in_y0;
-	assert(in_width > 0);
-	assert(in_height > 0);
-
-	int	in_window_w = int(ceilf(in_x1) - floorf(in_x0) + 1);
-	int	in_window_h = int(ceilf(in_y1) - floorf(in_y0) + 1);
-
-	/* create intermediate image to hold horizontal zoom */
-	tmp = image::create_rgb(out_width, in_window_h);
-	xscale = (float) (out_width - 1) / in_width;
-	yscale = (float) (out_height - 1) / in_height;
-
-	// xxxx protect against division by 0
-	if (yscale == 0) { yscale = 1.0f; }
-	if (xscale == 0) { xscale = 1.0f; }
-
-	/* pre-calculate filter contributions for a row */
-	contrib.resize(tmp->m_width);
-	if(xscale < 1.0f) {
-		width = support / xscale;
-		fscale = 1.0f / xscale;
-		for (i = 0; i < tmp->m_width; ++i) {
-			contrib[i].resize(0);
-
-			center = (float) i / xscale;
-			left = int(ceilf(center - width));
-			right = int(floorf(center + width));
-			for (k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight / fscale) / fscale;
-				n = iclamp(k, 0, in_window_w - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	} else {
-		for (i = 0; i < tmp->m_width; ++i) {
-			contrib[i].resize(0);
-			center = (float) i / xscale;
-			left = int(ceilf(center - support));
-			right = int(floorf(center + support));
-			for(k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight);
-				n = iclamp(k, 0, in_window_w - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	}
-
-	/* apply filter to zoom horizontally from src to tmp */
-	raster = (Uint8*) my_calloc(in_window_w, 3);
-	for (k = 0; k < tmp->m_height; ++k) {
-		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
-		for (i = 0; i < tmp->m_width; ++i) {
-			float	red = 0.0f;
-			float	green = 0.0f;
-			float	blue = 0.0f;
-			for(j = 0; j < contrib[i].size(); ++j) {
-				int	pixel = contrib[i][j].pixel;
-				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
-				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
-				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
-			}
-			put_pixel(tmp, i, k, red, green, blue);
-		}
-	}
-	my_cfree(raster);
-
-	contrib.resize(out_height);
-
-	if (yscale < 1.0f) {
-		width = support / yscale;
-		fscale = 1.0f / yscale;
-		for (i = 0; i < out_height; ++i) {
-			contrib[i].resize(0);
-
-			center = (float) i / yscale;
-			left = int(ceilf(center - width));
-			right = int(floorf(center + width));
-			for (k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight / fscale) / fscale;
-				n = iclamp(k, 0, tmp->m_height - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	} else {
-		for (i = 0; i < out_height; ++i) {
-			contrib[i].resize(0);
-			center = (float) i / yscale;
-			left = int(ceilf(center - support));
-			right = int(floorf(center + support));
-			for(k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight);
-				n = iclamp(k, 0, tmp->m_height - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	}
-
-	/* apply filter to zoom vertically from tmp to dst */
-	raster = (Uint8*) my_calloc(tmp->m_height, 3);
-	for (k = 0; k < tmp->m_width; ++k) {
-		get_column(raster, tmp, k);
-		for (i = 0; i < out_height; ++i) {
-			float	red = 0.0f;
-			float	green = 0.0f;
-			float	blue = 0.0f;
-			for (j = 0; j < contrib[i].size(); ++j) {
-				int	pixel = contrib[i][j].pixel;
-				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
-				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
-				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
-			}
-			put_pixel(out, k + out_x0, i + out_y0, red, green, blue);
-		}
-	}
-	my_cfree(raster);
-
-	contrib.resize(0);
-
-	delete tmp;
-}
-
-
-void	resample(image::rgba* out, int out_x0, int out_y0, int out_x1, int out_y1,
-		 image::rgba* in, float in_x0, float in_y0, float in_x1, float in_y1)
-// Rescale the specified portion of the input image into the specified
-// portion of the output image.  Coordinates are *inclusive*.
-//
-// Same as above, but with an alpha channel.
-{
-	assert(out_x0 <= out_x1);
-	assert(out_y0 <= out_y1);
-	assert(out_x0 >= 0 && out_x0 < out->m_width);
-	assert(out_x1 >= 0 && out_x1 < out->m_width);
-	assert(out_y0 >= 0 && out_y0 < out->m_height);
-	assert(out_y1 >= 0 && out_y1 < out->m_height);
-
-	float	(*filter_function)(float);
-	float	support;
-
-	// Pick a filter function & support.
-	assert(default_type >= FILTER0 && default_type < FILTER_COUNT);
-	filter_function = filter_table[default_type].filter_function;
-	support = filter_table[default_type].support;
-
-
-	image::rgba*	tmp;		/* intermediate image */
-	float	xscale, yscale;		/* zoom scale factors */
-	int i, k;			/* loop variables */
-	unsigned int j;			/* loop variables */
-	int n;				/* pixel number */
-	float center; int left, right;	/* filter calculation variables */
-	float width, fscale, weight;	/* filter calculation variables */
-	Uint8*	raster;			/* a row or column of pixels */
-
-	std::vector< std::vector<CONTRIB> >	contrib;
-
-	int	out_width = out_x1 - out_x0 + 1;
-	int	out_height = out_y1 - out_y0 + 1;
-	assert(out_width > 0);
-	assert(out_height > 0);
-
-	float	in_width = in_x1 - in_x0;
-	float	in_height = in_y1 - in_y0;
-	assert(in_width > 0);
-	assert(in_height > 0);
-
-	int	in_window_w = int(ceilf(in_x1) - floorf(in_x0) + 1);
-	int	in_window_h = int(ceilf(in_y1) - floorf(in_y0) + 1);
-
-	/* create intermediate image to hold horizontal zoom */
-	tmp = image::create_rgba(out_width, in_window_h);
-	xscale = (float) (out_width - 1) / in_width;
-	yscale = (float) (out_height - 1) / in_height;
-
-	// xxxx protect against division by 0
-	if (yscale == 0) { yscale = 1.0f; }
-	if (xscale == 0) { xscale = 1.0f; }
-
-	/* pre-calculate filter contributions for a row */
-	contrib.resize(tmp->m_width);
-	if(xscale < 1.0f) {
-		width = support / xscale;
-		fscale = 1.0f / xscale;
-		for (i = 0; i < tmp->m_width; ++i) {
-			contrib[i].resize(0);
-
-			center = (float) i / xscale;
-			left = int(ceilf(center - width));
-			right = int(floorf(center + width));
-			for (k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight / fscale) / fscale;
-				n = iclamp(k, 0, in_window_w - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	} else {
-		for (i = 0; i < tmp->m_width; ++i) {
-			contrib[i].resize(0);
-			center = (float) i / xscale;
-			left = int(ceilf(center - support));
-			right = int(floorf(center + support));
-			for(k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight);
-				n = iclamp(k, 0, in_window_w - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	}
-
-	/* apply filter to zoom horizontally from src to tmp */
-	raster = (Uint8*) my_calloc(in_window_w, 4);
-	for (k = 0; k < tmp->m_height; ++k) {
-		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
-		for (i = 0; i < tmp->m_width; ++i) {
-			float	red = 0.0f;
-			float	green = 0.0f;
-			float	blue = 0.0f;
-			float	alpha = 0.0f;
-			for(j = 0; j < contrib[i].size(); ++j) {
-				int	pixel = contrib[i][j].pixel;
-				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
-				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
-				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
-				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
-			}
-			put_pixel(tmp, i, k, red, green, blue, alpha);
-		}
-	}
-	my_cfree(raster);
-
-	contrib.resize(out_height);
-
-	if (yscale < 1.0f) {
-		width = support / yscale;
-		fscale = 1.0f / yscale;
-		for (i = 0; i < out_height; ++i) {
-			contrib[i].resize(0);
-
-			center = (float) i / yscale;
-			left = int(ceilf(center - width));
-			right = int(floorf(center + width));
-			for (k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight / fscale) / fscale;
-				n = iclamp(k, 0, tmp->m_height - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	} else {
-		for (i = 0; i < out_height; ++i) {
-			contrib[i].resize(0);
-			center = (float) i / yscale;
-			left = int(ceilf(center - support));
-			right = int(floorf(center + support));
-			for(k = left; k <= right; ++k) {
-				weight = center - (float) k;
-				weight = (*filter_function)(weight);
-				n = iclamp(k, 0, tmp->m_height - 1);
-				contrib[i].push_back(CONTRIB(n, weight));
-			}
-		}
-	}
-
-	/* apply filter to zoom vertically from tmp to dst */
-	raster = (Uint8*) my_calloc(tmp->m_height, 4);
-	for (k = 0; k < tmp->m_width; ++k) {
-		get_column(raster, tmp, k);
-		for (i = 0; i < out_height; ++i) {
-			float	red = 0.0f;
-			float	green = 0.0f;
-			float	blue = 0.0f;
-			float	alpha = 0.0f;
-			for (j = 0; j < contrib[i].size(); ++j) {
-				int	pixel = contrib[i][j].pixel;
-				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
-				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
-				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
-				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
-			}
-			put_pixel(out, k + out_x0, i + out_y0, red, green, blue, alpha);
-		}
-	}
-	my_cfree(raster);
-
-	contrib.resize(0);
-
-	delete tmp;
-}
-
-
-
-// tulrich: some interesting scaling code from Vitaly.  Looks like a
-// fast bilinear scale using fixed point.  I haven't validated this
-// myself.  Note: I would see about losing the sax & say arrays, and
-// fold that stuff directly into the pixel loops, to get rid of the
-// mallocs.
-
-void	zoom(image::rgba* src, image::rgba* dst)
-{
-  typedef struct
-  {
-    Uint8 r;
-    Uint8 g;
-    Uint8 b;
-    Uint8 a;
-  }
-  rgba;
-
-  int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2;
-  rgba *c00, *c01, *c10, *c11, *sp, *csp, *dp;
-  int sgap, dgap;
-
-  /* For interpolation: assume source dimension is one pixel */
-  /* smaller to avoid overflow on right and bottom edge.     */
-  sx = (int) (65536.0 * (float) (src->m_width - 1) / (float) dst->m_width);
-	sy = (int) (65536.0 * (float) (src->m_height - 1) / (float) dst->m_height);
-
-  /* Allocate memory for row increments */
-  sax = (int*) malloc ((dst->m_width + 1) * sizeof (Uint32));
-  say = (int*) malloc ((dst->m_height + 1) * sizeof (Uint32));
-
-  /* Precalculate row increments */
-  csx = 0;
-  csax = sax;
-  for (x = 0; x <= dst->m_width; x++)
-  {
-    *csax = csx;
-    csax++;
-    csx &= 0xffff;
-    csx += sx;
-  }
-  csy = 0;
-  csay = say;
-  for (y = 0; y <= dst->m_height; y++)
-  {
-    *csay = csy;
-    csay++;
-    csy &= 0xffff;
-    csy += sy;
-  }
-
-  /* Pointer setup */
-  sp = csp = (rgba *) src->m_data;
-  dp = (rgba *) dst->m_data;
-  sgap = src->m_pitch - src->m_width * 4;
-  dgap = dst->m_pitch - dst->m_width * 4;
-
-	/* Interpolating Zoom */
-	/* Scan destination */
-  csay = say;
-  for (y = 0; y < dst->m_height; y++)
-	{
-	  /* Setup color source pointers */
-	  c00 = csp;
-	  c01 = csp;
-	  c01++;
-	  c10 = (rgba *) ((Uint8 *) csp + src->m_pitch);
-	  c11 = c10;
-	  c11++;
-	  csax = sax;
-	  for (x = 0; x < dst->m_width; x++)
-		{
-			/* ABGR ordering */
-	    /* Interpolate colors */
-	    ex = (*csax & 0xffff);
-	    ey = (*csay & 0xffff);
-	    t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
-	    t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
-	    dp->r = (((t2 - t1) * ey) >> 16) + t1;
-	    t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
-	    t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
-	    dp->g = (((t2 - t1) * ey) >> 16) + t1;
-	    t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
-	    t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
-	    dp->b = (((t2 - t1) * ey) >> 16) + t1;
-	    t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
-	    t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
-	    dp->a = (((t2 - t1) * ey) >> 16) + t1;
-
-			/* Advance source pointers */
-      csax++;
-      int sstep = (*csax >> 16);
-      c00 += sstep;
-      c01 += sstep;
-      c10 += sstep;
-      c11 += sstep;
-      /* Advance destination pointer */
-      dp++;
-    }
-	  /* Advance source pointer */
-		csay++;
-	  csp = (rgba *) ((Uint8 *) csp + (*csay >> 16) * src->m_pitch);
-  	/* Advance destination pointers */
-	  dp = (rgba *) ((Uint8 *) dp + dgap);
-	}
-
-  /* Remove temp arrays */
-  free (sax);
-  free (say);
-}
-
-
-
-} // end namespace image
-
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
-
+// image_filters.cpp	-- Original code by Dale Schumacher, public domain 1991
+
+// See _Graphics Gems III_ "General Filtered Image Rescaling", Dale A. Schumacher
+
+// Modifications by Thatcher Ulrich <tu@tulrich.com> 2002
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// A series of image rescaling functions.  tulrich: Mostly I just
+// converted from K&R C to C-like C++, changed the interfaces a bit,
+// etc.
+
+
+#include "image.h"
+#include "utility.h"
+#include "container.h"
+#include "tu_math.h"
+#include <stdio.h>
+#include <string.h>
+
+
+namespace {
+// anonymous namespace to hold local stuff.
+
+
+inline void* my_calloc(int count, int size)
+{
+	void*	mem = (void*) new char[count * size];
+	memset(mem, 0, count * size);
+	return mem;
+}
+
+
+inline void	my_cfree(void* mem)
+{
+	delete [] (char*) mem;
+}
+
+
+void	get_row(Uint8* row, image::rgb* image, int x0, int xsize, int y)
+// Copy RGB data from the specified row into the given buffer.
+{
+	y = iclamp(y, 0, image->m_height - 1);
+	int	x1 = x0 + xsize - 1;
+	if (x1 >= image->m_width) {
+		// clip, then extend.
+		int	extra_pixels = x1 - image->m_width + 1;
+		Uint8*	p = ((Uint8*) image->m_data) + (y * image->m_pitch);
+		memcpy(row, p + x0 * 3, (3 * (image->m_width - x0)));
+		// repeat last pixel
+		p = p + (image->m_width - 1) * 3;
+		Uint8*	q = row + (image->m_width - x0) * 3;
+		while (extra_pixels > 0) {
+			*(q + 0) = *(p + 0);
+			*(q + 1) = *(p + 1);
+			*(q + 2) = *(p + 2);
+			q += 3;
+			extra_pixels--;
+		}
+	}
+	else
+	{
+		memcpy(row, ((Uint8*) image->m_data) + (y * image->m_pitch) + x0 * 3, (3 * \
xsize)); +	}
+}
+
+
+void	get_row(Uint8* row, image::rgba* image, int x0, int xsize, int y)
+// Copy RGBA data from the specified row into the given buffer.
+{
+	y = iclamp(y, 0, image->m_height - 1);
+	int	x1 = x0 + xsize - 1;
+	if (x1 >= image->m_width) {
+		// clip, then extend.
+		int	extra_pixels = x1 - image->m_width + 1;
+		Uint8*	p = ((Uint8*) image->m_data) + (y * image->m_pitch);
+		memcpy(row, p + x0 * 4, (4 * (image->m_width - x0)));
+		// repeat last pixel
+		p = p + (image->m_width - 1) * 4;
+		Uint8*	q = row + (image->m_width - x0) * 4;
+		while (extra_pixels > 0) {
+			*(q + 0) = *(p + 0);
+			*(q + 1) = *(p + 1);
+			*(q + 2) = *(p + 2);
+			*(q + 3) = *(p + 3);
+			q += 4;
+			extra_pixels--;
+		}
+	}
+	else
+	{
+		memcpy(row, ((Uint8*) image->m_data) + (y * image->m_pitch) + x0 * 4, (4 * \
xsize)); +	}
+}
+
+
+void	get_column(Uint8* column, image::rgb* image, int x)
+// Copy RGB data from the specified column into the given buffer.
+{
+	int	i, d;
+	Uint8*	p;
+
+	if ((x < 0) || (x >= image->m_width)) {
+		assert(0);
+		x = iclamp(x, 0, image->m_width - 1);
+	}
+
+	d = image->m_pitch;
+	for (i = image->m_height, p = ((Uint8*) image->m_data) + x * 3; i-- > 0; p += d) {
+		*column++ = *p;
+		*column++ = *(p + 1);
+		*column++ = *(p + 2);
+	}
+}
+
+
+void	get_column(Uint8* column, image::rgba* image, int x)
+// Copy RGBA data from the specified column into the given buffer.
+{
+	int	i, d;
+	Uint8*	p;
+
+	if ((x < 0) || (x >= image->m_width)) {
+		assert(0);
+		x = iclamp(x, 0, image->m_width - 1);
+	}
+
+	d = image->m_pitch;
+	for (i = image->m_height, p = ((Uint8*) image->m_data) + x * 4; i-- > 0; p += d) {
+		*column++ = *p;
+		*column++ = *(p + 1);
+		*column++ = *(p + 2);
+		*column++ = *(p + 3);
+	}
+}
+
+
+void	put_pixel(image::rgb* image, int x, int y, float r, float g, float b)
+// Clamp {r, g, b} to [0,255], and write pixel data to the given image
+// at (x, y).
+{
+	static image::rgb*	im = NULL;
+	static int	yy = -1;
+	static Uint8*	p = NULL;
+
+	if ((x < 0) || (x >= image->m_width) || (y < 0) || (y >= image->m_height)) {
+		assert(0);
+		return;
+	}
+	if ((im != image) || (yy != y)) {
+		im = image;
+		yy = y;
+		p = ((Uint8*) image->m_data) + (y * image->m_pitch);
+	}
+	p[x * 3 + 0] = iclamp(frnd(r), 0, 255);
+	p[x * 3 + 1] = iclamp(frnd(g), 0, 255);
+	p[x * 3 + 2] = iclamp(frnd(b), 0, 255);
+}
+
+
+void	put_pixel(image::rgba* image, int x, int y, float r, float g, float b, float a)
+// Clamp {r, g, b, a} to [0,255], and write pixel data to the given image
+// at (x, y).
+{
+	static image::rgba*	im = NULL;
+	static int	yy = -1;
+	static Uint8*	p = NULL;
+
+	if ((x < 0) || (x >= image->m_width) || (y < 0) || (y >= image->m_height)) {
+		assert(0);
+		return;
+	}
+	if ((im != image) || (yy != y)) {
+		im = image;
+		yy = y;
+		p = ((Uint8*) image->m_data) + (y * image->m_pitch);
+	}
+	p[x * 4	+ 0] = iclamp(frnd(r), 0, 255);
+	p[x * 4	+ 1] = iclamp(frnd(g), 0, 255);
+	p[x * 4	+ 2] = iclamp(frnd(b), 0, 255);
+	p[x * 4	+ 3] = iclamp(frnd(a), 0, 255);
+}
+
+
+/*
+ *	filter function definitions
+ */
+
+
+// SOME_CUBIC
+
+#define	cubic_filter_support		(1.0f)
+
+float	cubic_filter(float t)
+// Cubix approximation to the central hump of Sinc.
+{
+	/* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
+	if(t < 0.0f) t = -t;
+	if(t < 1.0f) return((2.0f * t - 3.0f) * t * t + 1.0f);
+	return(0.0f);
+}
+
+
+// BOX
+
+#define	box_support		(0.5f)
+
+float	box_filter(float t)
+{
+	if((t > -0.5) && (t <= 0.5)) return(1.0);
+	return(0.0);
+}
+
+
+// TRIANGLE
+
+#define	triangle_support	(1.0)
+
+float	triangle_filter(float t)
+{
+	if(t < 0.0f) t = -t;
+	if(t < 1.0f) return(1.0f - t);
+	return(0.0f);
+}
+
+
+// BELL
+
+#define	bell_support		(1.5)
+
+float	bell_filter(float t)
+/* box (*) box (*) box */
+{
+	if(t < 0) t = -t;
+	if(t < 0.5f) return(0.75f - (t * t));
+	if(t < 1.5f) {
+		t = (t - 1.5f);
+		return(0.5f * (t * t));
+	}
+	return(0.0f);
+}
+
+
+// B_SPLINE
+
+#define	B_spline_support	(2.0f)
+
+float	B_spline_filter(float t)
+/* box (*) box (*) box (*) box */
+{
+	float	tt;
+
+	if(t < 0.0f) t = -t;
+	if(t < 1.0f) {
+		tt = t * t;
+		return((0.5f * tt * t) - tt + (2.0f / 3.0f));
+	} else if (t < 2.0f) {
+		t = 2.0f - t;
+		return((1.0f / 6.0f) * (t * t * t));
+	}
+	return(0.0f);
+}
+
+
+// LANCZOS3
+
+float	sinc(float x)
+{
+	x *= (float) M_PI;
+	if (x != 0.0f) return(sinf(x) / x);
+	return(1.0f);
+}
+
+#define	Lanczos3_support	(3.0f)
+
+float	Lanczos3_filter(float t)
+{
+	if (t < 0.0f) t = -t;
+	if (t < 3.0f) return(sinc(t) * sinc(t/3.0f));
+	return(0.0f);
+}
+
+
+// MITCHELL
+
+#define	Mitchell_support	(2.0f)
+
+#define	B	(1.0f / 3.0f)
+#define	C	(1.0f / 3.0f)
+
+float	Mitchell_filter(float t)
+{
+	float tt;
+
+	tt = t * t;
+	if (t < 0.0f) t = -t;
+	if (t < 1.0f) {
+		t = (((12.0f - 9.0f * B - 6.0f * C) * (t * tt))
+		   + ((-18.0f + 12.0f * B + 6.0f * C) * tt)
+		   + (6.0f - 2.0f * B));
+		return(t / 6.0f);
+	} else if(t < 2.0f) {
+		t = (((-1.0f * B - 6.0f * C) * (t * tt))
+		   + ((6.0f * B + 30.0f * C) * tt)
+		   + ((-12.0f * B - 48.0f * C) * t)
+		   + (8.0f * B + 24 * C));
+		return(t / 6.0f);
+	}
+	return(0.0f);
+}
+
+
+struct CONTRIB {
+	int	pixel;
+	float	weight;
+
+	CONTRIB()
+		: pixel(0), weight(0.f)
+	{
+	}
+
+	CONTRIB(int p, float w)
+		: pixel(p), weight(w)
+	{
+	}
+};
+
+
+};	// end anonymous namespace
+
+
+namespace image {
+
+
+enum filter_type {
+	FILTER0 = 0,
+	BOX = FILTER0,
+	TRIANGLE,
+	BELL,
+	B_SPLINE,
+	SOME_CUBIC,	// Cubic approximation of Sinc's hump (but no tails).
+	LANCZOS3,
+	MITCHELL,	// This one is alleged to be pretty nice.
+
+	FILTER_COUNT
+};
+
+struct {
+	float	(*filter_function)(float);
+	float	support;
+} filter_table[] =
+{
+	{ box_filter, box_support },
+	{ triangle_filter, triangle_support },
+	{ bell_filter, bell_support },
+	{ B_spline_filter, B_spline_support },
+	{ cubic_filter, cubic_filter_support },
+	{ Lanczos3_filter, Lanczos3_support },
+	{ Mitchell_filter, Mitchell_support },
+};
+
+
+// TODO: experiment with different filter functions.
+filter_type	default_type = TRIANGLE;
+
+
+void	resample(image::rgb* out, int out_x0, int out_y0, int out_x1, int out_y1,
+		 image::rgb* in, float in_x0, float in_y0, float in_x1, float in_y1)
+// Rescale the specified portion of the input image into the specified
+// portion of the output image.  Coordinates are *inclusive*.
+{
+	assert(out_x0 <= out_x1);
+	assert(out_y0 <= out_y1);
+	assert(out_x0 >= 0 && out_x0 < out->m_width);
+	assert(out_x1 >= 0 && out_x1 < out->m_width);
+	assert(out_y0 >= 0 && out_y0 < out->m_height);
+	assert(out_y1 >= 0 && out_y1 < out->m_height);
+
+	float	(*filter_function)(float);
+	float	support;
+
+	// Pick a filter function & support.
+	assert(default_type >= FILTER0 && default_type < FILTER_COUNT);
+	filter_function = filter_table[default_type].filter_function;
+	support = filter_table[default_type].support;
+
+
+	image::rgb*	tmp;		/* intermediate image */
+	float	xscale, yscale;		/* zoom scale factors */
+	int i, k;			/* loop variables */
+	unsigned int j;			/* loop variables */
+	int n;				/* pixel number */
+	float center; int left, right;	/* filter calculation variables */
+	float width, fscale, weight;	/* filter calculation variables */
+	Uint8*	raster;			/* a row or column of pixels */
+
+	std::vector< std::vector<CONTRIB> >	contrib;
+
+	int	out_width = out_x1 - out_x0 + 1;
+	int	out_height = out_y1 - out_y0 + 1;
+	assert(out_width > 0);
+	assert(out_height > 0);
+
+	float	in_width = in_x1 - in_x0;
+	float	in_height = in_y1 - in_y0;
+	assert(in_width > 0);
+	assert(in_height > 0);
+
+	int	in_window_w = int(ceilf(in_x1) - floorf(in_x0) + 1);
+	int	in_window_h = int(ceilf(in_y1) - floorf(in_y0) + 1);
+
+	/* create intermediate image to hold horizontal zoom */
+	tmp = image::create_rgb(out_width, in_window_h);
+	xscale = (float) (out_width - 1) / in_width;
+	yscale = (float) (out_height - 1) / in_height;
+
+	// xxxx protect against division by 0
+	if (yscale == 0) { yscale = 1.0f; }
+	if (xscale == 0) { xscale = 1.0f; }
+
+	/* pre-calculate filter contributions for a row */
+	contrib.resize(tmp->m_width);
+	if(xscale < 1.0f) {
+		width = support / xscale;
+		fscale = 1.0f / xscale;
+		for (i = 0; i < tmp->m_width; ++i) {
+			contrib[i].resize(0);
+
+			center = (float) i / xscale;
+			left = int(ceilf(center - width));
+			right = int(floorf(center + width));
+			for (k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight / fscale) / fscale;
+				n = iclamp(k, 0, in_window_w - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	} else {
+		for (i = 0; i < tmp->m_width; ++i) {
+			contrib[i].resize(0);
+			center = (float) i / xscale;
+			left = int(ceilf(center - support));
+			right = int(floorf(center + support));
+			for(k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight);
+				n = iclamp(k, 0, in_window_w - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	}
+
+	/* apply filter to zoom horizontally from src to tmp */
+	raster = (Uint8*) my_calloc(in_window_w, 3);
+	for (k = 0; k < tmp->m_height; ++k) {
+		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
+		for (i = 0; i < tmp->m_width; ++i) {
+			float	red = 0.0f;
+			float	green = 0.0f;
+			float	blue = 0.0f;
+			for(j = 0; j < contrib[i].size(); ++j) {
+				int	pixel = contrib[i][j].pixel;
+				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
+				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
+				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
+			}
+			put_pixel(tmp, i, k, red, green, blue);
+		}
+	}
+	my_cfree(raster);
+
+	contrib.resize(out_height);
+
+	if (yscale < 1.0f) {
+		width = support / yscale;
+		fscale = 1.0f / yscale;
+		for (i = 0; i < out_height; ++i) {
+			contrib[i].resize(0);
+
+			center = (float) i / yscale;
+			left = int(ceilf(center - width));
+			right = int(floorf(center + width));
+			for (k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight / fscale) / fscale;
+				n = iclamp(k, 0, tmp->m_height - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	} else {
+		for (i = 0; i < out_height; ++i) {
+			contrib[i].resize(0);
+			center = (float) i / yscale;
+			left = int(ceilf(center - support));
+			right = int(floorf(center + support));
+			for(k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight);
+				n = iclamp(k, 0, tmp->m_height - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	}
+
+	/* apply filter to zoom vertically from tmp to dst */
+	raster = (Uint8*) my_calloc(tmp->m_height, 3);
+	for (k = 0; k < tmp->m_width; ++k) {
+		get_column(raster, tmp, k);
+		for (i = 0; i < out_height; ++i) {
+			float	red = 0.0f;
+			float	green = 0.0f;
+			float	blue = 0.0f;
+			for (j = 0; j < contrib[i].size(); ++j) {
+				int	pixel = contrib[i][j].pixel;
+				red	+= raster[pixel * 3 + 0] * contrib[i][j].weight;
+				green	+= raster[pixel * 3 + 1] * contrib[i][j].weight;
+				blue	+= raster[pixel * 3 + 2] * contrib[i][j].weight;
+			}
+			put_pixel(out, k + out_x0, i + out_y0, red, green, blue);
+		}
+	}
+	my_cfree(raster);
+
+	contrib.resize(0);
+
+	delete tmp;
+}
+
+
+void	resample(image::rgba* out, int out_x0, int out_y0, int out_x1, int out_y1,
+		 image::rgba* in, float in_x0, float in_y0, float in_x1, float in_y1)
+// Rescale the specified portion of the input image into the specified
+// portion of the output image.  Coordinates are *inclusive*.
+//
+// Same as above, but with an alpha channel.
+{
+	assert(out_x0 <= out_x1);
+	assert(out_y0 <= out_y1);
+	assert(out_x0 >= 0 && out_x0 < out->m_width);
+	assert(out_x1 >= 0 && out_x1 < out->m_width);
+	assert(out_y0 >= 0 && out_y0 < out->m_height);
+	assert(out_y1 >= 0 && out_y1 < out->m_height);
+
+	float	(*filter_function)(float);
+	float	support;
+
+	// Pick a filter function & support.
+	assert(default_type >= FILTER0 && default_type < FILTER_COUNT);
+	filter_function = filter_table[default_type].filter_function;
+	support = filter_table[default_type].support;
+
+
+	image::rgba*	tmp;		/* intermediate image */
+	float	xscale, yscale;		/* zoom scale factors */
+	int i, k;			/* loop variables */
+	unsigned int j;			/* loop variables */
+	int n;				/* pixel number */
+	float center; int left, right;	/* filter calculation variables */
+	float width, fscale, weight;	/* filter calculation variables */
+	Uint8*	raster;			/* a row or column of pixels */
+
+	std::vector< std::vector<CONTRIB> >	contrib;
+
+	int	out_width = out_x1 - out_x0 + 1;
+	int	out_height = out_y1 - out_y0 + 1;
+	assert(out_width > 0);
+	assert(out_height > 0);
+
+	float	in_width = in_x1 - in_x0;
+	float	in_height = in_y1 - in_y0;
+	assert(in_width > 0);
+	assert(in_height > 0);
+
+	int	in_window_w = int(ceilf(in_x1) - floorf(in_x0) + 1);
+	int	in_window_h = int(ceilf(in_y1) - floorf(in_y0) + 1);
+
+	/* create intermediate image to hold horizontal zoom */
+	tmp = image::create_rgba(out_width, in_window_h);
+	xscale = (float) (out_width - 1) / in_width;
+	yscale = (float) (out_height - 1) / in_height;
+
+	// xxxx protect against division by 0
+	if (yscale == 0) { yscale = 1.0f; }
+	if (xscale == 0) { xscale = 1.0f; }
+
+	/* pre-calculate filter contributions for a row */
+	contrib.resize(tmp->m_width);
+	if(xscale < 1.0f) {
+		width = support / xscale;
+		fscale = 1.0f / xscale;
+		for (i = 0; i < tmp->m_width; ++i) {
+			contrib[i].resize(0);
+
+			center = (float) i / xscale;
+			left = int(ceilf(center - width));
+			right = int(floorf(center + width));
+			for (k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight / fscale) / fscale;
+				n = iclamp(k, 0, in_window_w - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	} else {
+		for (i = 0; i < tmp->m_width; ++i) {
+			contrib[i].resize(0);
+			center = (float) i / xscale;
+			left = int(ceilf(center - support));
+			right = int(floorf(center + support));
+			for(k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight);
+				n = iclamp(k, 0, in_window_w - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	}
+
+	/* apply filter to zoom horizontally from src to tmp */
+	raster = (Uint8*) my_calloc(in_window_w, 4);
+	for (k = 0; k < tmp->m_height; ++k) {
+		get_row(raster, in, int(floorf(in_x0)), in_window_w, k);
+		for (i = 0; i < tmp->m_width; ++i) {
+			float	red = 0.0f;
+			float	green = 0.0f;
+			float	blue = 0.0f;
+			float	alpha = 0.0f;
+			for(j = 0; j < contrib[i].size(); ++j) {
+				int	pixel = contrib[i][j].pixel;
+				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
+				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
+				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
+				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
+			}
+			put_pixel(tmp, i, k, red, green, blue, alpha);
+		}
+	}
+	my_cfree(raster);
+
+	contrib.resize(out_height);
+
+	if (yscale < 1.0f) {
+		width = support / yscale;
+		fscale = 1.0f / yscale;
+		for (i = 0; i < out_height; ++i) {
+			contrib[i].resize(0);
+
+			center = (float) i / yscale;
+			left = int(ceilf(center - width));
+			right = int(floorf(center + width));
+			for (k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight / fscale) / fscale;
+				n = iclamp(k, 0, tmp->m_height - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	} else {
+		for (i = 0; i < out_height; ++i) {
+			contrib[i].resize(0);
+			center = (float) i / yscale;
+			left = int(ceilf(center - support));
+			right = int(floorf(center + support));
+			for(k = left; k <= right; ++k) {
+				weight = center - (float) k;
+				weight = (*filter_function)(weight);
+				n = iclamp(k, 0, tmp->m_height - 1);
+				contrib[i].push_back(CONTRIB(n, weight));
+			}
+		}
+	}
+
+	/* apply filter to zoom vertically from tmp to dst */
+	raster = (Uint8*) my_calloc(tmp->m_height, 4);
+	for (k = 0; k < tmp->m_width; ++k) {
+		get_column(raster, tmp, k);
+		for (i = 0; i < out_height; ++i) {
+			float	red = 0.0f;
+			float	green = 0.0f;
+			float	blue = 0.0f;
+			float	alpha = 0.0f;
+			for (j = 0; j < contrib[i].size(); ++j) {
+				int	pixel = contrib[i][j].pixel;
+				red	+= raster[pixel * 4 + 0] * contrib[i][j].weight;
+				green	+= raster[pixel * 4 + 1] * contrib[i][j].weight;
+				blue	+= raster[pixel * 4 + 2] * contrib[i][j].weight;
+				alpha	+= raster[pixel * 4 + 3] * contrib[i][j].weight;
+			}
+			put_pixel(out, k + out_x0, i + out_y0, red, green, blue, alpha);
+		}
+	}
+	my_cfree(raster);
+
+	contrib.resize(0);
+
+	delete tmp;
+}
+
+
+
+// tulrich: some interesting scaling code from Vitaly.  Looks like a
+// fast bilinear scale using fixed point.  I haven't validated this
+// myself.  Note: I would see about losing the sax & say arrays, and
+// fold that stuff directly into the pixel loops, to get rid of the
+// mallocs.
+
+void	zoom(image::rgba* src, image::rgba* dst)
+{
+  typedef struct
+  {
+    Uint8 r;
+    Uint8 g;
+    Uint8 b;
+    Uint8 a;
+  }
+  rgba;
+
+  int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2;
+  rgba *c00, *c01, *c10, *c11, *sp, *csp, *dp;
+  int sgap, dgap;
+
+  /* For interpolation: assume source dimension is one pixel */
+  /* smaller to avoid overflow on right and bottom edge.     */
+  sx = (int) (65536.0 * (float) (src->m_width - 1) / (float) dst->m_width);
+	sy = (int) (65536.0 * (float) (src->m_height - 1) / (float) dst->m_height);
+
+  /* Allocate memory for row increments */
+  sax = (int*) malloc ((dst->m_width + 1) * sizeof (Uint32));
+  say = (int*) malloc ((dst->m_height + 1) * sizeof (Uint32));
+
+  /* Precalculate row increments */
+  csx = 0;
+  csax = sax;
+  for (x = 0; x <= dst->m_width; x++)
+  {
+    *csax = csx;
+    csax++;
+    csx &= 0xffff;
+    csx += sx;
+  }
+  csy = 0;
+  csay = say;
+  for (y = 0; y <= dst->m_height; y++)
+  {
+    *csay = csy;
+    csay++;
+    csy &= 0xffff;
+    csy += sy;
+  }
+
+  /* Pointer setup */
+  sp = csp = (rgba *) src->m_data;
+  dp = (rgba *) dst->m_data;
+  sgap = src->m_pitch - src->m_width * 4;
+  dgap = dst->m_pitch - dst->m_width * 4;
+
+	/* Interpolating Zoom */
+	/* Scan destination */
+  csay = say;
+  for (y = 0; y < dst->m_height; y++)
+	{
+	  /* Setup color source pointers */
+	  c00 = csp;
+	  c01 = csp;
+	  c01++;
+	  c10 = (rgba *) ((Uint8 *) csp + src->m_pitch);
+	  c11 = c10;
+	  c11++;
+	  csax = sax;
+	  for (x = 0; x < dst->m_width; x++)
+		{
+			/* ABGR ordering */
+	    /* Interpolate colors */
+	    ex = (*csax & 0xffff);
+	    ey = (*csay & 0xffff);
+	    t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
+	    t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
+	    dp->r = (((t2 - t1) * ey) >> 16) + t1;
+	    t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
+	    t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
+	    dp->g = (((t2 - t1) * ey) >> 16) + t1;
+	    t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
+	    t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
+	    dp->b = (((t2 - t1) * ey) >> 16) + t1;
+	    t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
+	    t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
+	    dp->a = (((t2 - t1) * ey) >> 16) + t1;
+
+			/* Advance source pointers */
+      csax++;
+      int sstep = (*csax >> 16);
+      c00 += sstep;
+      c01 += sstep;
+      c10 += sstep;
+      c11 += sstep;
+      /* Advance destination pointer */
+      dp++;
+    }
+	  /* Advance source pointer */
+		csay++;
+	  csp = (rgba *) ((Uint8 *) csp + (*csay >> 16) * src->m_pitch);
+  	/* Advance destination pointers */
+	  dp = (rgba *) ((Uint8 *) dp + dgap);
+	}
+
+  /* Remove temp arrays */
+  free (sax);
+  free (say);
+}
+
+
+
+} // end namespace image
+
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
+
Index: gnash/libbase/jpeg.cpp
diff -u gnash/libbase/jpeg.cpp:1.3 gnash/libbase/jpeg.cpp:1.4
--- gnash/libbase/jpeg.cpp:1.3	Wed Feb 15 03:07:22 2006
+++ gnash/libbase/jpeg.cpp	Sun Feb 26 15:49:30 2006
@@ -1,543 +1,543 @@
-// jpeg.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2002
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Wrapper for jpeg file operations.  The actual work is done by the
-// IJG jpeg lib.
-
-
-#include "utility.h"
-#include "jpeg.h"
-#include "tu_file.h"
-#include <stdio.h>
-
-#if TU_CONFIG_LINK_TO_JPEGLIB
-
-extern "C" {
-#include <jpeglib.h>
-}
-
-
-namespace jpeg
-{
-	// jpeglib data source constructors, for using tu_file* instead
-	// of stdio for jpeg IO.
-	void	setup_rw_source(jpeg_decompress_struct* cinfo, tu_file* instream);
-	void	setup_rw_dest(jpeg_compress_struct* cinfo, tu_file* outstream);
-
-
-	// Helper object for reading jpeg image data.  Basically a thin
-	static const int	IO_BUF_SIZE = 4096;
-
-	// A jpeglib source manager that reads from a tu_file.  Paraphrased
-	// from IJG jpeglib jdatasrc.c.
-	struct rw_source
-	{
-		struct jpeg_source_mgr	m_pub;		/* public fields */
-
-		tu_file*	m_in_stream;		/* source stream */
-		bool	m_start_of_file;		/* have we gotten any data yet? */
-		JOCTET	m_buffer[IO_BUF_SIZE];	/* start of buffer */
-
-		rw_source(tu_file* in)
-			:
-			m_in_stream(in),
-			m_start_of_file(true)
-		// Constructor.  The caller is responsible for closing the input stream
-		// after it's done using us.
-		{
-			// fill in function pointers...
-			m_pub.init_source = init_source;
-			m_pub.fill_input_buffer = fill_input_buffer;
-			m_pub.skip_input_data = skip_input_data;
-			m_pub.resync_to_restart = jpeg_resync_to_restart;	// use default method
-			m_pub.term_source = term_source;
-			m_pub.bytes_in_buffer = 0;
-			m_pub.next_input_byte = NULL;
-		}
-
-		static void init_source(j_decompress_ptr cinfo)
-		{
-			rw_source*	src = (rw_source*) cinfo->src;
-			src->m_start_of_file = true;
-		}
-
-		static boolean	fill_input_buffer(j_decompress_ptr cinfo)
-		// Read data into our input buffer.  Client calls this
-		// when it needs more data from the file.
-		{
-			rw_source*	src = (rw_source*) cinfo->src;
-
-			size_t	bytes_read = src->m_in_stream->read_bytes(src->m_buffer, IO_BUF_SIZE);
-
-			if (bytes_read <= 0) {
-				// Is the file completely empty?
-				if (src->m_start_of_file) {
-					// Treat this as a fatal error.
-					throw "empty jpeg source stream.";
-				}
-				// warn("jpeg end-of-stream");
-
-				// Insert a fake EOI marker.
-				src->m_buffer[0] = (JOCTET) 0xFF;
-				src->m_buffer[1] = (JOCTET) JPEG_EOI;
-				bytes_read = 2;
-			}
-
-			// Hack to work around SWF bug: sometimes data
-			// starts with FFD9FFD8, when it should be
-			// FFD8FFD9!
-			if (src->m_start_of_file && bytes_read >= 4)
-			{
-				if (src->m_buffer[0] == 0xFF
-				    && src->m_buffer[1] == 0xD9 
-				    && src->m_buffer[2] == 0xFF
-				    && src->m_buffer[3] == 0xD8)
-				{
-					src->m_buffer[1] = 0xD8;
-					src->m_buffer[3] = 0xD9;
-				}
-			}
-
-			// Expose buffer state to clients.
-			src->m_pub.next_input_byte = src->m_buffer;
-			src->m_pub.bytes_in_buffer = bytes_read;
-			src->m_start_of_file = false;
-
-			return TRUE;
-		}
-
-		static void	skip_input_data(j_decompress_ptr cinfo, long num_bytes)
-		// Called by client when it wants to advance past some
-		// uninteresting data.
-		{
-			rw_source*	src = (rw_source*) cinfo->src;
-
-			// According to jpeg docs, large skips are
-			// infrequent.  So let's just do it the simple
-			// way.
-			if (num_bytes > 0) {
-				while (num_bytes > (long) src->m_pub.bytes_in_buffer) {
-					num_bytes -= (long) src->m_pub.bytes_in_buffer;
-					fill_input_buffer(cinfo);
-				}
-				// Handle remainder.
-				src->m_pub.next_input_byte += (size_t) num_bytes;
-				src->m_pub.bytes_in_buffer -= (size_t) num_bytes;
-			}
-		}
-
-		static void term_source(j_decompress_ptr cinfo)
-		// Terminate the source.  Make sure we get deleted.
-		{
-			/*rw_source*	src = (rw_source*) cinfo->src;
-			assert(src);
-
-			// @@ it's kind of bogus to be deleting here
-			// -- term_source happens at the end of
-			// reading an image, but we're probably going
-			// to want to init a source and use it to read
-			// many images, without reallocating our
-			// buffer.
-			delete src;
-			cinfo->src = NULL;*/
-		}
-
-
-		void	discard_partial_buffer()
-		{
-			// Discard existing bytes in our buffer.
-			m_pub.bytes_in_buffer = 0;
-			m_pub.next_input_byte = NULL;
-		}
-	};
-
-	
-	void	setup_rw_source(jpeg_decompress_struct* cinfo, tu_file* instream)
-	// Set up the given decompress object to read from the given
-	// stream.
-	{
-		// assert(cinfo->src == NULL);
-		cinfo->src = (jpeg_source_mgr*) (new rw_source(instream));
-	}
-
-
-	// A jpeglib destination manager that writes to a tu_file.
-	// Paraphrased from IJG jpeglib jdatadst.c.
-	struct rw_dest
-	{
-		struct jpeg_destination_mgr	m_pub;	/* public fields */
-
-		tu_file*	m_out_stream;		/* source stream */
-		JOCTET	m_buffer[IO_BUF_SIZE];	/* start of buffer */
-
-		rw_dest(tu_file* out)
-			:
-			m_out_stream(out)
-		// Constructor.  The caller is responsible for closing
-		// the output stream after it's done using us.
-		{
-			// fill in function pointers...
-			m_pub.init_destination = init_destination;
-			m_pub.empty_output_buffer = empty_output_buffer;
-			m_pub.term_destination = term_destination;
-
-			m_pub.next_output_byte = m_buffer;
-			m_pub.free_in_buffer = IO_BUF_SIZE;
-		}
-
-		static void init_destination(j_compress_ptr cinfo)
-		{
-			rw_dest*	dest = (rw_dest*) cinfo->dest;
-			assert(dest);
-
-			dest->m_pub.next_output_byte = dest->m_buffer;
-			dest->m_pub.free_in_buffer = IO_BUF_SIZE;
-		}
-
-		static boolean	empty_output_buffer(j_compress_ptr cinfo)
-		// Write the output buffer into the stream.
-		{
-			rw_dest*	dest = (rw_dest*) cinfo->dest;
-			assert(dest);
-
-			if (dest->m_out_stream->write_bytes(dest->m_buffer, IO_BUF_SIZE) != IO_BUF_SIZE)
-			{
-				// Error.
-				// @@ bah, exceptions suck.  TODO consider alternatives.
-				throw "jpeg::rw_dest couldn't write data.";
-			}
-
-			dest->m_pub.next_output_byte = dest->m_buffer;
-			dest->m_pub.free_in_buffer = IO_BUF_SIZE;
-
-			return TRUE;
-		}
-
-		static void term_destination(j_compress_ptr cinfo)
-		// Terminate the destination.  Flush any leftover
-		// data, and make sure we get deleted.
-		{
-			rw_dest*	dest = (rw_dest*) cinfo->dest;
-			assert(dest);
-
-			// Write any remaining data.
-			int	datacount = IO_BUF_SIZE - dest->m_pub.free_in_buffer;
-			if (datacount > 0) {
-				if (dest->m_out_stream->write_bytes(dest->m_buffer, datacount) != datacount)
-				{
-					// Error.
-					throw "jpeg::rw_dest::term_destination couldn't write data.";
-				}
-			}
-
-			// Clean ourselves up.
-			delete dest;
-			cinfo->dest = NULL;
-		}
-	};
-
-
-	void	setup_rw_dest(j_compress_ptr cinfo, tu_file* outstream)
-	// Set up the given compress object to write to the given
-	// output stream.
-	{
-		cinfo->dest = (jpeg_destination_mgr*) (new rw_dest(outstream));
-	}
-
-
-	//
-	// Error handler
-	//
-
-
-	void	jpeg_error_exit(j_common_ptr cinfo)
-	// Called when jpeglib has a fatal error.
-	{
-		assert(0);
-		(*cinfo->err->output_message) (cinfo);
-		tu_error_exit(1, "internal error in jpeglib");
-	}
-
-
-	static void	setup_jpeg_err(jpeg_error_mgr* jerr)
-	// Set up some error handlers for the jpeg lib.
-	{
-		// Set up defaults.
-		jpeg_std_error(jerr);
-
-		jerr->error_exit = jpeg_error_exit;
-	}
-
-
-	//
-	// wrappers
-	//
-
-
-	struct input_impl : public input
-	// Bascially this is a thin wrapper around jpeg_decompress
-	// object.
-	{
-		// State needed for input.
-		struct jpeg_decompress_struct	m_cinfo;
-		struct jpeg_error_mgr	m_jerr;
-
-		bool	m_compressor_opened;
-
-
-		enum SWF_DEFINE_BITS_JPEG2 { SWF_JPEG2 };
-		enum SWF_DEFINE_BITS_JPEG2_HEADER_ONLY { SWF_JPEG2_HEADER_ONLY };
-
-		input_impl(tu_file* in)
-			:
-			m_compressor_opened(false)
-		// Constructor.  Read the header data from in, and
-		// prepare to read data.
-		{
-			setup_jpeg_err(&m_jerr);
-			m_cinfo.err = &m_jerr;
-
-			// Initialize decompression object.
-			jpeg_create_decompress(&m_cinfo);
-
-			setup_rw_source(&m_cinfo, in);
-
-			start_image();
-		}
-
-
-		input_impl(SWF_DEFINE_BITS_JPEG2_HEADER_ONLY e, tu_file* in)
-			:
-			m_compressor_opened(false)
-		// The SWF file format stores JPEG images with the
-		// encoding tables separate from the image data.  This
-		// constructor reads the encoding table only and keeps
-		// them in this object.  You need to call
-		// start_image() and finish_image() around any calls
-		// to get_width/height/components and read_scanline.
-		{
-			setup_jpeg_err(&m_jerr);
-			m_cinfo.err = &m_jerr;
-
-			// Initialize decompression object.
-			jpeg_create_decompress(&m_cinfo);
-
-			setup_rw_source(&m_cinfo, in);
-
-			// Read the encoding tables.
-			jpeg_read_header(&m_cinfo, FALSE);
-
-			// Don't start reading any image data!
-			// App does that manually using start_image.
-		}
-
-		~input_impl()
-		// Destructor.  Clean up our jpeg reader state.
-		{
-			finish_image();
-
-			rw_source* src = (rw_source*) m_cinfo.src;
-			delete src;
-			m_cinfo.src = NULL;
-
-
-			jpeg_destroy_decompress(&m_cinfo);
-		}
-
-
-		void	discard_partial_buffer()
-		// Discard any data sitting in our input buffer.  Use
-		// this before/after reading headers or partial image
-		// data, to avoid screwing up future reads.
-		{
-			rw_source* src = (rw_source*) m_cinfo.src;
-
-			// We only have to discard the input buffer after reading the tables.
-			if (src)
-			{
-				src->discard_partial_buffer();
-			}
-		}
-
-
-		void	start_image()
-		// This is something you can do with "abbreviated"
-		// streams; i.e. if you constructed this inputter
-		// using (SWF_JPEG2_HEADER_ONLY) to just load the
-		// tables, or if you called finish_image() and want to
-		// load another image using the existing tables.
-		{
-			assert(m_compressor_opened == false);
-
+// jpeg.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2002
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Wrapper for jpeg file operations.  The actual work is done by the
+// IJG jpeg lib.
+
+
+#include "utility.h"
+#include "jpeg.h"
+#include "tu_file.h"
+#include <stdio.h>
+
+#if TU_CONFIG_LINK_TO_JPEGLIB
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+
+namespace jpeg
+{
+	// jpeglib data source constructors, for using tu_file* instead
+	// of stdio for jpeg IO.
+	void	setup_rw_source(jpeg_decompress_struct* cinfo, tu_file* instream);
+	void	setup_rw_dest(jpeg_compress_struct* cinfo, tu_file* outstream);
+
+
+	// Helper object for reading jpeg image data.  Basically a thin
+	static const int	IO_BUF_SIZE = 4096;
+
+	// A jpeglib source manager that reads from a tu_file.  Paraphrased
+	// from IJG jpeglib jdatasrc.c.
+	struct rw_source
+	{
+		struct jpeg_source_mgr	m_pub;		/* public fields */
+
+		tu_file*	m_in_stream;		/* source stream */
+		bool	m_start_of_file;		/* have we gotten any data yet? */
+		JOCTET	m_buffer[IO_BUF_SIZE];	/* start of buffer */
+
+		rw_source(tu_file* in)
+			:
+			m_in_stream(in),
+			m_start_of_file(true)
+		// Constructor.  The caller is responsible for closing the input stream
+		// after it's done using us.
+		{
+			// fill in function pointers...
+			m_pub.init_source = init_source;
+			m_pub.fill_input_buffer = fill_input_buffer;
+			m_pub.skip_input_data = skip_input_data;
+			m_pub.resync_to_restart = jpeg_resync_to_restart;	// use default method
+			m_pub.term_source = term_source;
+			m_pub.bytes_in_buffer = 0;
+			m_pub.next_input_byte = NULL;
+		}
+
+		static void init_source(j_decompress_ptr cinfo)
+		{
+			rw_source*	src = (rw_source*) cinfo->src;
+			src->m_start_of_file = true;
+		}
+
+		static boolean	fill_input_buffer(j_decompress_ptr cinfo)
+		// Read data into our input buffer.  Client calls this
+		// when it needs more data from the file.
+		{
+			rw_source*	src = (rw_source*) cinfo->src;
+
+			size_t	bytes_read = src->m_in_stream->read_bytes(src->m_buffer, IO_BUF_SIZE);
+
+			if (bytes_read <= 0) {
+				// Is the file completely empty?
+				if (src->m_start_of_file) {
+					// Treat this as a fatal error.
+					throw "empty jpeg source stream.";
+				}
+				// warn("jpeg end-of-stream");
+
+				// Insert a fake EOI marker.
+				src->m_buffer[0] = (JOCTET) 0xFF;
+				src->m_buffer[1] = (JOCTET) JPEG_EOI;
+				bytes_read = 2;
+			}
+
+			// Hack to work around SWF bug: sometimes data
+			// starts with FFD9FFD8, when it should be
+			// FFD8FFD9!
+			if (src->m_start_of_file && bytes_read >= 4)
+			{
+				if (src->m_buffer[0] == 0xFF
+				    && src->m_buffer[1] == 0xD9 
+				    && src->m_buffer[2] == 0xFF
+				    && src->m_buffer[3] == 0xD8)
+				{
+					src->m_buffer[1] = 0xD8;
+					src->m_buffer[3] = 0xD9;
+				}
+			}
+
+			// Expose buffer state to clients.
+			src->m_pub.next_input_byte = src->m_buffer;
+			src->m_pub.bytes_in_buffer = bytes_read;
+			src->m_start_of_file = false;
+
+			return TRUE;
+		}
+
+		static void	skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+		// Called by client when it wants to advance past some
+		// uninteresting data.
+		{
+			rw_source*	src = (rw_source*) cinfo->src;
+
+			// According to jpeg docs, large skips are
+			// infrequent.  So let's just do it the simple
+			// way.
+			if (num_bytes > 0) {
+				while (num_bytes > (long) src->m_pub.bytes_in_buffer) {
+					num_bytes -= (long) src->m_pub.bytes_in_buffer;
+					fill_input_buffer(cinfo);
+				}
+				// Handle remainder.
+				src->m_pub.next_input_byte += (size_t) num_bytes;
+				src->m_pub.bytes_in_buffer -= (size_t) num_bytes;
+			}
+		}
+
+		static void term_source(j_decompress_ptr cinfo)
+		// Terminate the source.  Make sure we get deleted.
+		{
+			/*rw_source*	src = (rw_source*) cinfo->src;
+			assert(src);
+
+			// @@ it's kind of bogus to be deleting here
+			// -- term_source happens at the end of
+			// reading an image, but we're probably going
+			// to want to init a source and use it to read
+			// many images, without reallocating our
+			// buffer.
+			delete src;
+			cinfo->src = NULL;*/
+		}
+
+
+		void	discard_partial_buffer()
+		{
+			// Discard existing bytes in our buffer.
+			m_pub.bytes_in_buffer = 0;
+			m_pub.next_input_byte = NULL;
+		}
+	};
+
+	
+	void	setup_rw_source(jpeg_decompress_struct* cinfo, tu_file* instream)
+	// Set up the given decompress object to read from the given
+	// stream.
+	{
+		// assert(cinfo->src == NULL);
+		cinfo->src = (jpeg_source_mgr*) (new rw_source(instream));
+	}
+
+
+	// A jpeglib destination manager that writes to a tu_file.
+	// Paraphrased from IJG jpeglib jdatadst.c.
+	struct rw_dest
+	{
+		struct jpeg_destination_mgr	m_pub;	/* public fields */
+
+		tu_file*	m_out_stream;		/* source stream */
+		JOCTET	m_buffer[IO_BUF_SIZE];	/* start of buffer */
+
+		rw_dest(tu_file* out)
+			:
+			m_out_stream(out)
+		// Constructor.  The caller is responsible for closing
+		// the output stream after it's done using us.
+		{
+			// fill in function pointers...
+			m_pub.init_destination = init_destination;
+			m_pub.empty_output_buffer = empty_output_buffer;
+			m_pub.term_destination = term_destination;
+
+			m_pub.next_output_byte = m_buffer;
+			m_pub.free_in_buffer = IO_BUF_SIZE;
+		}
+
+		static void init_destination(j_compress_ptr cinfo)
+		{
+			rw_dest*	dest = (rw_dest*) cinfo->dest;
+			assert(dest);
+
+			dest->m_pub.next_output_byte = dest->m_buffer;
+			dest->m_pub.free_in_buffer = IO_BUF_SIZE;
+		}
+
+		static boolean	empty_output_buffer(j_compress_ptr cinfo)
+		// Write the output buffer into the stream.
+		{
+			rw_dest*	dest = (rw_dest*) cinfo->dest;
+			assert(dest);
+
+			if (dest->m_out_stream->write_bytes(dest->m_buffer, IO_BUF_SIZE) != IO_BUF_SIZE)
+			{
+				// Error.
+				// @@ bah, exceptions suck.  TODO consider alternatives.
+				throw "jpeg::rw_dest couldn't write data.";
+			}
+
+			dest->m_pub.next_output_byte = dest->m_buffer;
+			dest->m_pub.free_in_buffer = IO_BUF_SIZE;
+
+			return TRUE;
+		}
+
+		static void term_destination(j_compress_ptr cinfo)
+		// Terminate the destination.  Flush any leftover
+		// data, and make sure we get deleted.
+		{
+			rw_dest*	dest = (rw_dest*) cinfo->dest;
+			assert(dest);
+
+			// Write any remaining data.
+			int	datacount = IO_BUF_SIZE - dest->m_pub.free_in_buffer;
+			if (datacount > 0) {
+				if (dest->m_out_stream->write_bytes(dest->m_buffer, datacount) != datacount)
+				{
+					// Error.
+					throw "jpeg::rw_dest::term_destination couldn't write data.";
+				}
+			}
+
+			// Clean ourselves up.
+			delete dest;
+			cinfo->dest = NULL;
+		}
+	};
+
+
+	void	setup_rw_dest(j_compress_ptr cinfo, tu_file* outstream)
+	// Set up the given compress object to write to the given
+	// output stream.
+	{
+		cinfo->dest = (jpeg_destination_mgr*) (new rw_dest(outstream));
+	}
+
+
+	//
+	// Error handler
+	//
+
+
+	void	jpeg_error_exit(j_common_ptr cinfo)
+	// Called when jpeglib has a fatal error.
+	{
+		assert(0);
+		(*cinfo->err->output_message) (cinfo);
+		tu_error_exit(1, "internal error in jpeglib");
+	}
+
+
+	static void	setup_jpeg_err(jpeg_error_mgr* jerr)
+	// Set up some error handlers for the jpeg lib.
+	{
+		// Set up defaults.
+		jpeg_std_error(jerr);
+
+		jerr->error_exit = jpeg_error_exit;
+	}
+
+
+	//
+	// wrappers
+	//
+
+
+	struct input_impl : public input
+	// Bascially this is a thin wrapper around jpeg_decompress
+	// object.
+	{
+		// State needed for input.
+		struct jpeg_decompress_struct	m_cinfo;
+		struct jpeg_error_mgr	m_jerr;
+
+		bool	m_compressor_opened;
+
+
+		enum SWF_DEFINE_BITS_JPEG2 { SWF_JPEG2 };
+		enum SWF_DEFINE_BITS_JPEG2_HEADER_ONLY { SWF_JPEG2_HEADER_ONLY };
+
+		input_impl(tu_file* in)
+			:
+			m_compressor_opened(false)
+		// Constructor.  Read the header data from in, and
+		// prepare to read data.
+		{
+			setup_jpeg_err(&m_jerr);
+			m_cinfo.err = &m_jerr;
+
+			// Initialize decompression object.
+			jpeg_create_decompress(&m_cinfo);
+
+			setup_rw_source(&m_cinfo, in);
+
+			start_image();
+		}
+
+
+		input_impl(SWF_DEFINE_BITS_JPEG2_HEADER_ONLY e, tu_file* in)
+			:
+			m_compressor_opened(false)
+		// The SWF file format stores JPEG images with the
+		// encoding tables separate from the image data.  This
+		// constructor reads the encoding table only and keeps
+		// them in this object.  You need to call
+		// start_image() and finish_image() around any calls
+		// to get_width/height/components and read_scanline.
+		{
+			setup_jpeg_err(&m_jerr);
+			m_cinfo.err = &m_jerr;
+
+			// Initialize decompression object.
+			jpeg_create_decompress(&m_cinfo);
+
+			setup_rw_source(&m_cinfo, in);
+
+			// Read the encoding tables.
+			jpeg_read_header(&m_cinfo, FALSE);
+
+			// Don't start reading any image data!
+			// App does that manually using start_image.
+		}
+
+		~input_impl()
+		// Destructor.  Clean up our jpeg reader state.
+		{
+			finish_image();
+
+			rw_source* src = (rw_source*) m_cinfo.src;
+			delete src;
+			m_cinfo.src = NULL;
+
+
+			jpeg_destroy_decompress(&m_cinfo);
+		}
+
+
+		void	discard_partial_buffer()
+		// Discard any data sitting in our input buffer.  Use
+		// this before/after reading headers or partial image
+		// data, to avoid screwing up future reads.
+		{
+			rw_source* src = (rw_source*) m_cinfo.src;
+
+			// We only have to discard the input buffer after reading the tables.
+			if (src)
+			{
+				src->discard_partial_buffer();
+			}
+		}
+
+
+		void	start_image()
+		// This is something you can do with "abbreviated"
+		// streams; i.e. if you constructed this inputter
+		// using (SWF_JPEG2_HEADER_ONLY) to just load the
+		// tables, or if you called finish_image() and want to
+		// load another image using the existing tables.
+		{
+			assert(m_compressor_opened == false);
+
 			// Now, read the image header.
 			jpeg_read_header(&m_cinfo, TRUE);
-
-			jpeg_start_decompress(&m_cinfo);
-			m_compressor_opened = true;
-		}
-
-		void	finish_image()
-		{
-			if (m_compressor_opened)
-			{
-				jpeg_finish_decompress(&m_cinfo);
-				m_compressor_opened = false;
-			}
-		}
-
-		int	get_height() const
-		// Return the height of the image.  Take the data from our m_cinfo struct.
-		{
-			assert(m_compressor_opened);
-			return m_cinfo.output_height;
-		}
-
-		int	get_width() const
-		// Return the width of the image.  Take the data from our m_cinfo struct.
-		{
-			assert(m_compressor_opened);
-			return m_cinfo.output_width;
-		}
-
-		int	get_components() const
-		// Return number of components (i.e. == 3 for RGB
-		// data).  The size of the data for a scanline is
-		// get_width() * get_components().
-		{
-			assert(m_compressor_opened);
-			return m_cinfo.output_components;
-		}
-
-
-		void	read_scanline(unsigned char* rgb_data)
-		// Read a scanline's worth of image data into the
-		// given buffer.  The amount of data read is
-		// get_width() * get_components().
-		{
-			assert(m_compressor_opened);
-			assert(m_cinfo.output_scanline < m_cinfo.output_height);
-			int	lines_read = jpeg_read_scanlines(&m_cinfo, &rgb_data, 1);
-			assert(lines_read == 1);
-			lines_read = lines_read;	// avoid warning in NDEBUG
-		}
-	};
-
-
-	/*static*/ input*	input::create(tu_file* in)
-	// Create and return a jpeg-input object that will read from the
-	// given input stream.
-	{
-		return new input_impl(in);
-	}
-
-	/*static*/ input*	input::create_swf_jpeg2_header_only(tu_file* in)
-	// Read SWF JPEG2-style header.  App needs to call
-	// start_image() before loading any image data.  Multiple
-	// images can be loaded by bracketing within
-	// start_image()/finish_image() pairs.
-	{
-		return new input_impl(input_impl::SWF_JPEG2_HEADER_ONLY, in);
-	}
-
-
-	// Default destructor.
-	input::~input() {}
-
-
-	struct output_impl : public output
-	// Basically this is a thin wrapper around jpeg_compress
-	// object.
-	{
-		// State needed for output.
-		struct jpeg_compress_struct	m_cinfo;
-		struct jpeg_error_mgr m_jerr;
-
-		output_impl(tu_file* out, int width, int height, int quality)
-		// Constructor.  Read the header data from in, and
-		// prepare to read data.
-		{
-			m_cinfo.err = jpeg_std_error(&m_jerr);
-
-			// Initialize decompression object.
-			jpeg_create_compress(&m_cinfo);
-
-			setup_rw_dest(&m_cinfo, out);
-			m_cinfo.image_width = width;
-			m_cinfo.image_height = height;
-			m_cinfo.input_components = 3;
-			m_cinfo.in_color_space = JCS_RGB;
-			jpeg_set_defaults(&m_cinfo);
-			jpeg_set_quality(&m_cinfo, quality, TRUE);
-
-			jpeg_start_compress(&m_cinfo, TRUE);
-		}
-
-
-		~output_impl()
-		// Destructor.  Clean up our jpeg reader state.
-		{
-			jpeg_finish_compress(&m_cinfo);
-/*
-			rw_dest* src = (rw_source*) m_cinfo.dest;
-			delete dest;
-			m_cinfo.dest = NULL;
-*/
-			jpeg_destroy_compress(&m_cinfo);
-		}
-
-
-		void	write_scanline(unsigned char* rgb_data)
-		// Write out a single scanline.
-		{
-			jpeg_write_scanlines(&m_cinfo, &rgb_data, 1);
-		}
-	};
-
-
-	/*static*/ output*	output::create(tu_file* in, int width, int height, int quality)
-	// Create and return a jpeg-input object that will read from the
-	// given input stream.
-	{
-		return new output_impl(in, width, height, quality);
-	}
-
-
-	// Default constructor.
-	output::~output() {}
-}
-
-
-#else // not TU_CONFIG_LINK_TO_JPEGLIB
-
-
-namespace jpeg
-{
-	/*static*/ input* input::create(tu_file* in)
-	{
-		return NULL;
-	}
-
-	/*static*/ input* input::create_swf_jpeg2_header_only(tu_file* in)
-	{
-		return NULL;
-	}
-
-	/*static*/ output* output::create(tu_file* out, int width, int height, int quality)
-	{
-		return NULL;
-	}
-
-}
-
-
-#endif // not TU_CONFIG_LINK_TO_JPEGLIB
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+
+			jpeg_start_decompress(&m_cinfo);
+			m_compressor_opened = true;
+		}
+
+		void	finish_image()
+		{
+			if (m_compressor_opened)
+			{
+				jpeg_finish_decompress(&m_cinfo);
+				m_compressor_opened = false;
+			}
+		}
+
+		int	get_height() const
+		// Return the height of the image.  Take the data from our m_cinfo struct.
+		{
+			assert(m_compressor_opened);
+			return m_cinfo.output_height;
+		}
+
+		int	get_width() const
+		// Return the width of the image.  Take the data from our m_cinfo struct.
+		{
+			assert(m_compressor_opened);
+			return m_cinfo.output_width;
+		}
+
+		int	get_components() const
+		// Return number of components (i.e. == 3 for RGB
+		// data).  The size of the data for a scanline is
+		// get_width() * get_components().
+		{
+			assert(m_compressor_opened);
+			return m_cinfo.output_components;
+		}
+
+
+		void	read_scanline(unsigned char* rgb_data)
+		// Read a scanline's worth of image data into the
+		// given buffer.  The amount of data read is
+		// get_width() * get_components().
+		{
+			assert(m_compressor_opened);
+			assert(m_cinfo.output_scanline < m_cinfo.output_height);
+			int	lines_read = jpeg_read_scanlines(&m_cinfo, &rgb_data, 1);
+			assert(lines_read == 1);
+			lines_read = lines_read;	// avoid warning in NDEBUG
+		}
+	};
+
+
+	/*static*/ input*	input::create(tu_file* in)
+	// Create and return a jpeg-input object that will read from the
+	// given input stream.
+	{
+		return new input_impl(in);
+	}
+
+	/*static*/ input*	input::create_swf_jpeg2_header_only(tu_file* in)
+	// Read SWF JPEG2-style header.  App needs to call
+	// start_image() before loading any image data.  Multiple
+	// images can be loaded by bracketing within
+	// start_image()/finish_image() pairs.
+	{
+		return new input_impl(input_impl::SWF_JPEG2_HEADER_ONLY, in);
+	}
+
+
+	// Default destructor.
+	input::~input() {}
+
+
+	struct output_impl : public output
+	// Basically this is a thin wrapper around jpeg_compress
+	// object.
+	{
+		// State needed for output.
+		struct jpeg_compress_struct	m_cinfo;
+		struct jpeg_error_mgr m_jerr;
+
+		output_impl(tu_file* out, int width, int height, int quality)
+		// Constructor.  Read the header data from in, and
+		// prepare to read data.
+		{
+			m_cinfo.err = jpeg_std_error(&m_jerr);
+
+			// Initialize decompression object.
+			jpeg_create_compress(&m_cinfo);
+
+			setup_rw_dest(&m_cinfo, out);
+			m_cinfo.image_width = width;
+			m_cinfo.image_height = height;
+			m_cinfo.input_components = 3;
+			m_cinfo.in_color_space = JCS_RGB;
+			jpeg_set_defaults(&m_cinfo);
+			jpeg_set_quality(&m_cinfo, quality, TRUE);
+
+			jpeg_start_compress(&m_cinfo, TRUE);
+		}
+
+
+		~output_impl()
+		// Destructor.  Clean up our jpeg reader state.
+		{
+			jpeg_finish_compress(&m_cinfo);
+/*
+			rw_dest* src = (rw_source*) m_cinfo.dest;
+			delete dest;
+			m_cinfo.dest = NULL;
+*/
+			jpeg_destroy_compress(&m_cinfo);
+		}
+
+
+		void	write_scanline(unsigned char* rgb_data)
+		// Write out a single scanline.
+		{
+			jpeg_write_scanlines(&m_cinfo, &rgb_data, 1);
+		}
+	};
+
+
+	/*static*/ output*	output::create(tu_file* in, int width, int height, int quality)
+	// Create and return a jpeg-input object that will read from the
+	// given input stream.
+	{
+		return new output_impl(in, width, height, quality);
+	}
+
+
+	// Default constructor.
+	output::~output() {}
+}
+
+
+#else // not TU_CONFIG_LINK_TO_JPEGLIB
+
+
+namespace jpeg
+{
+	/*static*/ input* input::create(tu_file* in)
+	{
+		return NULL;
+	}
+
+	/*static*/ input* input::create_swf_jpeg2_header_only(tu_file* in)
+	{
+		return NULL;
+	}
+
+	/*static*/ output* output::create(tu_file* out, int width, int height, int quality)
+	{
+		return NULL;
+	}
+
+}
+
+
+#endif // not TU_CONFIG_LINK_TO_JPEGLIB
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/membuf.cpp
diff -u gnash/libbase/membuf.cpp:1.2 gnash/libbase/membuf.cpp:1.3
--- gnash/libbase/membuf.cpp:1.2	Sat Feb 11 01:57:03 2006
+++ gnash/libbase/membuf.cpp	Sun Feb 26 15:49:30 2006
@@ -1,166 +1,166 @@
-// membuf.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// A simple memory buffer.  Similar to a string, but can hold null
-// characters.
-
-
-#include "membuf.h"
-#include "tu_file.h"
-#include "container.h"
-
-
-// Allocate in increments of BLOCKSIZE.
-static const int BLOCKSIZE = (1 << 12);
-
-
-static int capacity(int size)
-// Compute the buffer capacity corresponding to the given size.
-// Basically round up to the next block size.
-// Always return non-zero.
-{
-	// BLOCKSIZE must be a power of two.
-	compiler_assert((BLOCKSIZE & (BLOCKSIZE - 1)) == 0);
-
-	if (size == 0) {
-		// Special case, always allocate.
-		return BLOCKSIZE;
-	}
-
-	return (size + BLOCKSIZE - 1) & ~(BLOCKSIZE - 1);
-}
-
-
-membuf::membuf()
-	:
-	m_size(0),
-	m_capacity(0),
-	m_data(0),
-	m_read_only(false)
-{
-}
-
-
-membuf::membuf(const void* data, int size)
-	:
-	m_size(0),
-	m_capacity(0),
-	m_data(0),
-	m_read_only(false)
-{
-	append(data, size);
-}
-
-
-membuf::membuf(const membuf& buf)
-	:
-	m_size(0),
-	m_capacity(0),
-	m_data(0),
-	m_read_only(false)
-{
-	append(buf);
-}
-
-
-membuf::membuf(const tu_string& str)
-	:
-	m_size(0),
-	m_capacity(0),
-	m_data(0),
-	m_read_only(false)
-{
-	append(str);
-}
-
-
-// Special read-only constructor.
-membuf::membuf(read_only_enum e, const void* data, int size)
-	:
-	m_size(size),
-	m_capacity(0),
-	m_data(const_cast<void*>(data)),
-	m_read_only(true)
-{
-}
-
-
-membuf::~membuf()
-{
-	if (!m_read_only) {
-		tu_free(m_data, m_capacity);
-	}
-	m_capacity = 0;
-	m_data = NULL;
-}
-
-
-bool membuf::resize(int new_size)
-{
-	assert(!m_read_only);
-
-	if (new_size == m_size) {
-		return true;
-	}
-
-	int new_capacity = capacity(new_size);
-
-	if (m_data == NULL) {
-		m_data = tu_malloc(new_capacity);
-	} else {
-		if (new_capacity != m_capacity) {
-			m_data = tu_realloc(m_data, new_capacity, m_capacity);
-		}
-	}
-	if (m_data == NULL) {
-		// malloc/realloc failure!
-		m_size = 0;
-		m_capacity = 0;
-		m_data = NULL;
-		return false;
-	}
-	m_capacity = new_capacity;
-
-	assert(m_capacity >= new_size);
-
-	m_size = new_size;
-
-	return true;
-}
-
-
-bool membuf::append(const void* data, int datasize)
-{
-	assert(!m_read_only);
-
-	int old_size = size();
-	if (resize(size() + datasize) == false) {
-		return false;
-	}
-
-	memcpy(((char*) m_data) + old_size, data, datasize);
-
-	return true;
-}
-
-
-bool membuf::append(const membuf& buf)
-{
-	return append(buf.data(), buf.size());
-}
-
-
-bool membuf::append(const tu_string& str)
-{
-	return append(str.c_str(), str.length());
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// membuf.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// A simple memory buffer.  Similar to a string, but can hold null
+// characters.
+
+
+#include "membuf.h"
+#include "tu_file.h"
+#include "container.h"
+
+
+// Allocate in increments of BLOCKSIZE.
+static const int BLOCKSIZE = (1 << 12);
+
+
+static int capacity(int size)
+// Compute the buffer capacity corresponding to the given size.
+// Basically round up to the next block size.
+// Always return non-zero.
+{
+	// BLOCKSIZE must be a power of two.
+	compiler_assert((BLOCKSIZE & (BLOCKSIZE - 1)) == 0);
+
+	if (size == 0) {
+		// Special case, always allocate.
+		return BLOCKSIZE;
+	}
+
+	return (size + BLOCKSIZE - 1) & ~(BLOCKSIZE - 1);
+}
+
+
+membuf::membuf()
+	:
+	m_size(0),
+	m_capacity(0),
+	m_data(0),
+	m_read_only(false)
+{
+}
+
+
+membuf::membuf(const void* data, int size)
+	:
+	m_size(0),
+	m_capacity(0),
+	m_data(0),
+	m_read_only(false)
+{
+	append(data, size);
+}
+
+
+membuf::membuf(const membuf& buf)
+	:
+	m_size(0),
+	m_capacity(0),
+	m_data(0),
+	m_read_only(false)
+{
+	append(buf);
+}
+
+
+membuf::membuf(const tu_string& str)
+	:
+	m_size(0),
+	m_capacity(0),
+	m_data(0),
+	m_read_only(false)
+{
+	append(str);
+}
+
+
+// Special read-only constructor.
+membuf::membuf(read_only_enum e, const void* data, int size)
+	:
+	m_size(size),
+	m_capacity(0),
+	m_data(const_cast<void*>(data)),
+	m_read_only(true)
+{
+}
+
+
+membuf::~membuf()
+{
+	if (!m_read_only) {
+		tu_free(m_data, m_capacity);
+	}
+	m_capacity = 0;
+	m_data = NULL;
+}
+
+
+bool membuf::resize(int new_size)
+{
+	assert(!m_read_only);
+
+	if (new_size == m_size) {
+		return true;
+	}
+
+	int new_capacity = capacity(new_size);
+
+	if (m_data == NULL) {
+		m_data = tu_malloc(new_capacity);
+	} else {
+		if (new_capacity != m_capacity) {
+			m_data = tu_realloc(m_data, new_capacity, m_capacity);
+		}
+	}
+	if (m_data == NULL) {
+		// malloc/realloc failure!
+		m_size = 0;
+		m_capacity = 0;
+		m_data = NULL;
+		return false;
+	}
+	m_capacity = new_capacity;
+
+	assert(m_capacity >= new_size);
+
+	m_size = new_size;
+
+	return true;
+}
+
+
+bool membuf::append(const void* data, int datasize)
+{
+	assert(!m_read_only);
+
+	int old_size = size();
+	if (resize(size() + datasize) == false) {
+		return false;
+	}
+
+	memcpy(((char*) m_data) + old_size, data, datasize);
+
+	return true;
+}
+
+
+bool membuf::append(const membuf& buf)
+{
+	return append(buf.data(), buf.size());
+}
+
+
+bool membuf::append(const tu_string& str)
+{
+	return append(str.c_str(), str.length());
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/membuf.h
diff -u gnash/libbase/membuf.h:1.1 gnash/libbase/membuf.h:1.2
--- gnash/libbase/membuf.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/membuf.h	Sun Feb 26 15:49:30 2006
@@ -1,64 +1,64 @@
-// membuf.h	-- Thatcher Ulrich 2005
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// A simple memory buffer.  Similar to a string, but can hold null
-// characters.
-
-
-#ifndef MEMBUF_H
-#define MEMBUF_H
-
-
-#include "tu_config.h"
-#include "utility.h"
-
-class tu_string;
-
-
-struct membuf
-{
-	membuf();
-	membuf(const void* data, int size);
-	membuf(const membuf& buf);
-	membuf(const tu_string& str);
-	~membuf();
-
-	// Construct a read-only membuf that points at the given data,
-	// instead of copying it.
-	enum read_only_enum { READ_ONLY };
-	membuf(read_only_enum e, const void* data, int size);
-
-	int size() const { return m_size; }
-	const void* data() const { return m_data; }
-	void* data() { assert(!m_read_only); return m_data; }
-
-	// Don't call these mutators on read-only membufs.
-	
-	// Return false if we couldn't resize (i.e. realloc failure).
-	bool resize(int new_size);
-
-	// Return false on realloc failure.
-	bool append(const void* data, int size);
-	bool append(const membuf& buf);
-	// We do not append the terminating '\0'.
-	bool append(const tu_string& str);
-
-private:
-	int m_size;
-	int m_capacity;
-	void* m_data;
-	bool m_read_only;
-};
-
-
-#endif // MEMBUF_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// membuf.h	-- Thatcher Ulrich 2005
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// A simple memory buffer.  Similar to a string, but can hold null
+// characters.
+
+
+#ifndef MEMBUF_H
+#define MEMBUF_H
+
+
+#include "tu_config.h"
+#include "utility.h"
+
+class tu_string;
+
+
+struct membuf
+{
+	membuf();
+	membuf(const void* data, int size);
+	membuf(const membuf& buf);
+	membuf(const tu_string& str);
+	~membuf();
+
+	// Construct a read-only membuf that points at the given data,
+	// instead of copying it.
+	enum read_only_enum { READ_ONLY };
+	membuf(read_only_enum e, const void* data, int size);
+
+	int size() const { return m_size; }
+	const void* data() const { return m_data; }
+	void* data() { assert(!m_read_only); return m_data; }
+
+	// Don't call these mutators on read-only membufs.
+	
+	// Return false if we couldn't resize (i.e. realloc failure).
+	bool resize(int new_size);
+
+	// Return false on realloc failure.
+	bool append(const void* data, int size);
+	bool append(const membuf& buf);
+	// We do not append the terminating '\0'.
+	bool append(const tu_string& str);
+
+private:
+	int m_size;
+	int m_capacity;
+	void* m_data;
+	bool m_read_only;
+};
+
+
+#endif // MEMBUF_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/ogl.cpp
diff -u gnash/libbase/ogl.cpp:1.2 gnash/libbase/ogl.cpp:1.3
--- gnash/libbase/ogl.cpp:1.2	Sun Jan 22 16:04:17 2006
+++ gnash/libbase/ogl.cpp	Sun Feb 26 15:49:30 2006
@@ -1,445 +1,445 @@
-// ogl.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Some OpenGL helpers; mainly to generically deal with extensions.
-
-
-#include <SDL.h>
-#include "ogl.h"
-#include "utility.h"
-#include <stdlib.h>
-#include <string.h>
-
-
-namespace ogl {
-
-	bool	is_open = false;
-
-	// Pointers to extension functions.
-	typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, \
                float writefreq, float priority);
-	typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer);
-	typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (int size, void* buffer);
-	typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fence_array);
-	typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence_id, GLenum condition);
-	typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint fence_id);
-
-	typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
-	typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
-	typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, \
                GLfloat t);
-	typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const \
                GLfloat *v);
-
-	PFNWGLALLOCATEMEMORYNVPROC	wglAllocateMemoryNV = 0;
-	PFNWGLFREEMEMORYNVPROC	wglFreeMemoryNV = 0;
-	PFNGLVERTEXARRAYRANGENVPROC	glVertexArrayRangeNV = 0;
-	PFNGLGENFENCESNVPROC glGenFencesNV = 0;
-	PFNGLSETFENCENVPROC glSetFenceNV = 0;
-	PFNGLFINISHFENCENVPROC glFinishFenceNV = 0;
-
-	PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB = 0;
-	PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB = 0;
-	PFNGLMULTITEXCOORD2FARBPROC	glMultiTexCoord2fARB = 0;
-	PFNGLMULTITEXCOORD2FVARBPROC	glMultiTexCoord2fvARB = 0;
-
-
-	// GL_CLAMP or GL_CLAMP_TO_EDGE, depending on which is available.
-	int	s_clamp_to_edge = GL_CLAMP;
-
-	// Big, fast vertex-memory buffer.
-	const int	VERTEX_BUFFER_SIZE = 4 << 20;
-	void*	vertex_memory_buffer = 0;
-	int	vertex_memory_top = 0;
-	bool	vertex_memory_from_malloc = false;	// tells us whether to wglFreeMemoryNV() or \
                free() the buffer when we're done.
-
-
-	const int	STREAM_SUB_BUFFER_COUNT = 2;
-
-	class vertex_stream
-	{
-	// Class to facilitate streaming verts to the video card.  Takes
-	// care of fencing, and buffer bookkeeping.
-	public:
-		vertex_stream(int buffer_size);
-		~vertex_stream();
-	
-		void*	reserve_memory(int size);
-		void	flush_combiners();
-	
-	private:
-		int	m_sub_buffer_size;
-		int	m_buffer_top;
-		void*	m_buffer;
-		int	m_extra_bytes;	// extra bytes after last block; used to pad up to \
                write-combiner alignment
-	
-		unsigned int	m_fence[4];
-	};
-
-
-	vertex_stream*	s_stream = NULL;
-
-
-	void	open()
-	// Scan for extensions.
-	{
-		wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC) SDL_GL_GetProcAddress( \
                PROC_NAME_PREFIX "AllocateMemoryNV" );
-		wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) SDL_GL_GetProcAddress( PROC_NAME_PREFIX \
                "FreeMemoryNV" );
-		glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC) SDL_GL_GetProcAddress( \
                "glVertexArrayRangeNV" );
-
-		glGenFencesNV = (PFNGLGENFENCESNVPROC) SDL_GL_GetProcAddress( "glGenFencesNV" );
-		glSetFenceNV = (PFNGLSETFENCENVPROC) SDL_GL_GetProcAddress( "glSetFenceNV" );
-		glFinishFenceNV = (PFNGLFINISHFENCENVPROC) SDL_GL_GetProcAddress( \
                "glFinishFenceNV" );
-
-		glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) \
                SDL_GL_GetProcAddress("glActiveTextureARB");
-		glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) \
                SDL_GL_GetProcAddress("glClientActiveTextureARB");
-		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) \
                SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
-		glMultiTexCoord2fvARB = (PFNGLMULTITEXCOORD2FVARBPROC) \
                SDL_GL_GetProcAddress("glMultiTexCoord2fvARB");
-
-		if (check_extension("GL_SGIS_texture_edge_clamp")
-		    || check_extension("GL_EXT_texture_edge_clamp"))
-		{
-			// Use CLAMP_TO_EDGE, since it's available.
-			s_clamp_to_edge = GL_CLAMP_TO_EDGE;
-		}
-	}
-
-
-	void	close()
-	// Release anything we need to.
-	{
-		// @@ free that mongo vertex buffer.
-	}
-
-
-	int	get_clamp_mode()
-	// Return a constant to pass to glTexParameteri(GL_TEXTURE_2D,
-	// GL_TEXTURE_WRAP_x, ...), which is either GL_CLAMP or
-	// GL_CLAMP_TO_EDGE, depending on whether GL_CLAMP_TO_EDGE is
-	// available.
-	{
-		return s_clamp_to_edge;
-	}
-
-
-	bool	check_extension(const char* extension)
-	// Some extension checking code snipped from glut.
-	{
-		static const char*	extensions = NULL;
-		const char*	start;
-		char*	where;
-		char*	terminator;
-		bool	supported;
-	
-		// Extension names should not have spaces
-		where = strchr(extension, ' ');
-		if (where || *extension == '\0') return false;
-	
-		// Grab extensions (but only once)
-		if (!extensions) {
-			extensions = (const char*)glGetString(GL_EXTENSIONS);
-			// Double fault (no extensions)
-			if ( ! extensions ) return false;
-		}
-	
-		// Look for extension
-		start = extensions;
-		supported = false;
-		while (!supported)
-		{
-			// Does extension SEEM to be supported?
-			where = strstr((const char*)start, extension);
-			if (!where) break;
-
-			// Ok, extension SEEMS to be supported
-			supported = true;
-
-			// Check for space before extension
-			supported &= (where == start) || (where[-1] == ' ');
-
-			// Check for space after extension
-			terminator = where + strlen(extension);
-			supported &= (*terminator == '\0') || (*terminator == ' ');
-
-			// Next search starts at current terminator
-			start = terminator;
-		}
-
-		return supported;
-	}
-
-
-	void*	allocate_vertex_memory( int size )
-	// Allocate a block of memory for storing vertex data.  Using this
-	// allocator will hopefully give you faster glDrawElements(), if
-	// you do vertex_array_range on it before rendering.
-	{
-		// For best results, we must allocate one big ol' chunk of
-		// vertex memory on the first call to this function, via
-		// wglAllocateMemoryNV, and then allocate sub-chunks out of
-		// it.
-
-		if ( vertex_memory_buffer == 0 ) {
-			// Need to allocate the big chunk.
-			
-			// If we have NV's allocator, then use it.
-			if ( wglAllocateMemoryNV ) {
-				vertex_memory_buffer = wglAllocateMemoryNV( VERTEX_BUFFER_SIZE, 0.f, 0.f, 0.5f \
                );	// @@ this gets us AGP memory.
-//				wglAllocateMemoryNV( size, 0.f, 0.f, 1.0f );	// @@ this gets us video memory.
-				vertex_memory_from_malloc = false;
-				vertex_memory_top = 0;
-
-				if ( vertex_memory_buffer && glVertexArrayRangeNV ) {
-					glVertexArrayRangeNV( VERTEX_BUFFER_SIZE, vertex_memory_buffer );
-				}
-
-				glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);	// \
                GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV
-			}
-			// else we'll fall back on malloc() for vb allocations.
-		}
-
-		// Carve a chunk out of our big buffer, or out of malloc if
-		// the buffer is dry.
-
-		if ( vertex_memory_buffer && vertex_memory_top + size <= VERTEX_BUFFER_SIZE ) {
-			// Just allocate from the end of the big buffer and increment the top.
-			unsigned char*	buffer = (unsigned char*) vertex_memory_buffer + \
                vertex_memory_top;
-			vertex_memory_top += size;
-
-			return (void*) buffer;
-
-		} else {
-			// Fall back to malloc.
-			printf( "avm: warning, falling back to malloc!\n" );
-			return malloc( size );
-		}
-	}
-
-
-	void	free_vertex_memory(void* buffer)
-	// Frees a buffer previously allocated via allocate_vertex_memory().
-	{
-		// this function is not ready for prime-time.
-		assert( 0 );
-	}
-
-
-	void	gen_fences(int count, unsigned int* fence_array)
-	// Wrapper for glGenFencesNV.
-	{
-		if (glGenFencesNV) {
-			glGenFencesNV(count, (GLuint*)fence_array);
-		}
-		else
-		{
-			// set all fences to 0.
-			for (int i = 0; i < count; i++) {
-				fence_array[i] = 0;
-			}
-		}
-	}
-
-	
-	void	set_fence(unsigned int fence_id)
-	// Use this to declare all previous glDrawElements() calls as
-	// belonging to the specified fence.  A subsequent
-	// finish_fence(id) will block until those drawing calls have
-	// completed.
-	{
-		if (glSetFenceNV)
-		{
-			glSetFenceNV(fence_id, GL_ALL_COMPLETED_NV);
-		}
-		// else no-op.
-	}
-
-
-	void	finish_fence(unsigned int fence_id)
-	// Block until all gl drawing calls, associated with the specified
-	// fence, have completed.
-	{
-		if (glFinishFenceNV)
-		{
-			glFinishFenceNV(fence_id);
-		}
-		// else no-op.
-	}
-
-
-	void*	stream_get_vertex_memory(int size)
-	// Return a buffer to contain size bytes of vertex memory.
-	// Put your vertex data in it, then call
-	// stream_flush_combiners(), then call glDrawElements() to
-	// draw the primitives.
-	{
-		if (s_stream == NULL) {
-			s_stream = new vertex_stream(VERTEX_BUFFER_SIZE);
-		}
-
-		return s_stream->reserve_memory(size);
-	}
-
-
-	void	stream_flush_combiners()
-	// Make sure to flush all data written to the most recently
-	// requested vertex buffer (requested by the last call to
-	// stream_get_vertex_memory()).  Ensure that the data doesn't
-	// get hung up in a processor write-combiner.
-	{
-		assert(s_stream);
-		if (s_stream == NULL) return;
-
-		s_stream->flush_combiners();
-	}
-
-
-	static const int	WRITE_COMBINER_ALIGNMENT = 64;	// line-size (in bytes) of the \
                write-combiners, must be power of 2
-
-
-	int	wc_align_up(int size)
-	// Return given size, rounded up to the next nearest write combiner
-	// alignment boundary.
-	{
-		assert((WRITE_COMBINER_ALIGNMENT & (WRITE_COMBINER_ALIGNMENT - 1)) == 0);	// make \
                sure it's a power of 2
-
-		return (size + WRITE_COMBINER_ALIGNMENT - 1) & ~(WRITE_COMBINER_ALIGNMENT - 1);
-	}
-
-
-	//
-	// vertex_stream
-	//
-
-	vertex_stream::vertex_stream(int buffer_size)
-	// Construct a streaming buffer, with vertex RAM of the specified size.
-	{
-		assert(buffer_size >= STREAM_SUB_BUFFER_COUNT);
-	
-		m_sub_buffer_size = buffer_size / STREAM_SUB_BUFFER_COUNT;
-		m_buffer = ogl::allocate_vertex_memory(buffer_size);
-		m_buffer_top = 0;
-		m_extra_bytes = 0;
-	
-		// set up fences.
-		ogl::gen_fences(4, &m_fence[0]);
-
-		// Set (dummy) fences which will be finished as we reach them.
-		ogl::set_fence(m_fence[1]);
-		ogl::set_fence(m_fence[2]);
-		ogl::set_fence(m_fence[3]);
-	}
-
-	vertex_stream::~vertex_stream()
-	{
-//		ogl::free_vertex_memory(m_buffer);
-	}
-
-	void*	vertex_stream::reserve_memory(int size)
-	// Clients should call this to get a temporary chunk of fast
-	// vertex memory.  Fill it with vertex info and call
-	// glVertexPointer()/glDrawElements().  The memory won't get
-	// stomped until the drawing is finished, provided you use the
-	// returned buffer in a glDrawElements call before you call
-	// reserve_memory() to get the next chunk.
-	{
-		assert(size <= m_sub_buffer_size);
-
-		int	aligned_size = wc_align_up(size);
-		m_extra_bytes = aligned_size - size;
-	
-		for (int sub_buffer = 1; sub_buffer <= STREAM_SUB_BUFFER_COUNT; sub_buffer++)
-		{
-			int	border = m_sub_buffer_size * sub_buffer;
-
-			if (m_buffer_top <= border
-			    && m_buffer_top + aligned_size > border)
-			{
-				// Crossing into the next sub-buffer.
-
-				int	prev_buffer = sub_buffer - 1;
-				int	next_buffer = sub_buffer % STREAM_SUB_BUFFER_COUNT;
-
-				// Protect the previous sub-buffer.
-				ogl::set_fence(m_fence[prev_buffer]);
-
-				// Don't overwrite the next sub-buffer while it's still active.
-				ogl::finish_fence(m_fence[next_buffer]);
-	
-				// Start the next quarter-buffer.
-				m_buffer_top = m_sub_buffer_size * next_buffer;
-			}
-		}
-	
-		void*	buf = ((char*) m_buffer) + m_buffer_top;
-		m_buffer_top += aligned_size;
-	
-		return buf;
-	}
-	
-	
-	void	vertex_stream::flush_combiners()
-	// Make sure the tail of the block returned by the last call
-	// to reserve_memory() gets written to the system RAM.  If the
-	// block doesn't end on a write-combiner line boundary, the
-	// last bit of data may still be waiting to be flushed.
-	//
-	// That's my theory anyway -- farfetched but I'm not sure how
-	// else to explain certain bug reports of spurious triangles
-	// being rendered.
-	{
-		if (m_extra_bytes) {
-			// Fill up the rest of the last write-combiner line.
-			memset(((char*) m_buffer) + m_buffer_top - m_extra_bytes, 0, m_extra_bytes);
-		}
-	}
-
-
-	// Wrappers for multitexture extensions; no-op if the extension doesn't exist.
-
-	void	active_texture(int stage)
-	// Set the currently active texture stage; use GL_TEXTUREx_ARB.
-	{
-		if (glActiveTextureARB)
-		{
-			glActiveTextureARB(stage);
-		}
-	}
-
-	void	client_active_texture(int stage)
-	// Set the currently active texture stage for vertex array
-	// setup; use GL_TEXTUREx_ARB.
-	{
-		if (glClientActiveTextureARB)
-		{
-			glClientActiveTextureARB(stage);
-		}
-	}
-
-	void	multi_tex_coord_2f(int stage, float s, float t)
-	// Texture coords for the current vertex, in the specified
-	// stage.
-	{
-		if (glMultiTexCoord2fARB)
-		{
-			glMultiTexCoord2fARB(stage, s, t);
-		}
-	}
-
-	void	multi_tex_coord_2fv(int stage, float* st)
-	// Texture coords for the current vertex, in the specified
-	// stage.
-	{
-		if (glMultiTexCoord2fvARB)
-		{
-			glMultiTexCoord2fvARB(stage, st);
-		}
-	}
-};
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-
-// indent-tabs-mode: t
-// End:
+// ogl.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Some OpenGL helpers; mainly to generically deal with extensions.
+
+
+#include <SDL.h>
+#include "ogl.h"
+#include "utility.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+namespace ogl {
+
+	bool	is_open = false;
+
+	// Pointers to extension functions.
+	typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, \
float writefreq, float priority); +	typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) \
(void *pointer); +	typedef void (APIENTRY * PFNGLVERTEXARRAYRANGENVPROC) (int size, \
void* buffer); +	typedef void (APIENTRY * PFNGLGENFENCESNVPROC) (GLsizei n, GLuint \
*fence_array); +	typedef void (APIENTRY * PFNGLSETFENCENVPROC) (GLuint fence_id, \
GLenum condition); +	typedef void (APIENTRY * PFNGLFINISHFENCENVPROC) (GLuint \
fence_id); +
+	typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+	typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+	typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, \
GLfloat t); +	typedef void (APIENTRY * PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, \
const GLfloat *v); +
+	PFNWGLALLOCATEMEMORYNVPROC	wglAllocateMemoryNV = 0;
+	PFNWGLFREEMEMORYNVPROC	wglFreeMemoryNV = 0;
+	PFNGLVERTEXARRAYRANGENVPROC	glVertexArrayRangeNV = 0;
+	PFNGLGENFENCESNVPROC glGenFencesNV = 0;
+	PFNGLSETFENCENVPROC glSetFenceNV = 0;
+	PFNGLFINISHFENCENVPROC glFinishFenceNV = 0;
+
+	PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB = 0;
+	PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB = 0;
+	PFNGLMULTITEXCOORD2FARBPROC	glMultiTexCoord2fARB = 0;
+	PFNGLMULTITEXCOORD2FVARBPROC	glMultiTexCoord2fvARB = 0;
+
+
+	// GL_CLAMP or GL_CLAMP_TO_EDGE, depending on which is available.
+	int	s_clamp_to_edge = GL_CLAMP;
+
+	// Big, fast vertex-memory buffer.
+	const int	VERTEX_BUFFER_SIZE = 4 << 20;
+	void*	vertex_memory_buffer = 0;
+	int	vertex_memory_top = 0;
+	bool	vertex_memory_from_malloc = false;	// tells us whether to wglFreeMemoryNV() or \
free() the buffer when we're done. +
+
+	const int	STREAM_SUB_BUFFER_COUNT = 2;
+
+	class vertex_stream
+	{
+	// Class to facilitate streaming verts to the video card.  Takes
+	// care of fencing, and buffer bookkeeping.
+	public:
+		vertex_stream(int buffer_size);
+		~vertex_stream();
+	
+		void*	reserve_memory(int size);
+		void	flush_combiners();
+	
+	private:
+		int	m_sub_buffer_size;
+		int	m_buffer_top;
+		void*	m_buffer;
+		int	m_extra_bytes;	// extra bytes after last block; used to pad up to \
write-combiner alignment +	
+		unsigned int	m_fence[4];
+	};
+
+
+	vertex_stream*	s_stream = NULL;
+
+
+	void	open()
+	// Scan for extensions.
+	{
+		wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC) SDL_GL_GetProcAddress( \
PROC_NAME_PREFIX "AllocateMemoryNV" ); +		wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) \
SDL_GL_GetProcAddress( PROC_NAME_PREFIX "FreeMemoryNV" ); +		glVertexArrayRangeNV = \
(PFNGLVERTEXARRAYRANGENVPROC) SDL_GL_GetProcAddress( "glVertexArrayRangeNV" ); +
+		glGenFencesNV = (PFNGLGENFENCESNVPROC) SDL_GL_GetProcAddress( "glGenFencesNV" );
+		glSetFenceNV = (PFNGLSETFENCENVPROC) SDL_GL_GetProcAddress( "glSetFenceNV" );
+		glFinishFenceNV = (PFNGLFINISHFENCENVPROC) SDL_GL_GetProcAddress( \
"glFinishFenceNV" ); +
+		glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) \
SDL_GL_GetProcAddress("glActiveTextureARB"); +		glClientActiveTextureARB = \
(PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB"); \
+		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) \
SDL_GL_GetProcAddress("glMultiTexCoord2fARB"); +		glMultiTexCoord2fvARB = \
(PFNGLMULTITEXCOORD2FVARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fvARB"); +
+		if (check_extension("GL_SGIS_texture_edge_clamp")
+		    || check_extension("GL_EXT_texture_edge_clamp"))
+		{
+			// Use CLAMP_TO_EDGE, since it's available.
+			s_clamp_to_edge = GL_CLAMP_TO_EDGE;
+		}
+	}
+
+
+	void	close()
+	// Release anything we need to.
+	{
+		// @@ free that mongo vertex buffer.
+	}
+
+
+	int	get_clamp_mode()
+	// Return a constant to pass to glTexParameteri(GL_TEXTURE_2D,
+	// GL_TEXTURE_WRAP_x, ...), which is either GL_CLAMP or
+	// GL_CLAMP_TO_EDGE, depending on whether GL_CLAMP_TO_EDGE is
+	// available.
+	{
+		return s_clamp_to_edge;
+	}
+
+
+	bool	check_extension(const char* extension)
+	// Some extension checking code snipped from glut.
+	{
+		static const char*	extensions = NULL;
+		const char*	start;
+		char*	where;
+		char*	terminator;
+		bool	supported;
+	
+		// Extension names should not have spaces
+		where = strchr(extension, ' ');
+		if (where || *extension == '\0') return false;
+	
+		// Grab extensions (but only once)
+		if (!extensions) {
+			extensions = (const char*)glGetString(GL_EXTENSIONS);
+			// Double fault (no extensions)
+			if ( ! extensions ) return false;
+		}
+	
+		// Look for extension
+		start = extensions;
+		supported = false;
+		while (!supported)
+		{
+			// Does extension SEEM to be supported?
+			where = strstr((const char*)start, extension);
+			if (!where) break;
+
+			// Ok, extension SEEMS to be supported
+			supported = true;
+
+			// Check for space before extension
+			supported &= (where == start) || (where[-1] == ' ');
+
+			// Check for space after extension
+			terminator = where + strlen(extension);
+			supported &= (*terminator == '\0') || (*terminator == ' ');
+
+			// Next search starts at current terminator
+			start = terminator;
+		}
+
+		return supported;
+	}
+
+
+	void*	allocate_vertex_memory( int size )
+	// Allocate a block of memory for storing vertex data.  Using this
+	// allocator will hopefully give you faster glDrawElements(), if
+	// you do vertex_array_range on it before rendering.
+	{
+		// For best results, we must allocate one big ol' chunk of
+		// vertex memory on the first call to this function, via
+		// wglAllocateMemoryNV, and then allocate sub-chunks out of
+		// it.
+
+		if ( vertex_memory_buffer == 0 ) {
+			// Need to allocate the big chunk.
+			
+			// If we have NV's allocator, then use it.
+			if ( wglAllocateMemoryNV ) {
+				vertex_memory_buffer = wglAllocateMemoryNV( VERTEX_BUFFER_SIZE, 0.f, 0.f, 0.5f \
);	// @@ this gets us AGP memory. +//				wglAllocateMemoryNV( size, 0.f, 0.f, 1.0f \
);	// @@ this gets us video memory. +				vertex_memory_from_malloc = false;
+				vertex_memory_top = 0;
+
+				if ( vertex_memory_buffer && glVertexArrayRangeNV ) {
+					glVertexArrayRangeNV( VERTEX_BUFFER_SIZE, vertex_memory_buffer );
+				}
+
+				glEnableClientState(GL_VERTEX_ARRAY_RANGE_NV);	// \
GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV +			}
+			// else we'll fall back on malloc() for vb allocations.
+		}
+
+		// Carve a chunk out of our big buffer, or out of malloc if
+		// the buffer is dry.
+
+		if ( vertex_memory_buffer && vertex_memory_top + size <= VERTEX_BUFFER_SIZE ) {
+			// Just allocate from the end of the big buffer and increment the top.
+			unsigned char*	buffer = (unsigned char*) vertex_memory_buffer + \
vertex_memory_top; +			vertex_memory_top += size;
+
+			return (void*) buffer;
+
+		} else {
+			// Fall back to malloc.
+			printf( "avm: warning, falling back to malloc!\n" );
+			return malloc( size );
+		}
+	}
+
+
+	void	free_vertex_memory(void* buffer)
+	// Frees a buffer previously allocated via allocate_vertex_memory().
+	{
+		// this function is not ready for prime-time.
+		assert( 0 );
+	}
+
+
+	void	gen_fences(int count, unsigned int* fence_array)
+	// Wrapper for glGenFencesNV.
+	{
+		if (glGenFencesNV) {
+			glGenFencesNV(count, (GLuint*)fence_array);
+		}
+		else
+		{
+			// set all fences to 0.
+			for (int i = 0; i < count; i++) {
+				fence_array[i] = 0;
+			}
+		}
+	}
+
+	
+	void	set_fence(unsigned int fence_id)
+	// Use this to declare all previous glDrawElements() calls as
+	// belonging to the specified fence.  A subsequent
+	// finish_fence(id) will block until those drawing calls have
+	// completed.
+	{
+		if (glSetFenceNV)
+		{
+			glSetFenceNV(fence_id, GL_ALL_COMPLETED_NV);
+		}
+		// else no-op.
+	}
+
+
+	void	finish_fence(unsigned int fence_id)
+	// Block until all gl drawing calls, associated with the specified
+	// fence, have completed.
+	{
+		if (glFinishFenceNV)
+		{
+			glFinishFenceNV(fence_id);
+		}
+		// else no-op.
+	}
+
+
+	void*	stream_get_vertex_memory(int size)
+	// Return a buffer to contain size bytes of vertex memory.
+	// Put your vertex data in it, then call
+	// stream_flush_combiners(), then call glDrawElements() to
+	// draw the primitives.
+	{
+		if (s_stream == NULL) {
+			s_stream = new vertex_stream(VERTEX_BUFFER_SIZE);
+		}
+
+		return s_stream->reserve_memory(size);
+	}
+
+
+	void	stream_flush_combiners()
+	// Make sure to flush all data written to the most recently
+	// requested vertex buffer (requested by the last call to
+	// stream_get_vertex_memory()).  Ensure that the data doesn't
+	// get hung up in a processor write-combiner.
+	{
+		assert(s_stream);
+		if (s_stream == NULL) return;
+
+		s_stream->flush_combiners();
+	}
+
+
+	static const int	WRITE_COMBINER_ALIGNMENT = 64;	// line-size (in bytes) of the \
write-combiners, must be power of 2 +
+
+	int	wc_align_up(int size)
+	// Return given size, rounded up to the next nearest write combiner
+	// alignment boundary.
+	{
+		assert((WRITE_COMBINER_ALIGNMENT & (WRITE_COMBINER_ALIGNMENT - 1)) == 0);	// make \
sure it's a power of 2 +
+		return (size + WRITE_COMBINER_ALIGNMENT - 1) & ~(WRITE_COMBINER_ALIGNMENT - 1);
+	}
+
+
+	//
+	// vertex_stream
+	//
+
+	vertex_stream::vertex_stream(int buffer_size)
+	// Construct a streaming buffer, with vertex RAM of the specified size.
+	{
+		assert(buffer_size >= STREAM_SUB_BUFFER_COUNT);
+	
+		m_sub_buffer_size = buffer_size / STREAM_SUB_BUFFER_COUNT;
+		m_buffer = ogl::allocate_vertex_memory(buffer_size);
+		m_buffer_top = 0;
+		m_extra_bytes = 0;
+	
+		// set up fences.
+		ogl::gen_fences(4, &m_fence[0]);
+
+		// Set (dummy) fences which will be finished as we reach them.
+		ogl::set_fence(m_fence[1]);
+		ogl::set_fence(m_fence[2]);
+		ogl::set_fence(m_fence[3]);
+	}
+
+	vertex_stream::~vertex_stream()
+	{
+//		ogl::free_vertex_memory(m_buffer);
+	}
+
+	void*	vertex_stream::reserve_memory(int size)
+	// Clients should call this to get a temporary chunk of fast
+	// vertex memory.  Fill it with vertex info and call
+	// glVertexPointer()/glDrawElements().  The memory won't get
+	// stomped until the drawing is finished, provided you use the
+	// returned buffer in a glDrawElements call before you call
+	// reserve_memory() to get the next chunk.
+	{
+		assert(size <= m_sub_buffer_size);
+
+		int	aligned_size = wc_align_up(size);
+		m_extra_bytes = aligned_size - size;
+	
+		for (int sub_buffer = 1; sub_buffer <= STREAM_SUB_BUFFER_COUNT; sub_buffer++)
+		{
+			int	border = m_sub_buffer_size * sub_buffer;
+
+			if (m_buffer_top <= border
+			    && m_buffer_top + aligned_size > border)
+			{
+				// Crossing into the next sub-buffer.
+
+				int	prev_buffer = sub_buffer - 1;
+				int	next_buffer = sub_buffer % STREAM_SUB_BUFFER_COUNT;
+
+				// Protect the previous sub-buffer.
+				ogl::set_fence(m_fence[prev_buffer]);
+
+				// Don't overwrite the next sub-buffer while it's still active.
+				ogl::finish_fence(m_fence[next_buffer]);
+	
+				// Start the next quarter-buffer.
+				m_buffer_top = m_sub_buffer_size * next_buffer;
+			}
+		}
+	
+		void*	buf = ((char*) m_buffer) + m_buffer_top;
+		m_buffer_top += aligned_size;
+	
+		return buf;
+	}
+	
+	
+	void	vertex_stream::flush_combiners()
+	// Make sure the tail of the block returned by the last call
+	// to reserve_memory() gets written to the system RAM.  If the
+	// block doesn't end on a write-combiner line boundary, the
+	// last bit of data may still be waiting to be flushed.
+	//
+	// That's my theory anyway -- farfetched but I'm not sure how
+	// else to explain certain bug reports of spurious triangles
+	// being rendered.
+	{
+		if (m_extra_bytes) {
+			// Fill up the rest of the last write-combiner line.
+			memset(((char*) m_buffer) + m_buffer_top - m_extra_bytes, 0, m_extra_bytes);
+		}
+	}
+
+
+	// Wrappers for multitexture extensions; no-op if the extension doesn't exist.
+
+	void	active_texture(int stage)
+	// Set the currently active texture stage; use GL_TEXTUREx_ARB.
+	{
+		if (glActiveTextureARB)
+		{
+			glActiveTextureARB(stage);
+		}
+	}
+
+	void	client_active_texture(int stage)
+	// Set the currently active texture stage for vertex array
+	// setup; use GL_TEXTUREx_ARB.
+	{
+		if (glClientActiveTextureARB)
+		{
+			glClientActiveTextureARB(stage);
+		}
+	}
+
+	void	multi_tex_coord_2f(int stage, float s, float t)
+	// Texture coords for the current vertex, in the specified
+	// stage.
+	{
+		if (glMultiTexCoord2fARB)
+		{
+			glMultiTexCoord2fARB(stage, s, t);
+		}
+	}
+
+	void	multi_tex_coord_2fv(int stage, float* st)
+	// Texture coords for the current vertex, in the specified
+	// stage.
+	{
+		if (glMultiTexCoord2fvARB)
+		{
+			glMultiTexCoord2fvARB(stage, st);
+		}
+	}
+};
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/png_helper.cpp
diff -u gnash/libbase/png_helper.cpp:1.1 gnash/libbase/png_helper.cpp:1.2
--- gnash/libbase/png_helper.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/png_helper.cpp	Sun Feb 26 15:49:30 2006
@@ -1,98 +1,98 @@
-// png_helper.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2004
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Wrapper for png file operations.  The actual work is done by the
-// libpng lib.
-
-
-#include "utility.h"
-#include "png_helper.h"
-#include "tu_file.h"
-#include <stdio.h>
-
-#if TU_CONFIG_LINK_TO_LIBPNG
-
-#include <png.h>
-
-
-namespace png_helper
-{
-	void	write_grayscale(FILE* out, uint8* data, int width, int height)
-	// Writes an 8-bit grayscale image in .png format, to the
-	// given output stream.
-	{
-		png_structp	png_ptr;
-		png_infop	info_ptr;
-
-		png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-		if (png_ptr == NULL)
-		{
-			// @@ log error here!
-			return;
-		}
-
-		info_ptr = png_create_info_struct(png_ptr);
-		if (info_ptr == NULL)
-		{
-			// @@ log error here!
-			png_destroy_write_struct(&png_ptr, NULL);
-			return;
-		}
-
-		if (setjmp(png_jmpbuf(png_ptr)))
-		{
-			// Error.
-			png_destroy_write_struct(&png_ptr, &info_ptr);
-			return;
-		}
-
-		png_init_io(png_ptr, out);
-
-		png_set_IHDR(
-			png_ptr,
-			info_ptr,
-			width,
-			height,
-			8,
-			PNG_COLOR_TYPE_GRAY,
-			PNG_INTERLACE_NONE,
-			PNG_COMPRESSION_TYPE_DEFAULT,
-			PNG_FILTER_TYPE_DEFAULT);
-
-		png_write_info(png_ptr, info_ptr);
-		
-		for (int y = 0; y < height; y++)
-		{
-			png_write_row(png_ptr, data + width * y);
-		}
-
-		png_write_end(png_ptr, info_ptr);
-
-		png_destroy_write_struct(&png_ptr, &info_ptr);
-	}
-}
-
-
-#else // not TU_CONFIG_LINK_TO_JPEGLIB
-
-
-namespace jpeg
-{
-	void	write_grayscale(FILE* out, uint8* data, int width, int height)
-	{
-		// no-op
-	}
-}
-
-
-#endif // not TU_CONFIG_LINK_TO_LIBPNG
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// png_helper.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2004
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Wrapper for png file operations.  The actual work is done by the
+// libpng lib.
+
+
+#include "utility.h"
+#include "png_helper.h"
+#include "tu_file.h"
+#include <stdio.h>
+
+#if TU_CONFIG_LINK_TO_LIBPNG
+
+#include <png.h>
+
+
+namespace png_helper
+{
+	void	write_grayscale(FILE* out, uint8* data, int width, int height)
+	// Writes an 8-bit grayscale image in .png format, to the
+	// given output stream.
+	{
+		png_structp	png_ptr;
+		png_infop	info_ptr;
+
+		png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+		if (png_ptr == NULL)
+		{
+			// @@ log error here!
+			return;
+		}
+
+		info_ptr = png_create_info_struct(png_ptr);
+		if (info_ptr == NULL)
+		{
+			// @@ log error here!
+			png_destroy_write_struct(&png_ptr, NULL);
+			return;
+		}
+
+		if (setjmp(png_jmpbuf(png_ptr)))
+		{
+			// Error.
+			png_destroy_write_struct(&png_ptr, &info_ptr);
+			return;
+		}
+
+		png_init_io(png_ptr, out);
+
+		png_set_IHDR(
+			png_ptr,
+			info_ptr,
+			width,
+			height,
+			8,
+			PNG_COLOR_TYPE_GRAY,
+			PNG_INTERLACE_NONE,
+			PNG_COMPRESSION_TYPE_DEFAULT,
+			PNG_FILTER_TYPE_DEFAULT);
+
+		png_write_info(png_ptr, info_ptr);
+		
+		for (int y = 0; y < height; y++)
+		{
+			png_write_row(png_ptr, data + width * y);
+		}
+
+		png_write_end(png_ptr, info_ptr);
+
+		png_destroy_write_struct(&png_ptr, &info_ptr);
+	}
+}
+
+
+#else // not TU_CONFIG_LINK_TO_JPEGLIB
+
+
+namespace jpeg
+{
+	void	write_grayscale(FILE* out, uint8* data, int width, int height)
+	{
+		// no-op
+	}
+}
+
+
+#endif // not TU_CONFIG_LINK_TO_LIBPNG
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/postscript.cpp
diff -u gnash/libbase/postscript.cpp:1.1 gnash/libbase/postscript.cpp:1.2
--- gnash/libbase/postscript.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/postscript.cpp	Sun Feb 26 15:49:30 2006
@@ -1,288 +1,288 @@
-// postscript.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Some helpers for generating Postscript graphics.
-
-
-#include "postscript.h"
-
-#include "tu_file.h"
-#include "utility.h"
-#include <stdarg.h>
-
-
-// Loosely translated into C++ from:
-// -- ps.lua
-// -- lua interface to postscript
-// -- Luiz Henrique de Figueiredo (lhf@csg.uwaterloo.ca)
-// -- 14 May 96
-//
-// From the Lua 4.0.1 distribution, see http://www.lua.org
-
-
-
-postscript::postscript(tu_file* out, const char* title, bool encapsulated)
-	:
-	m_out(out),
-	m_page(0),
-	m_x0(1000),
-	m_x1(0),
-	m_y0(1000),
-	m_y1(0),
-	m_empty(true)	
-// Initialize the file & this struct, etc.
-{
-	assert(m_out != NULL);
-
-	if (title == NULL)
-	{
-		title = "no title";
-	}
-
-	if (encapsulated)
-	{
-		m_out->printf("%%!PS-Adobe-2.0 EPSF-1.2\n");
-	}
-	else
-	{
-		m_out->printf("%%!PS-Adobe 3.0\n");
-	}
-	m_out->printf("%%%%Title: %s\n", title);
-	m_out->printf(
-		"%%%%Creator: postscript.cpp from tu-testbed\n"
-		"%%%%CreationDate: 1 1 2001\n"
-		"%%%%Pages: (atend)\n"
-		"%%%%BoundingBox: (atend)\n"
-		"%%%%EndComments\n"
-		"%%%%BeginProcSet: postscript.cpp\n"
-		"/s { stroke } bind def\n"
-		"/f { fill } bind def\n"
-		"/m { moveto } bind def\n"
-		"/l { lineto } bind def\n"
-		"/L { moveto lineto stroke } bind def\n"
-		"/t { show } bind def\n"
-		"/o { 0 360 arc stroke } bind def\n"
-		"/O { 0 360 arc fill } bind def\n"
-		"/p { 3 0 360 arc fil } bind def\n"
-		"/F { findfont exch scalefont setfont } bind def\n"
-		"/LS { 0 setdash } bind def\n"
-		"/LW { setlinewidth } bind def\n"
-		"%%%%EndProcSet: postscript.cpp\n"
-		"%%%%EndProlog\n"
-		"%%%%BeginSetup\n"
-		"0 setlinewidth\n"
-		"1 setlinejoin\n"
-		"1 setlinecap\n"
-		"10 /Times-Roman F\n"
-		"%%%%EndSetup\n\n"
-		"%%%%Page: 1 1\n");
-}
-
-
-postscript::~postscript()
-// End the Postscript info.
-{
-	m_out->printf(
-		"stroke\n"
-		"showpage\n"
-		"%%%%Trailer\n"
-		"%%%%Pages: %d %d\n"
-		"%%%%BoundingBox: %d %d %d %d\n"
-		"%%%%EOF\n",
-		m_page + 1, m_page + 1,
-		int(m_x0), int(m_y0), int(m_x1), int(m_y1)
-		);
-	
-}
-
-
-void	postscript::clear()
-// New page.
-{
-	if (m_empty) return;
-
-	m_page++;
-	m_out->printf("showpage\n%%%%Page: %d %d\n", m_page + 1, m_page + 1);
-
-	m_empty = true;
-}
-
-
-void	postscript::comment(const char* s)
-// Insert a comment into the output.
-{
-	m_out->printf("%% %s\n", s);
-}
-
-
-void	postscript::rgbcolor(float r, float g, float b)
-// Set the pen color.  Components range from 0 to 1.
-{
-	m_out->printf("%f %f %f setrgbcolor\n", r, g, b);
-}
-
-
-void	postscript::gray(float amount)
-// 0 == black, 1 == white
-{
-	m_out->printf("%f setgray\n", amount);
-}
-
-
-void	postscript::black()
-{
-	rgbcolor(0, 0, 0);
-}
-
-
-void	postscript::line(float x0, float y0, float x1, float y1)
-{
-	m_out->printf(
-		"%f %f %f %f L\n",
-		x1, y1, x0, y0);
-
-	update(x0, y0);
-	update(x1, y1);
-}
-
-
-void	postscript::moveto(float x0, float y0)
-{
-	m_out->printf(
-		"%f %f m\n",
-		x0, y0);
-
-	update(x0, y0);
-}
-
-
-void	postscript::lineto(float x0, float y0)
-{
-	m_out->printf(
-		"%f %f l\n",
-		x0, y0);
-
-	update(x0, y0);
-}
-
-
-void	postscript::linewidth(float w)
-{
-	m_out->printf("%f LW\n", w);
-}
-
-
-// @@ linestyle ?
-
-
-void	postscript::fill()
-{
-	m_out->printf("f\n");
-}
-	
-
-void	postscript::font(const char* name, float size)
-{
-	m_out->printf("%f /%s F\n", size, name);
-}
-
-
-#ifdef _WIN32
-#define vsnprintf	_vsnprintf
-#endif // _WIN32
-
-
-void	postscript::printf(float x, float y, const char* fmt, ...)
-{
-	static const int	BUFFER_SIZE = 1000;
-
-	char	buffer[BUFFER_SIZE];
-
-	va_list ap;
-	va_start(ap, fmt);
-	vsnprintf(buffer, BUFFER_SIZE, fmt, ap);
-	va_end(ap);
-
-	m_out->printf("%f %f m (%s) t\n", x, y, buffer);
-	update(x, y);
-	update(x + 100, y + 10);	// @@ should get bounds of text and update properly!
-}
-
-
-void	postscript::circle(float x, float y, float radius)
-{
-	m_out->printf("%f %f %f o\n", x, y, radius);
-	update(x - radius, y - radius);
-	update(x + radius, y + radius);
-}
-
-
-void	postscript::disk(float x, float y, float radius)
-{
-	m_out->printf("%f %f %f O\n", x, y, radius);
-	update(x - radius, y - radius);
-	update(x + radius, y + radius);
-}
-
-
-void	postscript::dot(float x, float y)
-{
-	m_out->printf("%f %f p\n", x, y);
-	update(x, y);
-}
-
-
-void	postscript::rectangle(float x0, float x1, float y0, float y1)
-{
-	m_out->printf(
-		"%f %f m "
-		"%f %f l "
-		"%f %f l "
-		"%f %f l "
-		"%f %f l s\n",
-		x0, y0,
-		x1, y0,
-		x1, y1,
-		x0, y1,
-		x0, y0);
-	update(x0, y0);
-	update(x1, y1);
-}
-
-
-void	postscript::box(float x0, float x1, float y0, float y1)
-{
-	m_out->printf(
-		"%f %f m "
-		"%f %f l "
-		"%f %f l "
-		"%f %f l f\n",
-		x0, y0,
-		x1, y0,
-		x1, y1,
-		x0, y1);
-	update(x0, y0);
-	update(x1, y1);
-}
-
-
-void	postscript::update(float x, float y)
-// enlarge the bounding box if necessary.
-{
-	if (x < m_x0) m_x0 = floorf(x);
-	if (x > m_x1) m_x1 = ceilf(x);
-	if (y < m_y0) m_y0 = floorf(y);
-	if (y > m_y1) m_y1 = ceilf(y);
-
-	m_empty = false;
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// postscript.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Some helpers for generating Postscript graphics.
+
+
+#include "postscript.h"
+
+#include "tu_file.h"
+#include "utility.h"
+#include <stdarg.h>
+
+
+// Loosely translated into C++ from:
+// -- ps.lua
+// -- lua interface to postscript
+// -- Luiz Henrique de Figueiredo (lhf@csg.uwaterloo.ca)
+// -- 14 May 96
+//
+// From the Lua 4.0.1 distribution, see http://www.lua.org
+
+
+
+postscript::postscript(tu_file* out, const char* title, bool encapsulated)
+	:
+	m_out(out),
+	m_page(0),
+	m_x0(1000),
+	m_x1(0),
+	m_y0(1000),
+	m_y1(0),
+	m_empty(true)	
+// Initialize the file & this struct, etc.
+{
+	assert(m_out != NULL);
+
+	if (title == NULL)
+	{
+		title = "no title";
+	}
+
+	if (encapsulated)
+	{
+		m_out->printf("%%!PS-Adobe-2.0 EPSF-1.2\n");
+	}
+	else
+	{
+		m_out->printf("%%!PS-Adobe 3.0\n");
+	}
+	m_out->printf("%%%%Title: %s\n", title);
+	m_out->printf(
+		"%%%%Creator: postscript.cpp from tu-testbed\n"
+		"%%%%CreationDate: 1 1 2001\n"
+		"%%%%Pages: (atend)\n"
+		"%%%%BoundingBox: (atend)\n"
+		"%%%%EndComments\n"
+		"%%%%BeginProcSet: postscript.cpp\n"
+		"/s { stroke } bind def\n"
+		"/f { fill } bind def\n"
+		"/m { moveto } bind def\n"
+		"/l { lineto } bind def\n"
+		"/L { moveto lineto stroke } bind def\n"
+		"/t { show } bind def\n"
+		"/o { 0 360 arc stroke } bind def\n"
+		"/O { 0 360 arc fill } bind def\n"
+		"/p { 3 0 360 arc fil } bind def\n"
+		"/F { findfont exch scalefont setfont } bind def\n"
+		"/LS { 0 setdash } bind def\n"
+		"/LW { setlinewidth } bind def\n"
+		"%%%%EndProcSet: postscript.cpp\n"
+		"%%%%EndProlog\n"
+		"%%%%BeginSetup\n"
+		"0 setlinewidth\n"
+		"1 setlinejoin\n"
+		"1 setlinecap\n"
+		"10 /Times-Roman F\n"
+		"%%%%EndSetup\n\n"
+		"%%%%Page: 1 1\n");
+}
+
+
+postscript::~postscript()
+// End the Postscript info.
+{
+	m_out->printf(
+		"stroke\n"
+		"showpage\n"
+		"%%%%Trailer\n"
+		"%%%%Pages: %d %d\n"
+		"%%%%BoundingBox: %d %d %d %d\n"
+		"%%%%EOF\n",
+		m_page + 1, m_page + 1,
+		int(m_x0), int(m_y0), int(m_x1), int(m_y1)
+		);
+	
+}
+
+
+void	postscript::clear()
+// New page.
+{
+	if (m_empty) return;
+
+	m_page++;
+	m_out->printf("showpage\n%%%%Page: %d %d\n", m_page + 1, m_page + 1);
+
+	m_empty = true;
+}
+
+
+void	postscript::comment(const char* s)
+// Insert a comment into the output.
+{
+	m_out->printf("%% %s\n", s);
+}
+
+
+void	postscript::rgbcolor(float r, float g, float b)
+// Set the pen color.  Components range from 0 to 1.
+{
+	m_out->printf("%f %f %f setrgbcolor\n", r, g, b);
+}
+
+
+void	postscript::gray(float amount)
+// 0 == black, 1 == white
+{
+	m_out->printf("%f setgray\n", amount);
+}
+
+
+void	postscript::black()
+{
+	rgbcolor(0, 0, 0);
+}
+
+
+void	postscript::line(float x0, float y0, float x1, float y1)
+{
+	m_out->printf(
+		"%f %f %f %f L\n",
+		x1, y1, x0, y0);
+
+	update(x0, y0);
+	update(x1, y1);
+}
+
+
+void	postscript::moveto(float x0, float y0)
+{
+	m_out->printf(
+		"%f %f m\n",
+		x0, y0);
+
+	update(x0, y0);
+}
+
+
+void	postscript::lineto(float x0, float y0)
+{
+	m_out->printf(
+		"%f %f l\n",
+		x0, y0);
+
+	update(x0, y0);
+}
+
+
+void	postscript::linewidth(float w)
+{
+	m_out->printf("%f LW\n", w);
+}
+
+
+// @@ linestyle ?
+
+
+void	postscript::fill()
+{
+	m_out->printf("f\n");
+}
+	
+
+void	postscript::font(const char* name, float size)
+{
+	m_out->printf("%f /%s F\n", size, name);
+}
+
+
+#ifdef _WIN32
+#define vsnprintf	_vsnprintf
+#endif // _WIN32
+
+
+void	postscript::printf(float x, float y, const char* fmt, ...)
+{
+	static const int	BUFFER_SIZE = 1000;
+
+	char	buffer[BUFFER_SIZE];
+
+	va_list ap;
+	va_start(ap, fmt);
+	vsnprintf(buffer, BUFFER_SIZE, fmt, ap);
+	va_end(ap);
+
+	m_out->printf("%f %f m (%s) t\n", x, y, buffer);
+	update(x, y);
+	update(x + 100, y + 10);	// @@ should get bounds of text and update properly!
+}
+
+
+void	postscript::circle(float x, float y, float radius)
+{
+	m_out->printf("%f %f %f o\n", x, y, radius);
+	update(x - radius, y - radius);
+	update(x + radius, y + radius);
+}
+
+
+void	postscript::disk(float x, float y, float radius)
+{
+	m_out->printf("%f %f %f O\n", x, y, radius);
+	update(x - radius, y - radius);
+	update(x + radius, y + radius);
+}
+
+
+void	postscript::dot(float x, float y)
+{
+	m_out->printf("%f %f p\n", x, y);
+	update(x, y);
+}
+
+
+void	postscript::rectangle(float x0, float x1, float y0, float y1)
+{
+	m_out->printf(
+		"%f %f m "
+		"%f %f l "
+		"%f %f l "
+		"%f %f l "
+		"%f %f l s\n",
+		x0, y0,
+		x1, y0,
+		x1, y1,
+		x0, y1,
+		x0, y0);
+	update(x0, y0);
+	update(x1, y1);
+}
+
+
+void	postscript::box(float x0, float x1, float y0, float y1)
+{
+	m_out->printf(
+		"%f %f m "
+		"%f %f l "
+		"%f %f l "
+		"%f %f l f\n",
+		x0, y0,
+		x1, y0,
+		x1, y1,
+		x0, y1);
+	update(x0, y0);
+	update(x1, y1);
+}
+
+
+void	postscript::update(float x, float y)
+// enlarge the bounding box if necessary.
+{
+	if (x < m_x0) m_x0 = floorf(x);
+	if (x > m_x1) m_x1 = ceilf(x);
+	if (y < m_y0) m_y0 = floorf(y);
+	if (y > m_y1) m_y1 = ceilf(y);
+
+	m_empty = false;
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/test_ogl.cpp
diff -u gnash/libbase/test_ogl.cpp:1.1 gnash/libbase/test_ogl.cpp:1.2
--- gnash/libbase/test_ogl.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/test_ogl.cpp	Sun Feb 26 15:49:30 2006
@@ -1,42 +1,42 @@
-// ogl.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// test program for ogl wrapper
-
-
-#include <stdlib.h>
-#include "ogl.h"
-#include <SDL.h>
-
-
-#undef main	// SDL weirdness under WIN32!!
-extern "C" int	main(int argc, char *argv[])
-{
-	if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | \
                SDL_INIT_AUDIO*/))
-	{
-		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
-		exit(1);
-	}
-	atexit(SDL_Quit);
-
-	int	bpp = 24;
-	int	flags = SDL_OPENGL | (0 ? SDL_FULLSCREEN : 0);
-
-	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
-	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
-	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
-
-	// Set the video mode.
-	if (SDL_SetVideoMode(320, 240, bpp, flags) == 0) {
-		fprintf(stderr, "SDL_SetVideoMode() failed.");
-		exit(1);
-	}
-
-	ogl::open();
-
-	return 0;
-}
+// ogl.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// test program for ogl wrapper
+
+
+#include <stdlib.h>
+#include "ogl.h"
+#include <SDL.h>
+
+
+#undef main	// SDL weirdness under WIN32!!
+extern "C" int	main(int argc, char *argv[])
+{
+	if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | \
SDL_INIT_AUDIO*/)) +	{
+		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
+		exit(1);
+	}
+	atexit(SDL_Quit);
+
+	int	bpp = 24;
+	int	flags = SDL_OPENGL | (0 ? SDL_FULLSCREEN : 0);
+
+	SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
+	SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
+	SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
+	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
+	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+
+	// Set the video mode.
+	if (SDL_SetVideoMode(320, 240, bpp, flags) == 0) {
+		fprintf(stderr, "SDL_SetVideoMode() failed.");
+		exit(1);
+	}
+
+	ogl::open();
+
+	return 0;
+}
Index: gnash/libbase/triangulate_float.cpp
diff -u gnash/libbase/triangulate_float.cpp:1.3 \
                gnash/libbase/triangulate_float.cpp:1.4
--- gnash/libbase/triangulate_float.cpp:1.3	Sat Feb 25 03:54:03 2006
+++ gnash/libbase/triangulate_float.cpp	Sun Feb 26 15:49:30 2006
@@ -1,77 +1,77 @@
-// triangulate_float.cpp	-- Thatcher Ulrich 2004
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Code to triangulate arbitrary 2D polygonal regions.
-//
-// Instantiate our templated algo from triangulate_inst.h
-
-#include "triangulate_impl.h"
-
-
-namespace triangulate
-{
-	// Version using float coords
-	void	compute(
-		std::vector<float>* result,	// trilist
-		int path_count,
-		const std::vector<float> paths[],
-		int debug_halt_step /* = -1 */,
-		std::vector<float>* debug_remaining_loop /* = NULL */)
-	{
-		compute_triangulation<float>(result, path_count, paths, debug_halt_step, \
                debug_remaining_loop);
-	}
-}
-
-
-
-#ifdef TEST_TRIANGULATE_FLOAT
-
-// Compile test with something like:
-//
-// gcc -o triangulate_test -I../ triangulate_float.cpp tu_random.cpp \
                -DTEST_TRIANGULATE_FLOAT -lstdc++
-//
-// or
-//
-// cl -Od -Zi -o triangulate_test.exe -I../ triangulate_float.cpp tu_random.cpp \
                -DTEST_TRIANGULATE_FLOAT
-
-
-void	test_square()
-// A very minimal, easy test.
-{
-	std::vector<float>	result;
-	std::vector<std::vector<float> >	paths;
-
-	// Make a square.
-	paths.resize(1);
-	paths[0].push_back(0);
-	paths[0].push_back(0);
-	paths[0].push_back(1);
-	paths[0].push_back(0);
-	paths[0].push_back(1);
-	paths[0].push_back(1);
-	paths[0].push_back(0);
-	paths[0].push_back(1);
-
-	// Triangulate.
-	triangulate::compute(&result, paths.size(), &paths[0]);
-
-	// Dump.
-	for (int i = 0; i < result.size(); i++)
-	{
-		printf("%f\n", result[i]);
-	}
-}
-
-
-int	main()
-{
-	test_square();
-
-	return 0;
-}
-
-
-#endif // TEST_TRIANGULATE_FLOAT
-
+// triangulate_float.cpp	-- Thatcher Ulrich 2004
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Code to triangulate arbitrary 2D polygonal regions.
+//
+// Instantiate our templated algo from triangulate_inst.h
+
+#include "triangulate_impl.h"
+
+
+namespace triangulate
+{
+	// Version using float coords
+	void	compute(
+		std::vector<float>* result,	// trilist
+		int path_count,
+		const std::vector<float> paths[],
+		int debug_halt_step /* = -1 */,
+		std::vector<float>* debug_remaining_loop /* = NULL */)
+	{
+		compute_triangulation<float>(result, path_count, paths, debug_halt_step, \
debug_remaining_loop); +	}
+}
+
+
+
+#ifdef TEST_TRIANGULATE_FLOAT
+
+// Compile test with something like:
+//
+// gcc -o triangulate_test -I../ triangulate_float.cpp tu_random.cpp \
-DTEST_TRIANGULATE_FLOAT -lstdc++ +//
+// or
+//
+// cl -Od -Zi -o triangulate_test.exe -I../ triangulate_float.cpp tu_random.cpp \
-DTEST_TRIANGULATE_FLOAT +
+
+void	test_square()
+// A very minimal, easy test.
+{
+	std::vector<float>	result;
+	std::vector<std::vector<float> >	paths;
+
+	// Make a square.
+	paths.resize(1);
+	paths[0].push_back(0);
+	paths[0].push_back(0);
+	paths[0].push_back(1);
+	paths[0].push_back(0);
+	paths[0].push_back(1);
+	paths[0].push_back(1);
+	paths[0].push_back(0);
+	paths[0].push_back(1);
+
+	// Triangulate.
+	triangulate::compute(&result, paths.size(), &paths[0]);
+
+	// Dump.
+	for (int i = 0; i < result.size(); i++)
+	{
+		printf("%f\n", result[i]);
+	}
+}
+
+
+int	main()
+{
+	test_square();
+
+	return 0;
+}
+
+
+#endif // TEST_TRIANGULATE_FLOAT
+
Index: gnash/libbase/triangulate_sint32.cpp
diff -u gnash/libbase/triangulate_sint32.cpp:1.3 \
                gnash/libbase/triangulate_sint32.cpp:1.4
--- gnash/libbase/triangulate_sint32.cpp:1.3	Sat Feb 25 03:54:03 2006
+++ gnash/libbase/triangulate_sint32.cpp	Sun Feb 26 15:49:30 2006
@@ -1,25 +1,25 @@
-// triangulate_sint32.cpp	-- Thatcher Ulrich 2004
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Code to triangulate arbitrary 2D polygonal regions.
-//
-// Instantiate our templated algo from triangulate_inst.h
-
-#include "triangulate_impl.h"
-
-
-namespace triangulate
-{
-	// Version using sint32 coords
-	void	compute(
-		std::vector<sint32>* result,	// trilist
-		int path_count,
-		const std::vector<sint32> paths[],
-		int debug_halt_step /* = -1 */,
-		std::vector<sint32>* debug_remaining_loop /* = NULL */)
-	{
-		compute_triangulation<sint32>(result, path_count, paths, debug_halt_step, \
                debug_remaining_loop);
-	}
-}
+// triangulate_sint32.cpp	-- Thatcher Ulrich 2004
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Code to triangulate arbitrary 2D polygonal regions.
+//
+// Instantiate our templated algo from triangulate_inst.h
+
+#include "triangulate_impl.h"
+
+
+namespace triangulate
+{
+	// Version using sint32 coords
+	void	compute(
+		std::vector<sint32>* result,	// trilist
+		int path_count,
+		const std::vector<sint32> paths[],
+		int debug_halt_step /* = -1 */,
+		std::vector<sint32>* debug_remaining_loop /* = NULL */)
+	{
+		compute_triangulation<sint32>(result, path_count, paths, debug_halt_step, \
debug_remaining_loop); +	}
+}
Index: gnash/libbase/tu_file.cpp
diff -u gnash/libbase/tu_file.cpp:1.1 gnash/libbase/tu_file.cpp:1.2
--- gnash/libbase/tu_file.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_file.cpp	Sun Feb 26 15:49:30 2006
@@ -1,540 +1,540 @@
-// tu_file.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// A file class that can be customized with callbacks.
-
-
-#include "tu_file.h"
-#include "utility.h"
-#include "container.h"
-#include "membuf.h"
-
-
-//
-// tu_file functions using FILE
-//
-
-
-static int std_read_func(void* dst, int bytes, void* appdata) 
-// Return the number of bytes actually read.  EOF or an error would
-// cause that to not be equal to "bytes".
-{
-	assert(appdata);
-	assert(dst);
-	return fread( dst, 1, bytes, (FILE *)appdata );
-}
-
-static int std_write_func(const void* src, int bytes, void* appdata)
-// Return the number of bytes actually written.
-{
-	assert(appdata);
-	assert(src);
-	return fwrite( src, 1, bytes, (FILE *)appdata );
-}
-
-static int std_seek_func(int pos, void *appdata)
-// Return 0 on success, or TU_FILE_SEEK_ERROR on failure.
-{
-	assert(appdata);
-	clearerr((FILE*) appdata);	// make sure EOF flag is cleared.
-	int	result = fseek((FILE*)appdata, pos, SEEK_SET);
-	if (result == EOF)
-	{
-		// @@ TODO should set m_error to something relevant based on errno.
-		return TU_FILE_SEEK_ERROR;
-	}
-	return 0;
-}
-
-static int std_seek_to_end_func(void *appdata)
-// Return 0 on success, TU_FILE_SEEK_ERROR on failure.
-{
-	assert(appdata);
-	int	result = fseek((FILE*)appdata, 0, SEEK_END);
-	if (result == EOF)
-	{
-		// @@ TODO should set m_error to something relevant based on errno.
-		return TU_FILE_SEEK_ERROR;
-	}
-	return 0;
-}
-
-static int std_tell_func(const void *appdata)
-// Return the file position, or -1 on failure.
-{
-	assert(appdata);
-	return ftell((FILE*)appdata);
-}
-
-static bool std_get_eof_func(void *appdata)
-// Return true if we're at EOF.
-{
-	assert(appdata);
-	if (feof((FILE*) appdata))
-	{
-		return true;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-static int std_close_func(void *appdata)
-// Return 0 on success, or TU_FILE_CLOSE_ERROR on failure.
-{
-	assert(appdata);
-	int	result = fclose((FILE*)appdata);
-	if (result == EOF)
-	{
-		// @@ TODO should set m_error to something relevant based on errno.
-		return TU_FILE_CLOSE_ERROR;
-	}
-	return 0;
-}
-
-
-//
-// tu_file functions using a readable/writable memory buffer
-//
-
-
-struct filebuf
-{
-	membuf m_;
-	int	m_position;
-	bool	m_read_only;
-
-	filebuf()
-		:
-		m_position(0),
-		m_read_only(false)
-	{
-	}
-
-	filebuf(int size, void* data)
-		:
-		m_(membuf::READ_ONLY, data, size),
-		m_position(0),
-		m_read_only(true)
-	{
-	}
-
-	~filebuf()
-	{
-	}
-
-	bool	resize(int new_size)
-	// Return false if we couldn't resize.
-	{
-		if (m_read_only) return false;
-
-		m_.resize(new_size);
-
-		// Hm, does this make sense?  We're truncating the file, so clamping the cursor.
-		// Alternative would be to disallow resize, but that doesn't seem good either.
-		if (m_position > m_.size())
-		{
-			m_position = m_.size();
-		}
-
-		return true;
-	}
-
-	bool	is_valid()
-	{
-		return
-			m_position >= 0
-			&& m_position <= m_.size();
-	}
-
-	unsigned char*	get_cursor() { return ((unsigned char*) m_.data()) + m_position; }
-};
-
-
-static int mem_read_func(void* dst, int bytes, void* appdata) 
-// Return the number of bytes actually read.  EOF or an error would
-// cause that to not be equal to "bytes".
-{
-	assert(appdata);
-	assert(dst);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	int	bytes_to_read = imin(bytes, buf->m_.size() - buf->m_position);
-	if (bytes_to_read)
-	{
-		memcpy(dst, buf->get_cursor(), bytes_to_read);
-	}
-	buf->m_position += bytes_to_read;
-
-	return bytes_to_read;
-}
-
-
-static int mem_write_func(const void* src, int bytes, void* appdata)
-// Return the number of bytes actually written.
-{
-	assert(appdata);
-	assert(src);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	// Expand buffer if necessary.
-	int	bytes_to_expand = imax(0, buf->m_position + bytes - buf->m_.size());
-	if (bytes_to_expand)
-	{
-		if (buf->resize(buf->m_.size() + bytes_to_expand) == false)
-		{
-			// Couldn't expand!
-			return 0;
-		}
-	}
-
-	memcpy(buf->get_cursor(), src, bytes);
-	buf->m_position += bytes;
-
-	return bytes;
-}
-
-static int mem_seek_func(int pos, void *appdata)
-// Return 0 on success, or TU_FILE_SEEK_ERROR on failure.
-{
-	assert(appdata);
-	assert(pos >= 0);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	if (pos < 0)
-	{
-		buf->m_position = 0;
-		return TU_FILE_SEEK_ERROR;
-	}
-
-	if (pos > buf->m_.size())
-	{
-		buf->m_position = buf->m_.size();
-		return TU_FILE_SEEK_ERROR;
-	}
-
-	buf->m_position = pos;
-	return 0;
-}
-
-static int mem_seek_to_end_func(void* appdata)
-// Return 0 on success, TU_FILE_SEEK_ERROR on failure.
-{
-	assert(appdata);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	buf->m_position = buf->m_.size();
-	return 0;
-}
-
-static int mem_tell_func(const void* appdata)
-// Return the file position, or -1 on failure.
-{
-	assert(appdata);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	return buf->m_position;
-}
-
-static bool	mem_get_eof_func(void* appdata)
-// Return true if we're positioned at the end of the buffer.
-{
-	assert(appdata);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	return buf->m_position >= buf->m_.size();
-}
-
-static int mem_close_func(void* appdata)
-// Return 0 on success, or TU_FILE_CLOSE_ERROR on failure.
-{
-	assert(appdata);
-
-	filebuf* buf = (filebuf*) appdata;
-	assert(buf->is_valid());
-
-	delete buf;
-
-	return 0;
-}
-
-
-//
-// generic functionality
-//
-
-
-tu_file::tu_file(
-	void * appdata,
-	read_func rf,
-	write_func wf,
-	seek_func sf,
-	seek_to_end_func ef,
-	tell_func tf,
-	get_eof_func gef,
-	close_func cf)
-// Create a file using the custom callbacks.
-{
-	m_data = appdata;
-	m_read = rf;
-	m_write = wf;
-	m_seek = sf;
-	m_seek_to_end = ef;
-	m_tell = tf;
-	m_get_eof = gef;
-	m_close = cf;
-	m_error = TU_FILE_NO_ERROR;
-}
-
-
-tu_file::tu_file(FILE* fp, bool autoclose=false)
-// Create a file from a standard file pointer.
-{
-	m_data = (void *)fp;
-	m_read = std_read_func;
-	m_write = std_write_func;
-	m_seek = std_seek_func;
-	m_seek_to_end = std_seek_to_end_func;
-	m_tell = std_tell_func;
-	m_get_eof = std_get_eof_func;
-	m_close = autoclose ? std_close_func : NULL;
-	m_error = TU_FILE_NO_ERROR;
-}
-
-
-tu_file::tu_file(const char * name, const char * mode)
-// Create a file from the given name and the given mode.
-{
-	m_data = fopen(name, mode);
-	if (m_data)
-	{
-		m_read = std_read_func;
-		m_write = std_write_func;
-		m_seek = std_seek_func;
-		m_seek_to_end = std_seek_to_end_func;
-		m_tell = std_tell_func;
-		m_get_eof = std_get_eof_func;
-		m_close = std_close_func;
-		m_error = TU_FILE_NO_ERROR;
-	}
-	else 
-	{
-		m_read = NULL;
-		m_write = NULL;
-		m_seek = NULL;
-		m_seek_to_end = NULL;
-		m_tell = NULL;
-		m_get_eof = NULL;
-		m_close = NULL;
-		m_error = TU_FILE_OPEN_ERROR;
-	}
-}
-
-
-tu_file::tu_file(memory_buffer_enum m)
-// Create a read/write memory buffer.
-{
-	m_data = new membuf;
-
-	m_read = mem_read_func;
-	m_write = mem_write_func;
-	m_seek = mem_seek_func;
-	m_seek_to_end = mem_seek_to_end_func;
-	m_tell = mem_tell_func;
-	m_get_eof = mem_get_eof_func;
-	m_close = mem_close_func;
-	m_error = TU_FILE_NO_ERROR;
-}
-
-
-tu_file::tu_file(memory_buffer_enum m, int size, void* data)
-// Create a read-only memory buffer, using the given data.
-{
-	m_data = new membuf(data, size);
-
-	m_read = mem_read_func;
-	m_write = mem_write_func;
-	m_seek = mem_seek_func;
-	m_seek_to_end = mem_seek_to_end_func;
-	m_tell = mem_tell_func;
-	m_get_eof = mem_get_eof_func;
-	m_close = mem_close_func;
-	m_error = TU_FILE_NO_ERROR;
-}
-
-
-tu_file::~tu_file()
-// Close this file when destroyed.
-{
-	close();
-}
-
-
-void tu_file::close() 
-// Close this file.
-{ 
-	if (m_close)
-	{
-		m_close(m_data);
-	}
-	m_data = NULL; 
-	m_read = NULL; 
-	m_write = NULL; 
-	m_seek = NULL; 
-	m_tell = NULL; 
-	m_close = NULL; 
-}
-
-
-void	tu_file::copy_from(tu_file* src)
-// Copy remaining contents of *src into *this.
-{
-	// @@ bah, should buffer this!
-	while (src->get_eof() == false)
-	{
-		Uint8	b = src->read8();
-		if (src->get_error())
-		{
-			break;
-		}
-
-		write8(b);
-	}
-}
-
-
-void	tu_file::copy_to(membuf* dst)
-// Copy remaining contents of *this into *dst.
-{
-	static const int BUFSIZE = 4096;
-	
-	while (get_eof() == false)
-	{
-		// Make room at the end of dst.
-		dst->resize(dst->size() + BUFSIZE);
-		int bytes_read = read_bytes(((char*) dst->data()) + dst->size() - BUFSIZE, \
                BUFSIZE);
-		if (bytes_read < BUFSIZE) {
-			// Didn't use everything we allocated; trim the unused bytes.
-			dst->resize(dst->size() - (BUFSIZE - bytes_read));
-		}
-
-		if (get_error())
-		{
-			break;
-		}
-	}
-}
-
-
-int	tu_file::copy_bytes(tu_file* src, int byte_count)
-// Copy a fixed number of bytes from *src into *this.  Return the
-// number of bytes copied.
-{
-	static const int	BUFSIZE = 4096;
-	char	buffer[BUFSIZE];
-
-	int	bytes_left = byte_count;
-	while (bytes_left)
-	{
-		int	to_copy = imin(bytes_left, BUFSIZE);
-
-		int	read_count = src->read_bytes(buffer, to_copy);
-		int	write_count = write_bytes(buffer, read_count);
-
-		assert(write_count <= read_count);
-		assert(read_count <= to_copy);
-		assert(to_copy <= bytes_left);
-
-		bytes_left -= write_count;
-		if (write_count < to_copy)
-		{
-			// Some kind of error; abort.
-			return byte_count - bytes_left;
-		}
-	}
-
-	assert(bytes_left == 0);
-
-	return byte_count;
-}
-
-
-void tu_file::write_string(const char* src)
-{
-	for (;;)
-	{
-		write8(*src);
-		if (*src == 0)
-		{
-			break;
-		}
-		src++;
-	}
-}
-
-
-int tu_file::read_string(char* dst, int max_length) 
-{
-	int i=0;
-	while (i<max_length)
-	{
-		dst[i] = read8();
-		if (dst[i]=='\0')
-		{
-			return i;
-		}
-		i++;
-	}
-
-	dst[max_length - 1] = 0;	// force termination.
-
-	return -1;
-}
-
-
-
-#include <stdarg.h>
-#include <string.h>
-
-#ifdef _WIN32
-#define vsnprintf	_vsnprintf
-#endif // _WIN32
-
-
-int	tu_file::printf(const char* fmt, ...)
-// Use printf-like semantics to send output to this stream.
-{
-	// Workspace for vsnprintf formatting.
-	static const int	BUFFER_SIZE = 1000;
-	char	buffer[BUFFER_SIZE];
-
-	va_list ap;
-	va_start(ap, fmt);
-	vsnprintf(buffer, BUFFER_SIZE, fmt, ap);
-	va_end(ap);
-
-	return write_bytes(buffer, strlen(buffer));
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// tu_file.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// A file class that can be customized with callbacks.
+
+
+#include "tu_file.h"
+#include "utility.h"
+#include "container.h"
+#include "membuf.h"
+
+
+//
+// tu_file functions using FILE
+//
+
+
+static int std_read_func(void* dst, int bytes, void* appdata) 
+// Return the number of bytes actually read.  EOF or an error would
+// cause that to not be equal to "bytes".
+{
+	assert(appdata);
+	assert(dst);
+	return fread( dst, 1, bytes, (FILE *)appdata );
+}
+
+static int std_write_func(const void* src, int bytes, void* appdata)
+// Return the number of bytes actually written.
+{
+	assert(appdata);
+	assert(src);
+	return fwrite( src, 1, bytes, (FILE *)appdata );
+}
+
+static int std_seek_func(int pos, void *appdata)
+// Return 0 on success, or TU_FILE_SEEK_ERROR on failure.
+{
+	assert(appdata);
+	clearerr((FILE*) appdata);	// make sure EOF flag is cleared.
+	int	result = fseek((FILE*)appdata, pos, SEEK_SET);
+	if (result == EOF)
+	{
+		// @@ TODO should set m_error to something relevant based on errno.
+		return TU_FILE_SEEK_ERROR;
+	}
+	return 0;
+}
+
+static int std_seek_to_end_func(void *appdata)
+// Return 0 on success, TU_FILE_SEEK_ERROR on failure.
+{
+	assert(appdata);
+	int	result = fseek((FILE*)appdata, 0, SEEK_END);
+	if (result == EOF)
+	{
+		// @@ TODO should set m_error to something relevant based on errno.
+		return TU_FILE_SEEK_ERROR;
+	}
+	return 0;
+}
+
+static int std_tell_func(const void *appdata)
+// Return the file position, or -1 on failure.
+{
+	assert(appdata);
+	return ftell((FILE*)appdata);
+}
+
+static bool std_get_eof_func(void *appdata)
+// Return true if we're at EOF.
+{
+	assert(appdata);
+	if (feof((FILE*) appdata))
+	{
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+static int std_close_func(void *appdata)
+// Return 0 on success, or TU_FILE_CLOSE_ERROR on failure.
+{
+	assert(appdata);
+	int	result = fclose((FILE*)appdata);
+	if (result == EOF)
+	{
+		// @@ TODO should set m_error to something relevant based on errno.
+		return TU_FILE_CLOSE_ERROR;
+	}
+	return 0;
+}
+
+
+//
+// tu_file functions using a readable/writable memory buffer
+//
+
+
+struct filebuf
+{
+	membuf m_;
+	int	m_position;
+	bool	m_read_only;
+
+	filebuf()
+		:
+		m_position(0),
+		m_read_only(false)
+	{
+	}
+
+	filebuf(int size, void* data)
+		:
+		m_(membuf::READ_ONLY, data, size),
+		m_position(0),
+		m_read_only(true)
+	{
+	}
+
+	~filebuf()
+	{
+	}
+
+	bool	resize(int new_size)
+	// Return false if we couldn't resize.
+	{
+		if (m_read_only) return false;
+
+		m_.resize(new_size);
+
+		// Hm, does this make sense?  We're truncating the file, so clamping the cursor.
+		// Alternative would be to disallow resize, but that doesn't seem good either.
+		if (m_position > m_.size())
+		{
+			m_position = m_.size();
+		}
+
+		return true;
+	}
+
+	bool	is_valid()
+	{
+		return
+			m_position >= 0
+			&& m_position <= m_.size();
+	}
+
+	unsigned char*	get_cursor() { return ((unsigned char*) m_.data()) + m_position; }
+};
+
+
+static int mem_read_func(void* dst, int bytes, void* appdata) 
+// Return the number of bytes actually read.  EOF or an error would
+// cause that to not be equal to "bytes".
+{
+	assert(appdata);
+	assert(dst);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	int	bytes_to_read = imin(bytes, buf->m_.size() - buf->m_position);
+	if (bytes_to_read)
+	{
+		memcpy(dst, buf->get_cursor(), bytes_to_read);
+	}
+	buf->m_position += bytes_to_read;
+
+	return bytes_to_read;
+}
+
+
+static int mem_write_func(const void* src, int bytes, void* appdata)
+// Return the number of bytes actually written.
+{
+	assert(appdata);
+	assert(src);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	// Expand buffer if necessary.
+	int	bytes_to_expand = imax(0, buf->m_position + bytes - buf->m_.size());
+	if (bytes_to_expand)
+	{
+		if (buf->resize(buf->m_.size() + bytes_to_expand) == false)
+		{
+			// Couldn't expand!
+			return 0;
+		}
+	}
+
+	memcpy(buf->get_cursor(), src, bytes);
+	buf->m_position += bytes;
+
+	return bytes;
+}
+
+static int mem_seek_func(int pos, void *appdata)
+// Return 0 on success, or TU_FILE_SEEK_ERROR on failure.
+{
+	assert(appdata);
+	assert(pos >= 0);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	if (pos < 0)
+	{
+		buf->m_position = 0;
+		return TU_FILE_SEEK_ERROR;
+	}
+
+	if (pos > buf->m_.size())
+	{
+		buf->m_position = buf->m_.size();
+		return TU_FILE_SEEK_ERROR;
+	}
+
+	buf->m_position = pos;
+	return 0;
+}
+
+static int mem_seek_to_end_func(void* appdata)
+// Return 0 on success, TU_FILE_SEEK_ERROR on failure.
+{
+	assert(appdata);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	buf->m_position = buf->m_.size();
+	return 0;
+}
+
+static int mem_tell_func(const void* appdata)
+// Return the file position, or -1 on failure.
+{
+	assert(appdata);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	return buf->m_position;
+}
+
+static bool	mem_get_eof_func(void* appdata)
+// Return true if we're positioned at the end of the buffer.
+{
+	assert(appdata);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	return buf->m_position >= buf->m_.size();
+}
+
+static int mem_close_func(void* appdata)
+// Return 0 on success, or TU_FILE_CLOSE_ERROR on failure.
+{
+	assert(appdata);
+
+	filebuf* buf = (filebuf*) appdata;
+	assert(buf->is_valid());
+
+	delete buf;
+
+	return 0;
+}
+
+
+//
+// generic functionality
+//
+
+
+tu_file::tu_file(
+	void * appdata,
+	read_func rf,
+	write_func wf,
+	seek_func sf,
+	seek_to_end_func ef,
+	tell_func tf,
+	get_eof_func gef,
+	close_func cf)
+// Create a file using the custom callbacks.
+{
+	m_data = appdata;
+	m_read = rf;
+	m_write = wf;
+	m_seek = sf;
+	m_seek_to_end = ef;
+	m_tell = tf;
+	m_get_eof = gef;
+	m_close = cf;
+	m_error = TU_FILE_NO_ERROR;
+}
+
+
+tu_file::tu_file(FILE* fp, bool autoclose=false)
+// Create a file from a standard file pointer.
+{
+	m_data = (void *)fp;
+	m_read = std_read_func;
+	m_write = std_write_func;
+	m_seek = std_seek_func;
+	m_seek_to_end = std_seek_to_end_func;
+	m_tell = std_tell_func;
+	m_get_eof = std_get_eof_func;
+	m_close = autoclose ? std_close_func : NULL;
+	m_error = TU_FILE_NO_ERROR;
+}
+
+
+tu_file::tu_file(const char * name, const char * mode)
+// Create a file from the given name and the given mode.
+{
+	m_data = fopen(name, mode);
+	if (m_data)
+	{
+		m_read = std_read_func;
+		m_write = std_write_func;
+		m_seek = std_seek_func;
+		m_seek_to_end = std_seek_to_end_func;
+		m_tell = std_tell_func;
+		m_get_eof = std_get_eof_func;
+		m_close = std_close_func;
+		m_error = TU_FILE_NO_ERROR;
+	}
+	else 
+	{
+		m_read = NULL;
+		m_write = NULL;
+		m_seek = NULL;
+		m_seek_to_end = NULL;
+		m_tell = NULL;
+		m_get_eof = NULL;
+		m_close = NULL;
+		m_error = TU_FILE_OPEN_ERROR;
+	}
+}
+
+
+tu_file::tu_file(memory_buffer_enum m)
+// Create a read/write memory buffer.
+{
+	m_data = new membuf;
+
+	m_read = mem_read_func;
+	m_write = mem_write_func;
+	m_seek = mem_seek_func;
+	m_seek_to_end = mem_seek_to_end_func;
+	m_tell = mem_tell_func;
+	m_get_eof = mem_get_eof_func;
+	m_close = mem_close_func;
+	m_error = TU_FILE_NO_ERROR;
+}
+
+
+tu_file::tu_file(memory_buffer_enum m, int size, void* data)
+// Create a read-only memory buffer, using the given data.
+{
+	m_data = new membuf(data, size);
+
+	m_read = mem_read_func;
+	m_write = mem_write_func;
+	m_seek = mem_seek_func;
+	m_seek_to_end = mem_seek_to_end_func;
+	m_tell = mem_tell_func;
+	m_get_eof = mem_get_eof_func;
+	m_close = mem_close_func;
+	m_error = TU_FILE_NO_ERROR;
+}
+
+
+tu_file::~tu_file()
+// Close this file when destroyed.
+{
+	close();
+}
+
+
+void tu_file::close() 
+// Close this file.
+{ 
+	if (m_close)
+	{
+		m_close(m_data);
+	}
+	m_data = NULL; 
+	m_read = NULL; 
+	m_write = NULL; 
+	m_seek = NULL; 
+	m_tell = NULL; 
+	m_close = NULL; 
+}
+
+
+void	tu_file::copy_from(tu_file* src)
+// Copy remaining contents of *src into *this.
+{
+	// @@ bah, should buffer this!
+	while (src->get_eof() == false)
+	{
+		Uint8	b = src->read8();
+		if (src->get_error())
+		{
+			break;
+		}
+
+		write8(b);
+	}
+}
+
+
+void	tu_file::copy_to(membuf* dst)
+// Copy remaining contents of *this into *dst.
+{
+	static const int BUFSIZE = 4096;
+	
+	while (get_eof() == false)
+	{
+		// Make room at the end of dst.
+		dst->resize(dst->size() + BUFSIZE);
+		int bytes_read = read_bytes(((char*) dst->data()) + dst->size() - BUFSIZE, \
BUFSIZE); +		if (bytes_read < BUFSIZE) {
+			// Didn't use everything we allocated; trim the unused bytes.
+			dst->resize(dst->size() - (BUFSIZE - bytes_read));
+		}
+
+		if (get_error())
+		{
+			break;
+		}
+	}
+}
+
+
+int	tu_file::copy_bytes(tu_file* src, int byte_count)
+// Copy a fixed number of bytes from *src into *this.  Return the
+// number of bytes copied.
+{
+	static const int	BUFSIZE = 4096;
+	char	buffer[BUFSIZE];
+
+	int	bytes_left = byte_count;
+	while (bytes_left)
+	{
+		int	to_copy = imin(bytes_left, BUFSIZE);
+
+		int	read_count = src->read_bytes(buffer, to_copy);
+		int	write_count = write_bytes(buffer, read_count);
+
+		assert(write_count <= read_count);
+		assert(read_count <= to_copy);
+		assert(to_copy <= bytes_left);
+
+		bytes_left -= write_count;
+		if (write_count < to_copy)
+		{
+			// Some kind of error; abort.
+			return byte_count - bytes_left;
+		}
+	}
+
+	assert(bytes_left == 0);
+
+	return byte_count;
+}
+
+
+void tu_file::write_string(const char* src)
+{
+	for (;;)
+	{
+		write8(*src);
+		if (*src == 0)
+		{
+			break;
+		}
+		src++;
+	}
+}
+
+
+int tu_file::read_string(char* dst, int max_length) 
+{
+	int i=0;
+	while (i<max_length)
+	{
+		dst[i] = read8();
+		if (dst[i]=='\0')
+		{
+			return i;
+		}
+		i++;
+	}
+
+	dst[max_length - 1] = 0;	// force termination.
+
+	return -1;
+}
+
+
+
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef _WIN32
+#define vsnprintf	_vsnprintf
+#endif // _WIN32
+
+
+int	tu_file::printf(const char* fmt, ...)
+// Use printf-like semantics to send output to this stream.
+{
+	// Workspace for vsnprintf formatting.
+	static const int	BUFFER_SIZE = 1000;
+	char	buffer[BUFFER_SIZE];
+
+	va_list ap;
+	va_start(ap, fmt);
+	vsnprintf(buffer, BUFFER_SIZE, fmt, ap);
+	va_end(ap);
+
+	return write_bytes(buffer, strlen(buffer));
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/tu_file_SDL.cpp
diff -u gnash/libbase/tu_file_SDL.cpp:1.1 gnash/libbase/tu_file_SDL.cpp:1.2
--- gnash/libbase/tu_file_SDL.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_file_SDL.cpp	Sun Feb 26 15:49:30 2006
@@ -1,120 +1,120 @@
-// tu_file_SDL.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// tu_file constructor, for creating a tu_file from an SDL_RWops*
-// stream.  In its own source file so that if clients of the base
-// library don't call it, it won't get pulled in by the linker and
-// won't try to link with SDL.
-
-
-#include "tu_file.h"
-#include "utility.h"
-#include <SDL.h>
-
-
-// TODO: add error detection and reporting!!!
-
-static int sdl_read_func(void* dst, int bytes, void* appdata) 
-{
-	assert(dst);
-	assert(appdata);
-	int	result = SDL_RWread((SDL_RWops*) appdata, dst, 1, bytes);
-	if (result == -1)
-	{
-		// @@ set appdata->m_error?
-		return 0;
-	}
-	return result;
-}
-
-static int sdl_write_func(const void* src, int bytes, void* appdata)
-{
-	assert(src);
-	assert(appdata);
-	int	result = SDL_RWwrite((SDL_RWops*) appdata, src, 1, bytes);
-	if (result == -1)
-	{
-		// @@ set m_errer?
-		return 0;
-	}
-	return result;
-}
-
-static int sdl_seek_func(int pos, void *appdata)
-{
-	assert(pos >= 0);
-	assert(appdata);
-	return SDL_RWseek((SDL_RWops*) appdata, pos, SEEK_SET);
-}
-
-static int sdl_seek_to_end_func(void *appdata)
-{
-	assert(appdata);
-	return SDL_RWseek((SDL_RWops*) appdata, 0, SEEK_END);
-}
-
-static int sdl_tell_func(const void *appdata)
-{
-	assert(appdata);
-	return SDL_RWtell((SDL_RWops*) appdata);
-}
-
-static bool sdl_get_eof_func(void* appdata)
-{
-	assert(appdata);
-
-	int	cur_pos = sdl_tell_func(appdata);
-	sdl_seek_to_end_func(appdata);
-	int	end_pos = sdl_tell_func(appdata);
-	if (end_pos <= cur_pos)
-	{
-		return true;
-	}
-	else
-	{
-		sdl_seek_func(cur_pos, appdata);
-		return false;
-	}
-}
-
-static int sdl_close_func(void *appdata)
-{
-	assert(appdata);
-	int	result = SDL_RWclose((SDL_RWops*) appdata);
-	if (result != 0)
-	{
-		return TU_FILE_CLOSE_ERROR;
-	}
-	return 0;
-}
-
-	
-tu_file::tu_file(SDL_RWops* sdl_stream, bool autoclose)
-// Create a tu_file object that can be used to read/write stuff.  Use
-// an SDL_RWops* as the underlying implementation.
-//
-// If autoclose is true, then the sdl_stream has SDL_RWclose()
-// called on it when the resulting file object is destructed.
-{
-	assert(sdl_stream);
-
-	m_data = (void*) sdl_stream;
-	m_read = sdl_read_func;
-	m_write = sdl_write_func;
-	m_seek = sdl_seek_func;
-	m_seek_to_end = sdl_seek_to_end_func;
-	m_tell = sdl_tell_func;
-	m_get_eof = sdl_get_eof_func;
-	m_close = autoclose ? sdl_close_func : NULL;
-	m_error = TU_FILE_NO_ERROR;
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// tu_file_SDL.cpp	-- Ignacio Castaño, Thatcher Ulrich <tu@tulrich.com> 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// tu_file constructor, for creating a tu_file from an SDL_RWops*
+// stream.  In its own source file so that if clients of the base
+// library don't call it, it won't get pulled in by the linker and
+// won't try to link with SDL.
+
+
+#include "tu_file.h"
+#include "utility.h"
+#include <SDL.h>
+
+
+// TODO: add error detection and reporting!!!
+
+static int sdl_read_func(void* dst, int bytes, void* appdata) 
+{
+	assert(dst);
+	assert(appdata);
+	int	result = SDL_RWread((SDL_RWops*) appdata, dst, 1, bytes);
+	if (result == -1)
+	{
+		// @@ set appdata->m_error?
+		return 0;
+	}
+	return result;
+}
+
+static int sdl_write_func(const void* src, int bytes, void* appdata)
+{
+	assert(src);
+	assert(appdata);
+	int	result = SDL_RWwrite((SDL_RWops*) appdata, src, 1, bytes);
+	if (result == -1)
+	{
+		// @@ set m_errer?
+		return 0;
+	}
+	return result;
+}
+
+static int sdl_seek_func(int pos, void *appdata)
+{
+	assert(pos >= 0);
+	assert(appdata);
+	return SDL_RWseek((SDL_RWops*) appdata, pos, SEEK_SET);
+}
+
+static int sdl_seek_to_end_func(void *appdata)
+{
+	assert(appdata);
+	return SDL_RWseek((SDL_RWops*) appdata, 0, SEEK_END);
+}
+
+static int sdl_tell_func(const void *appdata)
+{
+	assert(appdata);
+	return SDL_RWtell((SDL_RWops*) appdata);
+}
+
+static bool sdl_get_eof_func(void* appdata)
+{
+	assert(appdata);
+
+	int	cur_pos = sdl_tell_func(appdata);
+	sdl_seek_to_end_func(appdata);
+	int	end_pos = sdl_tell_func(appdata);
+	if (end_pos <= cur_pos)
+	{
+		return true;
+	}
+	else
+	{
+		sdl_seek_func(cur_pos, appdata);
+		return false;
+	}
+}
+
+static int sdl_close_func(void *appdata)
+{
+	assert(appdata);
+	int	result = SDL_RWclose((SDL_RWops*) appdata);
+	if (result != 0)
+	{
+		return TU_FILE_CLOSE_ERROR;
+	}
+	return 0;
+}
+
+	
+tu_file::tu_file(SDL_RWops* sdl_stream, bool autoclose)
+// Create a tu_file object that can be used to read/write stuff.  Use
+// an SDL_RWops* as the underlying implementation.
+//
+// If autoclose is true, then the sdl_stream has SDL_RWclose()
+// called on it when the resulting file object is destructed.
+{
+	assert(sdl_stream);
+
+	m_data = (void*) sdl_stream;
+	m_read = sdl_read_func;
+	m_write = sdl_write_func;
+	m_seek = sdl_seek_func;
+	m_seek_to_end = sdl_seek_to_end_func;
+	m_tell = sdl_tell_func;
+	m_get_eof = sdl_get_eof_func;
+	m_close = autoclose ? sdl_close_func : NULL;
+	m_error = TU_FILE_NO_ERROR;
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/tu_random.cpp
diff -u gnash/libbase/tu_random.cpp:1.1 gnash/libbase/tu_random.cpp:1.2
--- gnash/libbase/tu_random.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_random.cpp	Sun Feb 26 15:49:30 2006
@@ -1,150 +1,150 @@
-// tu_random.cpp	-- Thatcher Ulrich 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Pseudorandom number generator.
-
-
-#include "tu_random.h"
-
-
-namespace tu_random
-{
-	// Global generator.
-	static generator	s_generator;
-
-	Uint32	next_random()
-	{
-		return s_generator.next_random();
-	}
-
-	void	seed_random(Uint32 seed)
-	{
-		s_generator.seed_random(seed);
-	}
-
-	float	get_unit_float()
-	{
-		return s_generator.get_unit_float();
-	}
-
-
-	// PRNG code adapted from the complimentary-multiply-with-carry
-	// code in the article: George Marsaglia, "Seeds for Random Number
-	// Generators", Communications of the ACM, May 2003, Vol 46 No 5,
-	// pp90-93.
-	//
-	// The article says:
-	//
-	// "Any one of the choices for seed table size and multiplier will
-	// provide a RNG that has passed extensive tests of randomness,
-	// particularly those in [3], yet is simple and fast --
-	// approximately 30 million random 32-bit integers per second on a
-	// 850MHz PC.  The period is a*b^n, where a is the multiplier, n
-	// the size of the seed table and b=2^32-1.  (a is chosen so that
-	// b is a primitive root of the prime a*b^n + 1.)"
-	//
-	// [3] Marsaglia, G., Zaman, A., and Tsang, W.  Toward a universal
-	// random number generator.  _Statistics and Probability Letters
-	// 8_ (1990), 35-39.
-
-//	const Uint64	a = 123471786;	// for SEED_COUNT=1024
-//	const Uint64	a = 123554632;	// for SEED_COUNT=512
-//	const Uint64	a = 8001634;	// for SEED_COUNT=255
-//	const Uint64	a = 8007626;	// for SEED_COUNT=128
-//	const Uint64	a = 647535442;	// for SEED_COUNT=64
-//	const Uint64	a = 547416522;	// for SEED_COUNT=32
-//	const Uint64	a = 487198574;	// for SEED_COUNT=16
-	const Uint64	a = 716514398;	// for SEED_COUNT=8
-
-
-	generator::generator()
-		:
-		c(362436),
-		i(SEED_COUNT - 1)
-	{
-		seed_random(987654321);
-	}
-
-
-	void	generator::seed_random(Uint32 seed)
-	{
-		// Simple pseudo-random to reseed the seeds.
-		// Suggested by the above article.
-		Uint32	j = seed;
-		for (int i = 0; i < SEED_COUNT; i++)
-		{
-			j = j ^ (j << 13);
-			j = j ^ (j >> 17);
-			j = j ^ (j << 5);
-			Q[i] = j;
-		}
-	}
-
-
-	Uint32	generator::next_random()
-	// Return the next pseudo-random number in the sequence.
-	{
-		Uint64	t;
-		Uint32	x;
-
-		//static Uint32	c = 362436;
-		//static Uint32	i = SEED_COUNT - 1;
-		const Uint32	r = 0xFFFFFFFE;
-
-		i = (i+1) & (SEED_COUNT - 1);
-		t = a * Q[i] + c;
-		c = (Uint32) (t >> 32);
-		x = (Uint32) (t + c);
-		if (x < c)
-		{
-			x++;
-			c++;
-		}
-		
-		Uint32	val = r - x;
-		Q[i] = val;
-		return val;
-	}
-
-	
-	float	generator::get_unit_float()
-	{
-		Uint32	r = next_random();
-
-		// 24 bits of precision.
-		return float(r >> 8) / (16777216.0f - 1.0f);
-	}
-
-}	// end namespace tu_random
-
-
-#ifdef TEST_TU_RANDOM
-
-// Compile with e.g.:
-//
-//  gcc -o tu_random_test tu_random.cpp -I.. -g -DTEST_TU_RANDOM -lstdc++
-//
-// Generate a test file of random numbers for DIEHARD.
-int	main()
-{
-	const int	COUNT = 15000000 / 4;	// number of 4-byte words; DIEHARD needs ~80M bits
-
-	for (int i = 0; i < COUNT; i++)
-	{
-		Uint32	val = tu_random::next_random();
-		fwrite(&val, sizeof(val), 1, stdout);
-	}
-}
-
-
-#endif // TEST_TU_RANDOM
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// tu_random.cpp	-- Thatcher Ulrich 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Pseudorandom number generator.
+
+
+#include "tu_random.h"
+
+
+namespace tu_random
+{
+	// Global generator.
+	static generator	s_generator;
+
+	Uint32	next_random()
+	{
+		return s_generator.next_random();
+	}
+
+	void	seed_random(Uint32 seed)
+	{
+		s_generator.seed_random(seed);
+	}
+
+	float	get_unit_float()
+	{
+		return s_generator.get_unit_float();
+	}
+
+
+	// PRNG code adapted from the complimentary-multiply-with-carry
+	// code in the article: George Marsaglia, "Seeds for Random Number
+	// Generators", Communications of the ACM, May 2003, Vol 46 No 5,
+	// pp90-93.
+	//
+	// The article says:
+	//
+	// "Any one of the choices for seed table size and multiplier will
+	// provide a RNG that has passed extensive tests of randomness,
+	// particularly those in [3], yet is simple and fast --
+	// approximately 30 million random 32-bit integers per second on a
+	// 850MHz PC.  The period is a*b^n, where a is the multiplier, n
+	// the size of the seed table and b=2^32-1.  (a is chosen so that
+	// b is a primitive root of the prime a*b^n + 1.)"
+	//
+	// [3] Marsaglia, G., Zaman, A., and Tsang, W.  Toward a universal
+	// random number generator.  _Statistics and Probability Letters
+	// 8_ (1990), 35-39.
+
+//	const Uint64	a = 123471786;	// for SEED_COUNT=1024
+//	const Uint64	a = 123554632;	// for SEED_COUNT=512
+//	const Uint64	a = 8001634;	// for SEED_COUNT=255
+//	const Uint64	a = 8007626;	// for SEED_COUNT=128
+//	const Uint64	a = 647535442;	// for SEED_COUNT=64
+//	const Uint64	a = 547416522;	// for SEED_COUNT=32
+//	const Uint64	a = 487198574;	// for SEED_COUNT=16
+	const Uint64	a = 716514398;	// for SEED_COUNT=8
+
+
+	generator::generator()
+		:
+		c(362436),
+		i(SEED_COUNT - 1)
+	{
+		seed_random(987654321);
+	}
+
+
+	void	generator::seed_random(Uint32 seed)
+	{
+		// Simple pseudo-random to reseed the seeds.
+		// Suggested by the above article.
+		Uint32	j = seed;
+		for (int i = 0; i < SEED_COUNT; i++)
+		{
+			j = j ^ (j << 13);
+			j = j ^ (j >> 17);
+			j = j ^ (j << 5);
+			Q[i] = j;
+		}
+	}
+
+
+	Uint32	generator::next_random()
+	// Return the next pseudo-random number in the sequence.
+	{
+		Uint64	t;
+		Uint32	x;
+
+		//static Uint32	c = 362436;
+		//static Uint32	i = SEED_COUNT - 1;
+		const Uint32	r = 0xFFFFFFFE;
+
+		i = (i+1) & (SEED_COUNT - 1);
+		t = a * Q[i] + c;
+		c = (Uint32) (t >> 32);
+		x = (Uint32) (t + c);
+		if (x < c)
+		{
+			x++;
+			c++;
+		}
+		
+		Uint32	val = r - x;
+		Q[i] = val;
+		return val;
+	}
+
+	
+	float	generator::get_unit_float()
+	{
+		Uint32	r = next_random();
+
+		// 24 bits of precision.
+		return float(r >> 8) / (16777216.0f - 1.0f);
+	}
+
+}	// end namespace tu_random
+
+
+#ifdef TEST_TU_RANDOM
+
+// Compile with e.g.:
+//
+//  gcc -o tu_random_test tu_random.cpp -I.. -g -DTEST_TU_RANDOM -lstdc++
+//
+// Generate a test file of random numbers for DIEHARD.
+int	main()
+{
+	const int	COUNT = 15000000 / 4;	// number of 4-byte words; DIEHARD needs ~80M bits
+
+	for (int i = 0; i < COUNT; i++)
+	{
+		Uint32	val = tu_random::next_random();
+		fwrite(&val, sizeof(val), 1, stdout);
+	}
+}
+
+
+#endif // TEST_TU_RANDOM
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/tu_swap.h
diff -u gnash/libbase/tu_swap.h:1.1 gnash/libbase/tu_swap.h:1.2
--- gnash/libbase/tu_swap.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_swap.h	Sun Feb 26 15:49:30 2006
@@ -28,6 +28,9 @@
 // endian conversions
 //
 
+#ifdef swap16
+#undef swap16
+#endif
 
 inline Uint16 swap16(Uint16 u)
 { 
@@ -35,6 +38,9 @@
 		((u & 0xFF00) >> 8);
 }
 
+#ifdef swap32
+#undef swap32
+#endif
 inline Uint32 swap32(Uint32 u)
 { 
 	return ((u & 0x000000FF) << 24) | 
@@ -43,6 +49,9 @@
 		((u & 0xFF000000) >> 24);
 }
 
+#ifdef swap64
+#undef swap64
+#endif
 inline Uint64 swap64(Uint64 u)
 {
 #ifdef __GNUC__
Index: gnash/libbase/tu_timer.cpp
diff -u gnash/libbase/tu_timer.cpp:1.1 gnash/libbase/tu_timer.cpp:1.2
--- gnash/libbase/tu_timer.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_timer.cpp	Sun Feb 26 15:49:30 2006
@@ -1,104 +1,104 @@
-// tu_timer.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Utility/profiling timer.
-
-
-#include "tu_timer.h"
-
-
-#ifdef _WIN32
-
-#include <windows.h>
-
-
-uint64 tu_timer::get_ticks()
-{
-	return timeGetTime();
-}
-
-
-double tu_timer::ticks_to_seconds(uint64 ticks)
-{
-	return ticks * (1.0f / 1000.f);
-}
-
-
-uint64	tu_timer::get_profile_ticks()
-{
-	// @@ use rdtsc?
-
-	LARGE_INTEGER	li;
-	QueryPerformanceCounter(&li);
-
-	return li.QuadPart;
-}
-
-
-double	tu_timer::profile_ticks_to_seconds(uint64 ticks)
-{
-	LARGE_INTEGER	freq;
-	QueryPerformanceFrequency(&freq);
-
-	double	seconds = (double) ticks;
-	seconds /= (double) freq.QuadPart;
-
-	return seconds;
-}
-
-
-#else	// not _WIN32
-
-
-#include <sys/time.h>
-
-
-// The profile ticks implementation is just fine for a normal timer.
-
-
-uint64 tu_timer::get_ticks()
-{
-	return get_profile_ticks();
-}
-
-
-double tu_timer::ticks_to_seconds(uint64 ticks)
-{
-	return profile_ticks_to_seconds(ticks);
-}
-
-
-uint64	tu_timer::get_profile_ticks()
-{
-	// @@ TODO prefer rdtsc when available?
-
-	// Return microseconds.
-	struct timeval tv;
-	uint64 result;
-	
-	gettimeofday(&tv, 0);
-
-	result = tv.tv_sec * 1000000;
-	result += tv.tv_usec;
-	
-	return result;
-}
-
-
-double	tu_timer::profile_ticks_to_seconds(uint64 ticks)
-{
-	// ticks is microseconds.  Convert to seconds.
-	return ticks / 1000000.0;
-}
-
-#endif	// not _WIN32
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// tu_timer.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Utility/profiling timer.
+
+
+#include "tu_timer.h"
+
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+
+uint64 tu_timer::get_ticks()
+{
+	return timeGetTime();
+}
+
+
+double tu_timer::ticks_to_seconds(uint64 ticks)
+{
+	return ticks * (1.0f / 1000.f);
+}
+
+
+uint64	tu_timer::get_profile_ticks()
+{
+	// @@ use rdtsc?
+
+	LARGE_INTEGER	li;
+	QueryPerformanceCounter(&li);
+
+	return li.QuadPart;
+}
+
+
+double	tu_timer::profile_ticks_to_seconds(uint64 ticks)
+{
+	LARGE_INTEGER	freq;
+	QueryPerformanceFrequency(&freq);
+
+	double	seconds = (double) ticks;
+	seconds /= (double) freq.QuadPart;
+
+	return seconds;
+}
+
+
+#else	// not _WIN32
+
+
+#include <sys/time.h>
+
+
+// The profile ticks implementation is just fine for a normal timer.
+
+
+uint64 tu_timer::get_ticks()
+{
+	return get_profile_ticks();
+}
+
+
+double tu_timer::ticks_to_seconds(uint64 ticks)
+{
+	return profile_ticks_to_seconds(ticks);
+}
+
+
+uint64	tu_timer::get_profile_ticks()
+{
+	// @@ TODO prefer rdtsc when available?
+
+	// Return microseconds.
+	struct timeval tv;
+	uint64 result;
+	
+	gettimeofday(&tv, 0);
+
+	result = tv.tv_sec * 1000000;
+	result += tv.tv_usec;
+	
+	return result;
+}
+
+
+double	tu_timer::profile_ticks_to_seconds(uint64 ticks)
+{
+	// ticks is microseconds.  Convert to seconds.
+	return ticks / 1000000.0;
+}
+
+#endif	// not _WIN32
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/tu_types.cpp
diff -u gnash/libbase/tu_types.cpp:1.1 gnash/libbase/tu_types.cpp:1.2
--- gnash/libbase/tu_types.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/tu_types.cpp	Sun Feb 26 15:49:30 2006
@@ -1,60 +1,60 @@
-// tu_types.cpp	-- Ignacio Castaño, Thatcher Ulrich 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Minimal typedefs.  Follows SDL conventions; falls back on SDL.h if
-// platform isn't obvious.
-
-
-#include "tu_types.h"
-#include "utility.h"
-
-
-bool	tu_types_validate()
-{
-	// Check typedef sizes.
-	if (sizeof(Uint8) != 1
-		|| sizeof(Uint16) != 2
-		|| sizeof(Uint32) != 4
-		|| sizeof(Uint64) != 8
-		|| sizeof(Sint8) != 1
-		|| sizeof(Sint16) != 2
-		|| sizeof(Sint32) != 4
-		|| sizeof(Sint64) != 8)
-	{
-		// No good.
-		assert(0);
-		return false;
-	}
-
-	// Endian checks.
-	char* buf = "1234";
-
-#ifdef _TU_LITTLE_ENDIAN_
-	if (*(Uint32*) buf != 0x34333231)
-	{
-		// No good.
-		assert(0);
-		return false;
-	}
-#else	// not _TU_LITTLE_ENDIAN_
-	if (*(Uint32*) buf != 0x31323334)
-	{
-		// No good.
-		assert(0);
-		return false;
-	}
-#endif	// not _TU_LITTLE_ENDIAN_
-
-	// Checks passed.
-	return true;
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// tu_types.cpp	-- Ignacio Castaño, Thatcher Ulrich 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Minimal typedefs.  Follows SDL conventions; falls back on SDL.h if
+// platform isn't obvious.
+
+
+#include "tu_types.h"
+#include "utility.h"
+
+
+bool	tu_types_validate()
+{
+	// Check typedef sizes.
+	if (sizeof(Uint8) != 1
+		|| sizeof(Uint16) != 2
+		|| sizeof(Uint32) != 4
+		|| sizeof(Uint64) != 8
+		|| sizeof(Sint8) != 1
+		|| sizeof(Sint16) != 2
+		|| sizeof(Sint32) != 4
+		|| sizeof(Sint64) != 8)
+	{
+		// No good.
+		assert(0);
+		return false;
+	}
+
+	// Endian checks.
+	char* buf = "1234";
+
+#ifdef _TU_LITTLE_ENDIAN_
+	if (*(Uint32*) buf != 0x34333231)
+	{
+		// No good.
+		assert(0);
+		return false;
+	}
+#else	// not _TU_LITTLE_ENDIAN_
+	if (*(Uint32*) buf != 0x31323334)
+	{
+		// No good.
+		assert(0);
+		return false;
+	}
+#endif	// not _TU_LITTLE_ENDIAN_
+
+	// Checks passed.
+	return true;
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/utf8.cpp
diff -u gnash/libbase/utf8.cpp:1.1 gnash/libbase/utf8.cpp:1.2
--- gnash/libbase/utf8.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/utf8.cpp	Sun Feb 26 15:49:30 2006
@@ -1,365 +1,365 @@
-// utf8.cpp	-- Thatcher Ulrich 2004   -*- coding: utf-8;-*-
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.  THE AUTHOR DOES NOT WARRANT THIS CODE.
-
-// Utility code for dealing with UTF-8 encoded text.
-//
-// Much useful info at "UTF-8 and Unicode FAQ" \
                http://www.cl.cam.ac.uk/~mgk25/unicode.html
-
-
-#include "utf8.h"
-
-
-Uint32	utf8::decode_next_unicode_character(const char** utf8_buffer)
-{
-	Uint32	uc;
-	char	c;
-
-	// Security considerations:
-	//
-	// If we hit a zero byte, we want to return 0 without stepping
-	// the buffer pointer past the 0.
-	//
-	// If we hit an "overlong sequence"; i.e. a character encoded
-	// in a longer multibyte string than is necessary, then we
-	// need to discard the character.  This is so attackers can't
-	// disguise dangerous characters or character sequences --
-	// there is only one valid encoding for each character.
-	//
-	// If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE,
-	// 0xFFFF } then we ignore them; they are not valid in UTF-8.
-
-// This isn't actually an invalid character; it's a valid char that
-// looks like an inverted question mark.
-#define INVALID 0x0FFFD
-
-#define FIRST_BYTE(mask, shift)		\
-	uc = (c & (mask)) << (shift);
-
-#define NEXT_BYTE(shift)						\
-	c = **utf8_buffer;						\
-	if (c == 0) return 0; /* end of buffer, do not advance */	\
-	if ((c & 0xC0) != 0x80) return INVALID; /* standard check */	\
-	(*utf8_buffer)++;						\
-	uc |= (c & 0x3F) << shift;
-
-	c = **utf8_buffer;
-	if (c == 0) return 0;	// End of buffer.  Do not advance.
-
-	(*utf8_buffer)++;
-	if ((c & 0x80) == 0) return (Uint32) c;	// Conventional 7-bit ASCII.
-
-	// Multi-byte sequences.
-	if ((c & 0xE0) == 0xC0)
-	{
-		// Two-byte sequence.
-		FIRST_BYTE(0x1F, 6);
-		NEXT_BYTE(0);
-		if (uc < 0x80) return INVALID;	// overlong
-		return uc;
-	}
-	else if ((c & 0xF0) == 0xE0)
-	{
-		// Three-byte sequence.
-		FIRST_BYTE(0x0F, 12);
-		NEXT_BYTE(6);
-		NEXT_BYTE(0);
-		if (uc < 0x800) return INVALID;	// overlong
-		if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID;	// not valid ISO 10646
-		if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID;	// not valid ISO 10646
-		return uc;
-	}
-	else if ((c & 0xF8) == 0xF0)
-	{
-		// Four-byte sequence.
-		FIRST_BYTE(0x07, 18);
-		NEXT_BYTE(12);
-		NEXT_BYTE(6);
-		NEXT_BYTE(0);
-		if (uc < 0x010000) return INVALID;	// overlong
-		return uc;
-	}
-	else if ((c & 0xFC) == 0xF8)
-	{
-		// Five-byte sequence.
-		FIRST_BYTE(0x03, 24);
-		NEXT_BYTE(18);
-		NEXT_BYTE(12);
-		NEXT_BYTE(6);
-		NEXT_BYTE(0);
-		if (uc < 0x0200000) return INVALID;	// overlong
-		return uc;
-	}
-	else if ((c & 0xFE) == 0xFC)
-	{
-		// Six-byte sequence.
-		FIRST_BYTE(0x01, 30);
-		NEXT_BYTE(24);
-		NEXT_BYTE(18);
-		NEXT_BYTE(12);
-		NEXT_BYTE(6);
-		NEXT_BYTE(0);
-		if (uc < 0x04000000) return INVALID;	// overlong
-		return uc;
-	}
-	else
-	{
-		// Invalid.
-		return INVALID;
-	}
-}
-
-
-void	utf8::encode_unicode_character(char* buffer, int* index, Uint32 ucs_character)
-{
-	if (ucs_character <= 0x7F)
-	{
-		// Plain single-byte ASCII.
-		buffer[(*index)++] = (char) ucs_character;
-	}
-	else if (ucs_character <= 0x7FF)
-	{
-		// Two bytes.
-		buffer[(*index)++] = 0xC0 | (ucs_character >> 6);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
-	}
-	else if (ucs_character <= 0xFFFF)
-	{
-		// Three bytes.
-		buffer[(*index)++] = 0xE0 | (ucs_character >> 12);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
-	}
-	else if (ucs_character <= 0x1FFFFF)
-	{
-		// Four bytes.
-		buffer[(*index)++] = 0xF0 | (ucs_character >> 18);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
-	}
-	else if (ucs_character <= 0x3FFFFFF)
-	{
-		// Five bytes.
-		buffer[(*index)++] = 0xF8 | (ucs_character >> 24);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 18) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
-	}
-	else if (ucs_character <= 0x7FFFFFFF)
-	{
-		// Six bytes.
-		buffer[(*index)++] = 0xFC | (ucs_character >> 30);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 24) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 18) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
-		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
-	}
-	else
-	{
-		// Invalid char; don't encode anything.
-	}
-}
-
-
-#ifdef UTF8_UNIT_TEST
-
-// Compile this test case with something like:
-//
-// gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test
-//
-//    or
-//
-// cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I..
-//
-// If possible, try running the test program with the first arg
-// pointing at the file:
-//
-// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
-// 
-// and examine the results by eye to make sure they are acceptable to
-// you.
-
-
-#include "utility.h"
-#include <stdio.h>
-
-
-bool	check_equal(const char* utf8_in, const Uint32* ucs_in)
-{
-	for (;;)
-	{
-		Uint32	next_ucs = *ucs_in++;
-		Uint32	next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in);
-		if (next_ucs != next_ucs_from_utf8)
-		{
-			return false;
-		}
-		if (next_ucs == 0)
-		{
-			assert(next_ucs_from_utf8 == 0);
-			break;
-		}
-	}
-
-	return true;
-}
-
-
-void	log_ascii(const char* line)
-{
-	for (;;)
-	{
-		unsigned char	c = (unsigned char) *line++;
-		if (c == 0)
-		{
-			// End of line.
-			return;
-		}
-		else if (c != '\n'
-			 && (c < 32 || c > 127))
-		{
-			// Non-printable as plain ASCII.
-			printf("<0x%02X>", (int) c);
-		}
-		else
-		{
-			printf("%c", c);
-		}
-	}
-}
-
-
-void	log_ucs(const Uint32* line)
-{
-	for (;;)
-	{
-		Uint32	uc = *line++;
-		if (uc == 0)
-		{
-			// End of line.
-			return;
-		}
-		else if (uc != '\n'
-			 && (uc < 32 || uc > 127))
-		{
-			// Non-printable as plain ASCII.
-			printf("<U-%04X>", uc);
-		}
-		else
-		{
-			printf("%c", (char) uc);
-		}
-	}
-}
-
-
-int main(int argc, const char* argv[])
-{
-	// Simple canned test.
-	{
-		const char*	test8 = "Ignacio Castaño";
-		const Uint32	test32[] =
-			{
-				0x49, 0x67, 0x6E, 0x61, 0x63,
-				0x69, 0x6F, 0x20, 0x43, 0x61,
-				0x73, 0x74, 0x61, 0xF1, 0x6F,
-				0x00
-			};
-
-		assert(check_equal(test8, test32));
-	}
-
-	// If user passed an arg, try reading the file as UTF-8 encoded text.
-	if (argc > 1)
-	{
-		const char*	filename = argv[1];
-		FILE*	fp = fopen(filename, "rb");
-		if (fp == NULL)
-		{
-			printf("Can't open file '%s'\n", filename);
-			return 1;
-		}
-
-		// Read lines from the file, encode/decode them, and highlight discrepancies.
-		const int LINE_SIZE = 200;	// max line size
-		char	line_buffer_utf8[LINE_SIZE];
-		char	reencoded_utf8[6 * LINE_SIZE];
-		Uint32	line_buffer_ucs[LINE_SIZE];
-
-		int	byte_counter = 0;
-		for (;;)
-		{
-			int	c = fgetc(fp);
-			if (c == EOF)
-			{
-				// Done.
-				break;
-			}
-			line_buffer_utf8[byte_counter++] = c;
-			if (c == '\n' || byte_counter >= LINE_SIZE - 2)
-			{
-				// End of line.  Process the line.
-				line_buffer_utf8[byte_counter++] = 0;	// terminate.
-
-				// Decode into UCS.
-				const char*	p = line_buffer_utf8;
-				Uint32*	q = line_buffer_ucs;
-				for (;;)
-				{
-					Uint32	uc = utf8::decode_next_unicode_character(&p);
-					*q++ = uc;
-
-					assert(q < line_buffer_ucs + LINE_SIZE);
-					assert(p < line_buffer_utf8 + LINE_SIZE);
-
-					if (uc == 0) break;
-				}
-
-				// Encode back into UTF-8.
-				q = line_buffer_ucs;
-				int	index = 0;
-				for (;;)
-				{
-					Uint32	uc = *q++;
-					assert(index < LINE_SIZE * 6 - 6);
-					int	last_index = index;
-					utf8::encode_unicode_character(reencoded_utf8, &index, uc);
-					assert(index <= last_index + 6);
-					if (uc == 0) break;
-				}
-
-// This can be useful for debugging.
-#if 0
-				// Show the UCS and the re-encoded UTF-8.
-				log_ucs(line_buffer_ucs);
-				log_ascii(reencoded_utf8);
-#endif // 0
-
-				assert(check_equal(line_buffer_utf8, line_buffer_ucs));
-				assert(check_equal(reencoded_utf8, line_buffer_ucs));
-
-				// Start next line.
-				byte_counter = 0;
-			}
-		}
-
-		fclose(fp);
-	}
-
-	return 0;
-}
-
-
-#endif // UTF8_UNIT_TEST
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// utf8.cpp	-- Thatcher Ulrich 2004   -*- coding: utf-8;-*-
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.  THE AUTHOR DOES NOT WARRANT THIS CODE.
+
+// Utility code for dealing with UTF-8 encoded text.
+//
+// Much useful info at "UTF-8 and Unicode FAQ" \
http://www.cl.cam.ac.uk/~mgk25/unicode.html +
+
+#include "utf8.h"
+
+
+Uint32	utf8::decode_next_unicode_character(const char** utf8_buffer)
+{
+	Uint32	uc;
+	char	c;
+
+	// Security considerations:
+	//
+	// If we hit a zero byte, we want to return 0 without stepping
+	// the buffer pointer past the 0.
+	//
+	// If we hit an "overlong sequence"; i.e. a character encoded
+	// in a longer multibyte string than is necessary, then we
+	// need to discard the character.  This is so attackers can't
+	// disguise dangerous characters or character sequences --
+	// there is only one valid encoding for each character.
+	//
+	// If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE,
+	// 0xFFFF } then we ignore them; they are not valid in UTF-8.
+
+// This isn't actually an invalid character; it's a valid char that
+// looks like an inverted question mark.
+#define INVALID 0x0FFFD
+
+#define FIRST_BYTE(mask, shift)		\
+	uc = (c & (mask)) << (shift);
+
+#define NEXT_BYTE(shift)						\
+	c = **utf8_buffer;						\
+	if (c == 0) return 0; /* end of buffer, do not advance */	\
+	if ((c & 0xC0) != 0x80) return INVALID; /* standard check */	\
+	(*utf8_buffer)++;						\
+	uc |= (c & 0x3F) << shift;
+
+	c = **utf8_buffer;
+	if (c == 0) return 0;	// End of buffer.  Do not advance.
+
+	(*utf8_buffer)++;
+	if ((c & 0x80) == 0) return (Uint32) c;	// Conventional 7-bit ASCII.
+
+	// Multi-byte sequences.
+	if ((c & 0xE0) == 0xC0)
+	{
+		// Two-byte sequence.
+		FIRST_BYTE(0x1F, 6);
+		NEXT_BYTE(0);
+		if (uc < 0x80) return INVALID;	// overlong
+		return uc;
+	}
+	else if ((c & 0xF0) == 0xE0)
+	{
+		// Three-byte sequence.
+		FIRST_BYTE(0x0F, 12);
+		NEXT_BYTE(6);
+		NEXT_BYTE(0);
+		if (uc < 0x800) return INVALID;	// overlong
+		if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID;	// not valid ISO 10646
+		if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID;	// not valid ISO 10646
+		return uc;
+	}
+	else if ((c & 0xF8) == 0xF0)
+	{
+		// Four-byte sequence.
+		FIRST_BYTE(0x07, 18);
+		NEXT_BYTE(12);
+		NEXT_BYTE(6);
+		NEXT_BYTE(0);
+		if (uc < 0x010000) return INVALID;	// overlong
+		return uc;
+	}
+	else if ((c & 0xFC) == 0xF8)
+	{
+		// Five-byte sequence.
+		FIRST_BYTE(0x03, 24);
+		NEXT_BYTE(18);
+		NEXT_BYTE(12);
+		NEXT_BYTE(6);
+		NEXT_BYTE(0);
+		if (uc < 0x0200000) return INVALID;	// overlong
+		return uc;
+	}
+	else if ((c & 0xFE) == 0xFC)
+	{
+		// Six-byte sequence.
+		FIRST_BYTE(0x01, 30);
+		NEXT_BYTE(24);
+		NEXT_BYTE(18);
+		NEXT_BYTE(12);
+		NEXT_BYTE(6);
+		NEXT_BYTE(0);
+		if (uc < 0x04000000) return INVALID;	// overlong
+		return uc;
+	}
+	else
+	{
+		// Invalid.
+		return INVALID;
+	}
+}
+
+
+void	utf8::encode_unicode_character(char* buffer, int* index, Uint32 ucs_character)
+{
+	if (ucs_character <= 0x7F)
+	{
+		// Plain single-byte ASCII.
+		buffer[(*index)++] = (char) ucs_character;
+	}
+	else if (ucs_character <= 0x7FF)
+	{
+		// Two bytes.
+		buffer[(*index)++] = 0xC0 | (ucs_character >> 6);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
+	}
+	else if (ucs_character <= 0xFFFF)
+	{
+		// Three bytes.
+		buffer[(*index)++] = 0xE0 | (ucs_character >> 12);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
+	}
+	else if (ucs_character <= 0x1FFFFF)
+	{
+		// Four bytes.
+		buffer[(*index)++] = 0xF0 | (ucs_character >> 18);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
+	}
+	else if (ucs_character <= 0x3FFFFFF)
+	{
+		// Five bytes.
+		buffer[(*index)++] = 0xF8 | (ucs_character >> 24);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 18) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
+	}
+	else if (ucs_character <= 0x7FFFFFFF)
+	{
+		// Six bytes.
+		buffer[(*index)++] = 0xFC | (ucs_character >> 30);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 24) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 18) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 12) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 6) & 0x3F);
+		buffer[(*index)++] = 0x80 | ((ucs_character >> 0) & 0x3F);
+	}
+	else
+	{
+		// Invalid char; don't encode anything.
+	}
+}
+
+
+#ifdef UTF8_UNIT_TEST
+
+// Compile this test case with something like:
+//
+// gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test
+//
+//    or
+//
+// cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I..
+//
+// If possible, try running the test program with the first arg
+// pointing at the file:
+//
+// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+// 
+// and examine the results by eye to make sure they are acceptable to
+// you.
+
+
+#include "utility.h"
+#include <stdio.h>
+
+
+bool	check_equal(const char* utf8_in, const Uint32* ucs_in)
+{
+	for (;;)
+	{
+		Uint32	next_ucs = *ucs_in++;
+		Uint32	next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in);
+		if (next_ucs != next_ucs_from_utf8)
+		{
+			return false;
+		}
+		if (next_ucs == 0)
+		{
+			assert(next_ucs_from_utf8 == 0);
+			break;
+		}
+	}
+
+	return true;
+}
+
+
+void	log_ascii(const char* line)
+{
+	for (;;)
+	{
+		unsigned char	c = (unsigned char) *line++;
+		if (c == 0)
+		{
+			// End of line.
+			return;
+		}
+		else if (c != '\n'
+			 && (c < 32 || c > 127))
+		{
+			// Non-printable as plain ASCII.
+			printf("<0x%02X>", (int) c);
+		}
+		else
+		{
+			printf("%c", c);
+		}
+	}
+}
+
+
+void	log_ucs(const Uint32* line)
+{
+	for (;;)
+	{
+		Uint32	uc = *line++;
+		if (uc == 0)
+		{
+			// End of line.
+			return;
+		}
+		else if (uc != '\n'
+			 && (uc < 32 || uc > 127))
+		{
+			// Non-printable as plain ASCII.
+			printf("<U-%04X>", uc);
+		}
+		else
+		{
+			printf("%c", (char) uc);
+		}
+	}
+}
+
+
+int main(int argc, const char* argv[])
+{
+	// Simple canned test.
+	{
+		const char*	test8 = "Ignacio Castaño";
+		const Uint32	test32[] =
+			{
+				0x49, 0x67, 0x6E, 0x61, 0x63,
+				0x69, 0x6F, 0x20, 0x43, 0x61,
+				0x73, 0x74, 0x61, 0xF1, 0x6F,
+				0x00
+			};
+
+		assert(check_equal(test8, test32));
+	}
+
+	// If user passed an arg, try reading the file as UTF-8 encoded text.
+	if (argc > 1)
+	{
+		const char*	filename = argv[1];
+		FILE*	fp = fopen(filename, "rb");
+		if (fp == NULL)
+		{
+			printf("Can't open file '%s'\n", filename);
+			return 1;
+		}
+
+		// Read lines from the file, encode/decode them, and highlight discrepancies.
+		const int LINE_SIZE = 200;	// max line size
+		char	line_buffer_utf8[LINE_SIZE];
+		char	reencoded_utf8[6 * LINE_SIZE];
+		Uint32	line_buffer_ucs[LINE_SIZE];
+
+		int	byte_counter = 0;
+		for (;;)
+		{
+			int	c = fgetc(fp);
+			if (c == EOF)
+			{
+				// Done.
+				break;
+			}
+			line_buffer_utf8[byte_counter++] = c;
+			if (c == '\n' || byte_counter >= LINE_SIZE - 2)
+			{
+				// End of line.  Process the line.
+				line_buffer_utf8[byte_counter++] = 0;	// terminate.
+
+				// Decode into UCS.
+				const char*	p = line_buffer_utf8;
+				Uint32*	q = line_buffer_ucs;
+				for (;;)
+				{
+					Uint32	uc = utf8::decode_next_unicode_character(&p);
+					*q++ = uc;
+
+					assert(q < line_buffer_ucs + LINE_SIZE);
+					assert(p < line_buffer_utf8 + LINE_SIZE);
+
+					if (uc == 0) break;
+				}
+
+				// Encode back into UTF-8.
+				q = line_buffer_ucs;
+				int	index = 0;
+				for (;;)
+				{
+					Uint32	uc = *q++;
+					assert(index < LINE_SIZE * 6 - 6);
+					int	last_index = index;
+					utf8::encode_unicode_character(reencoded_utf8, &index, uc);
+					assert(index <= last_index + 6);
+					if (uc == 0) break;
+				}
+
+// This can be useful for debugging.
+#if 0
+				// Show the UCS and the re-encoded UTF-8.
+				log_ucs(line_buffer_ucs);
+				log_ascii(reencoded_utf8);
+#endif // 0
+
+				assert(check_equal(line_buffer_utf8, line_buffer_ucs));
+				assert(check_equal(reencoded_utf8, line_buffer_ucs));
+
+				// Start next line.
+				byte_counter = 0;
+			}
+		}
+
+		fclose(fp);
+	}
+
+	return 0;
+}
+
+
+#endif // UTF8_UNIT_TEST
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/utility.cpp
diff -u gnash/libbase/utility.cpp:1.2 gnash/libbase/utility.cpp:1.3
--- gnash/libbase/utility.cpp:1.2	Mon Jan 23 20:37:19 2006
+++ gnash/libbase/utility.cpp	Sun Feb 26 15:49:30 2006
@@ -1,95 +1,95 @@
-//   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "utility.h"
-#include "dlmalloc.h"
-
-#ifdef HAVE_DMALLOC
-
-// Overrides of new/delete that use Doug Lea's malloc.  Very helpful
-// on certain lame platforms.
-
-void*	operator new(size_t size)
-{
-	return dlmalloc(size);
-}
-
-void	operator delete(void* ptr)
-{
-	if (ptr) dlfree(ptr);
-}
-
-void*	operator new[](size_t size)
-{
-	return dlmalloc(size);
-}
-
-void	operator delete[](void* ptr)
-{
-	if (ptr) dlfree(ptr);
-}
-// end of HAVE_DMALLOC
-#endif
-
-
-void dump_memory_stats(const char *from, int line, const char *label) 
-// Dump the internal statistics from malloc() so we can track memory leaks
-{
-
-  
-// This does not work with DMALLOC, since the internal data structures
-// differ.
-#ifdef HAVE_MALLINFO
-
-	struct mallinfo mi;
-	static int allocated = 0;
-	static int freeb = 0;
-  
-	mi = mallinfo();
-	if (label != 0) {
-		printf("Malloc Statistics from %s() (line #%d): %s\n", from, line, label);
-	} else { 
-		printf("Malloc Statistics from %s() (line #%d):\n", from, line);
-	}
-  
-	//printf("\tnon-mapped space from system:  %d\n", mi.arena);
-	printf("\ttotal allocated space:         %d\n", mi.uordblks);
-	printf("\ttotal free space:              %d\n", mi.fordblks);
-	//printf("\tspace in mmapped regions:      %d\n", mi.hblkhd);
-	//printf("\ttop-most, releasable space:    %d\n", mi.keepcost); // Prints 78824
-	if (freeb != mi.fordblks) {
-		printf("\t%d bytes difference in free space.\n", freeb - mi.fordblks);
-		freeb = mi.fordblks;
-	}
-
-	//if (allocated != mi.uordblks) {
-	//  printf("\t%d bytes difference in allocated space.\n", mi.uordblks - allocated);
-	//  allocated = mi.uordblks;
-	//}  
-
-// HAVE_MALLINFO
-#endif
-}
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:
+//   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "utility.h"
+#include "dlmalloc.h"
+
+#ifdef HAVE_DMALLOC
+
+// Overrides of new/delete that use Doug Lea's malloc.  Very helpful
+// on certain lame platforms.
+
+void*	operator new(size_t size)
+{
+	return dlmalloc(size);
+}
+
+void	operator delete(void* ptr)
+{
+	if (ptr) dlfree(ptr);
+}
+
+void*	operator new[](size_t size)
+{
+	return dlmalloc(size);
+}
+
+void	operator delete[](void* ptr)
+{
+	if (ptr) dlfree(ptr);
+}
+// end of HAVE_DMALLOC
+#endif
+
+
+void dump_memory_stats(const char *from, int line, const char *label) 
+// Dump the internal statistics from malloc() so we can track memory leaks
+{
+
+  
+// This does not work with DMALLOC, since the internal data structures
+// differ.
+#ifdef HAVE_MALLINFO
+
+	struct mallinfo mi;
+	static int allocated = 0;
+	static int freeb = 0;
+  
+	mi = mallinfo();
+	if (label != 0) {
+		printf("Malloc Statistics from %s() (line #%d): %s\n", from, line, label);
+	} else { 
+		printf("Malloc Statistics from %s() (line #%d):\n", from, line);
+	}
+  
+	//printf("\tnon-mapped space from system:  %d\n", mi.arena);
+	printf("\ttotal allocated space:         %d\n", mi.uordblks);
+	printf("\ttotal free space:              %d\n", mi.fordblks);
+	//printf("\tspace in mmapped regions:      %d\n", mi.hblkhd);
+	//printf("\ttop-most, releasable space:    %d\n", mi.keepcost); // Prints 78824
+	if (freeb != mi.fordblks) {
+		printf("\t%d bytes difference in free space.\n", freeb - mi.fordblks);
+		freeb = mi.fordblks;
+	}
+
+	//if (allocated != mi.uordblks) {
+	//  printf("\t%d bytes difference in allocated space.\n", mi.uordblks - allocated);
+	//  allocated = mi.uordblks;
+	//}  
+
+// HAVE_MALLINFO
+#endif
+}
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/utility.h
diff -u gnash/libbase/utility.h:1.1 gnash/libbase/utility.h:1.2
--- gnash/libbase/utility.h:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/utility.h	Sun Feb 26 15:49:30 2006
@@ -1,180 +1,180 @@
-// utility.h	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Various little utility functions, macros & typedefs.
-
-
-#ifndef UTILITY_H
-#define UTILITY_H
-
-#include "tu_config.h"
-#include <assert.h>
-#include "tu_math.h"
-#include "tu_types.h"
-#include "tu_swap.h"
-#include <ctype.h>
-
-
-#ifdef _WIN32
-#ifndef NDEBUG
-
-// On windows, replace ANSI assert with our own, for a less annoying
-// debugging experience.
-//int	tu_testbed_assert_break(const char* filename, int linenum, const char* \
                expression);
-#undef assert
-#define assert(x)	if (!(x)) { __asm { int 3 } }	// tu_testbed_assert_break(__FILE__, \
                __LINE__, #x))
-
-#endif // not NDEBUG
-#endif // _WIN32
-
-
-// Compile-time assert.  Thanks to Jon Jagger
-// (http://www.jaggersoft.com) for this trick.
-#define compiler_assert(x)	switch(0){case 0: case x:;}
-
-
-//
-// new/delete wackiness -- if USE_DL_MALLOC is defined, we're going to
-// try to use Doug Lea's malloc as much as possible by overriding the
-// default operator new/delete.
-//
-#ifdef USE_DL_MALLOC
-
-void*	operator new(size_t size);
-void	operator delete(void* ptr);
-void*	operator new[](size_t size);
-void	operator delete[](void* ptr);
-
-#else	// not USE_DL_MALLOC
-
-// If we're not using DL_MALLOC, then *really* don't use it: #define
-// away dlmalloc(), dlfree(), etc, back to the platform defaults.
-#define dlmalloc	malloc
-#define dlfree	free
-#define dlrealloc	realloc
-#define dlcalloc	calloc
-#define dlmemalign	memalign
-#define dlvalloc	valloc
-#define dlpvalloc	pvalloc
-#define dlmalloc_trim	malloc_trim
-#define dlmalloc_stats	malloc_stats
-
-#endif	// not USE_DL_MALLOC
-
-
-#ifndef M_PI
-#define M_PI 3.141592654
-#endif // M_PI
-
-
-//
-// some misc handy math functions
-//
-
-inline int	iabs(int i) { if (i < 0) return -i; else return i; }
-inline int	imax(int a, int b) { if (a < b) return b; else return a; }
-inline float	fmax(float a, float b) { if (a < b) return b; else return a; }
-inline int	imin(int a, int b) { if (a < b) return a; else return b; }
-inline float	fmin(float a, float b) { if (a < b) return a; else return b; }
-
-
-inline int	iclamp(int i, int min, int max) {
-	assert( min <= max );
-	return imax(min, imin(i, max));
-}
-
-inline float	fclamp(float f, float xmin, float xmax) {
-	assert( xmin <= xmax );
-	return fmax(xmin, fmin(f, xmax));
-}
-
-inline float flerp(float a, float b, float f) { return (b - a) * f + a; }
-
-const float LN_2 = 0.693147180559945f;
-inline float	log2(float f) { return logf(f) / LN_2; }
-
-inline int	fchop( float f ) { return (int) f; }	// replace w/ inline asm if desired
-inline int	frnd(float f) { return fchop(f + 0.5f); }	// replace with inline asm if \
                desired
-
-
-// Handy macro to quiet compiler warnings about unused parameters/variables.
-#define UNUSED(x) (x) = (x)
-
-
-// Compile-time constant size of array.
-#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
-
-
-inline size_t	bernstein_hash(const void* data_in, int size, unsigned int seed = \
                5381)
-// Computes a hash of the given data buffer.
-// Hash function suggested by http://www.cs.yorku.ca/~oz/hash.html
-// Due to Dan Bernstein.  Allegedly very good on strings.
-//
-// One problem with this hash function is that e.g. if you take a
-// bunch of 32-bit ints and hash them, their hash values will be
-// concentrated toward zero, instead of randomly distributed in
-// [0,2^32-1], because of shifting up only 5 bits per byte.
-{
-	const unsigned char*	data = (const unsigned char*) data_in;
-	unsigned int	h = seed;
-	while (size > 0) {
-		size--;
-		h = ((h << 5) + h) ^ (unsigned) data[size];
-	}
-
-	return h;
-}
-
-
-inline size_t	sdbm_hash(const void* data_in, int size, unsigned int seed = 5381)
-// Alternative: "sdbm" hash function, suggested at same web page
-// above, http::/www.cs.yorku.ca/~oz/hash.html
-//
-// This is somewhat slower, but it works way better than the above
-// hash function for hashing large numbers of 32-bit ints.
-{
-	const unsigned char*	data = (const unsigned char*) data_in;
-	unsigned int	h = seed;
-	while (size > 0) {
-		size--;
-		h = (h << 16) + (h << 6) - h + (unsigned) data[size];
-	}
-
-	return h;
-}
-
-
-inline size_t	bernstein_hash_case_insensitive(const void* data_in, int size, \
                unsigned int seed = 5381)
-// Computes a hash of the given data buffer; does tolower() on each
-// byte.  Hash function suggested by
-// http://www.cs.yorku.ca/~oz/hash.html Due to Dan Bernstein.
-// Allegedly very good on strings.
-{
-	const unsigned char*	data = (const unsigned char*) data_in;
-	unsigned int	h = seed;
-	while (size > 0) {
-		size--;
-		h = ((h << 5) + h) ^ (unsigned) tolower(data[size]);
-	}
-
-	// Alternative: "sdbm" hash function, suggested at same web page above.
-	// h = 0;
-	// for bytes { h = (h << 16) + (h << 6) - hash + *p; }
-
-	return h;
-}
-
-// Dump the internal statistics from malloc() so we can track memory leaks
-void dump_memory_stats(const char *from, int line, const char *label);
-
-#endif // UTILITY_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// utility.h	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Various little utility functions, macros & typedefs.
+
+
+#ifndef UTILITY_H
+#define UTILITY_H
+
+#include "tu_config.h"
+#include <assert.h>
+#include "tu_math.h"
+#include "tu_types.h"
+#include "tu_swap.h"
+#include <ctype.h>
+
+
+#ifdef _WIN32
+#ifndef NDEBUG
+
+// On windows, replace ANSI assert with our own, for a less annoying
+// debugging experience.
+//int	tu_testbed_assert_break(const char* filename, int linenum, const char* \
expression); +#undef assert
+#define assert(x)	if (!(x)) { __asm { int 3 } }	// tu_testbed_assert_break(__FILE__, \
__LINE__, #x)) +
+#endif // not NDEBUG
+#endif // _WIN32
+
+
+// Compile-time assert.  Thanks to Jon Jagger
+// (http://www.jaggersoft.com) for this trick.
+#define compiler_assert(x)	switch(0){case 0: case x:;}
+
+
+//
+// new/delete wackiness -- if USE_DL_MALLOC is defined, we're going to
+// try to use Doug Lea's malloc as much as possible by overriding the
+// default operator new/delete.
+//
+#ifdef USE_DL_MALLOC
+
+void*	operator new(size_t size);
+void	operator delete(void* ptr);
+void*	operator new[](size_t size);
+void	operator delete[](void* ptr);
+
+#else	// not USE_DL_MALLOC
+
+// If we're not using DL_MALLOC, then *really* don't use it: #define
+// away dlmalloc(), dlfree(), etc, back to the platform defaults.
+#define dlmalloc	malloc
+#define dlfree	free
+#define dlrealloc	realloc
+#define dlcalloc	calloc
+#define dlmemalign	memalign
+#define dlvalloc	valloc
+#define dlpvalloc	pvalloc
+#define dlmalloc_trim	malloc_trim
+#define dlmalloc_stats	malloc_stats
+
+#endif	// not USE_DL_MALLOC
+
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif // M_PI
+
+
+//
+// some misc handy math functions
+//
+
+inline int	iabs(int i) { if (i < 0) return -i; else return i; }
+inline int	imax(int a, int b) { if (a < b) return b; else return a; }
+inline float	fmax(float a, float b) { if (a < b) return b; else return a; }
+inline int	imin(int a, int b) { if (a < b) return a; else return b; }
+inline float	fmin(float a, float b) { if (a < b) return a; else return b; }
+
+
+inline int	iclamp(int i, int min, int max) {
+	assert( min <= max );
+	return imax(min, imin(i, max));
+}
+
+inline float	fclamp(float f, float xmin, float xmax) {
+	assert( xmin <= xmax );
+	return fmax(xmin, fmin(f, xmax));
+}
+
+inline float flerp(float a, float b, float f) { return (b - a) * f + a; }
+
+const float LN_2 = 0.693147180559945f;
+inline float	log2(float f) { return logf(f) / LN_2; }
+
+inline int	fchop( float f ) { return (int) f; }	// replace w/ inline asm if desired
+inline int	frnd(float f) { return fchop(f + 0.5f); }	// replace with inline asm if \
desired +
+
+// Handy macro to quiet compiler warnings about unused parameters/variables.
+#define UNUSED(x) (x) = (x)
+
+
+// Compile-time constant size of array.
+#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
+
+
+inline size_t	bernstein_hash(const void* data_in, int size, unsigned int seed = \
5381) +// Computes a hash of the given data buffer.
+// Hash function suggested by http://www.cs.yorku.ca/~oz/hash.html
+// Due to Dan Bernstein.  Allegedly very good on strings.
+//
+// One problem with this hash function is that e.g. if you take a
+// bunch of 32-bit ints and hash them, their hash values will be
+// concentrated toward zero, instead of randomly distributed in
+// [0,2^32-1], because of shifting up only 5 bits per byte.
+{
+	const unsigned char*	data = (const unsigned char*) data_in;
+	unsigned int	h = seed;
+	while (size > 0) {
+		size--;
+		h = ((h << 5) + h) ^ (unsigned) data[size];
+	}
+
+	return h;
+}
+
+
+inline size_t	sdbm_hash(const void* data_in, int size, unsigned int seed = 5381)
+// Alternative: "sdbm" hash function, suggested at same web page
+// above, http::/www.cs.yorku.ca/~oz/hash.html
+//
+// This is somewhat slower, but it works way better than the above
+// hash function for hashing large numbers of 32-bit ints.
+{
+	const unsigned char*	data = (const unsigned char*) data_in;
+	unsigned int	h = seed;
+	while (size > 0) {
+		size--;
+		h = (h << 16) + (h << 6) - h + (unsigned) data[size];
+	}
+
+	return h;
+}
+
+
+inline size_t	bernstein_hash_case_insensitive(const void* data_in, int size, \
unsigned int seed = 5381) +// Computes a hash of the given data buffer; does \
tolower() on each +// byte.  Hash function suggested by
+// http://www.cs.yorku.ca/~oz/hash.html Due to Dan Bernstein.
+// Allegedly very good on strings.
+{
+	const unsigned char*	data = (const unsigned char*) data_in;
+	unsigned int	h = seed;
+	while (size > 0) {
+		size--;
+		h = ((h << 5) + h) ^ (unsigned) tolower(data[size]);
+	}
+
+	// Alternative: "sdbm" hash function, suggested at same web page above.
+	// h = 0;
+	// for bytes { h = (h << 16) + (h << 6) - hash + *p; }
+
+	return h;
+}
+
+// Dump the internal statistics from malloc() so we can track memory leaks
+void dump_memory_stats(const char *from, int line, const char *label);
+
+#endif // UTILITY_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libbase/zlib_adapter.cpp
diff -u gnash/libbase/zlib_adapter.cpp:1.1 gnash/libbase/zlib_adapter.cpp:1.2
--- gnash/libbase/zlib_adapter.cpp:1.1	Tue Dec 20 20:57:00 2005
+++ gnash/libbase/zlib_adapter.cpp	Sun Feb 26 15:49:30 2006
@@ -1,326 +1,326 @@
-// zlib_adapter.cpp	-- Thatcher Ulrich 2003
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Code to wrap zlib compression/decompression around a tu_file
-// stream.
-
-
-#include "zlib_adapter.h"
-#include "tu_file.h"
-#include "utility.h"
-
-
-#if !TU_CONFIG_LINK_TO_ZLIB
-
-
-// Stubs, in case client doesn't want to link to zlib.
-namespace zlib_adapter
-{
-	tu_file*	make_inflater(tu_file* in) { return NULL; }
-	tu_file*	make_deflater(tu_file* out) { return NULL; }
-}
-
-
-#else // TU_CONFIG_LINK_TO_ZLIB
-
-
-#include <zlib.h>
-
-
-namespace zlib_adapter
-{
-	const int	ZBUF_SIZE = 4096;
-
-	struct inflater_impl
-	{
-		tu_file*	m_in;
-		z_stream	m_zstream;
-		int	m_initial_stream_pos;	// position of the input stream where we started \
                inflating.
-		int	m_logical_stream_pos;	// current stream position of uncompressed data.
-		bool	m_at_eof;
-
-		unsigned char	m_rawdata[ZBUF_SIZE];
-
-		int	m_error;
-
-
-		inflater_impl(tu_file* in)
-		// Constructor.
-			:
-			m_in(in),
-			m_initial_stream_pos(in->get_position()),
-			m_logical_stream_pos(0),
-			m_at_eof(false),
-			m_error(0)
-		{
-			assert(m_in);
-
-			m_zstream.zalloc = (alloc_func)0;
-			m_zstream.zfree = (free_func)0;
-			m_zstream.opaque = (voidpf)0;
-
-			m_zstream.next_in  = 0;
-			m_zstream.avail_in = 0;
-
-			m_zstream.next_out = 0;
-			m_zstream.avail_out = 0;
-
-			int	err = inflateInit(&m_zstream);
-			if (err != Z_OK) {
-				//log_error("error: inflater_impl::ctor() inflateInit() returned %d\n", err);
-				m_error = 1;
-				return;
-			}
-
-			// Ready to go!
-		}
-
-
-		void	reset()
-		// Discard current results and rewind to the beginning.
-		// Necessary in order to seek backwards.
-		{
-			m_error = 0;
-			m_at_eof = 0;
-			int	err = inflateReset(&m_zstream);
-			if (err != Z_OK) {
-				m_error = 1;
-				return;
-			}
-
-			m_zstream.next_in = 0;
-			m_zstream.avail_in = 0;
-
-			m_zstream.next_out = 0;
-			m_zstream.avail_out = 0;
-
-			// Rewind the underlying stream.
-			m_in->set_position(m_initial_stream_pos);
-
-			m_logical_stream_pos = 0;
-		}
-
-
-		int	inflate_from_stream(void* dst, int bytes)
-		{
-			if (m_error)
-			{
-				return 0;
-			}
-
-			m_zstream.next_out = (unsigned char*) dst;
-			m_zstream.avail_out = bytes;
-
-			for (;;)
-			{
-				if (m_zstream.avail_in == 0)
-				{
-					// Get more raw data.
-					int	new_bytes = m_in->read_bytes(m_rawdata, ZBUF_SIZE);
-					if (new_bytes == 0)
-					{
-						// The cupboard is bare!  We have nothing to feed to inflate().
-						break;
-					}
-					else
-					{
-						m_zstream.next_in = m_rawdata;
-						m_zstream.avail_in = new_bytes;
-					}
-				}
-
-				int	err = inflate(&m_zstream, Z_SYNC_FLUSH);
-				if (err == Z_STREAM_END)
-				{
-					m_at_eof = true;
-					break;
-				}
-				if (err != Z_OK)
-				{
-					// something's wrong.
-					m_error = 1;
-					break;
-				}
-
-				if (m_zstream.avail_out == 0)
-				{
-					break;
-				}
-			}
-
-			int	bytes_read = bytes - m_zstream.avail_out;
-			m_logical_stream_pos += bytes_read;
-
-			return bytes_read;
-		}
-
-		void	rewind_unused_bytes()
-		// If we have unused bytes in our input buffer, rewind
-		// to before they started.
-		{
-			if (m_zstream.avail_in > 0)
-			{
-				int	pos = m_in->get_position();
-				int	rewound_pos = pos - m_zstream.avail_in;
-				assert(pos >= 0);
-				assert(pos >= m_initial_stream_pos);
-				assert(rewound_pos >= 0);
-				assert(rewound_pos >= m_initial_stream_pos);
-
-				m_in->set_position(rewound_pos);
-			}
-		}
-	};
-
-
-	int	inflate_read(void* dst, int bytes, void* appdata)
-	// Return number of bytes actually read.
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-		if (inf->m_error)
-		{
-			return 0;
-		}
-
-		return inf->inflate_from_stream(dst, bytes);
-	}
-
-
-	int	inflate_write(const void* src, int bytes, void* appdata)
-	// Return number of bytes actually written.
-	{
-		// *In*flaters can't write!!!
-		assert(0);
-		return 0;
-	}
-
-
-	int	inflate_seek(int pos, void* appdata)
-	// Try to go to pos.  Return actual pos.
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-		if (inf->m_error)
-		{
-			return inf->m_logical_stream_pos;
-		}
-
-		// If we're seeking backwards, then restart from the beginning.
-		if (pos < inf->m_logical_stream_pos)
-		{
-			inf->reset();
-		}
-
-		unsigned char	temp[ZBUF_SIZE];
-
-		// Now seek forwards, by just reading data in blocks.
-		while (inf->m_logical_stream_pos < pos)
-		{
-			int	to_read = pos - inf->m_logical_stream_pos;
-			int	to_read_this_time = imin(to_read, ZBUF_SIZE);
-			assert(to_read_this_time > 0);
-
-			int	bytes_read = inf->inflate_from_stream(temp, to_read_this_time);
-			assert(bytes_read <= to_read_this_time);
-			if (bytes_read == 0)
-			{
-				// Trouble; can't seek any further.
-				break;
-			}
-		}
-
-		assert(inf->m_logical_stream_pos <= pos);
-
-		return inf->m_logical_stream_pos;
-	}
-
-
-	int	inflate_seek_to_end(void* appdata)
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-		if (inf->m_error)
-		{
-			return inf->m_logical_stream_pos;
-		}
-
-		// Keep reading until we can't read any more.
-
-		unsigned char	temp[ZBUF_SIZE];
-
-		// Seek forwards.
-		for (;;)
-		{
-			int	bytes_read = inf->inflate_from_stream(temp, ZBUF_SIZE);
-			if (bytes_read == 0)
-			{
-				// We've seeked as far as we can.
-				break;
-			}
-		}
-
-		return inf->m_logical_stream_pos;
-	}
-
-	int	inflate_tell(const void* appdata)
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-
-		return inf->m_logical_stream_pos;
-	}
-
-	bool	inflate_get_eof(void* appdata)
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-
-		return inf->m_at_eof;
-	}
-
-	int	inflate_close(void* appdata)
-	{
-		inflater_impl*	inf = (inflater_impl*) appdata;
-
-		inf->rewind_unused_bytes();
-		int	err = inflateEnd(&(inf->m_zstream));
-
-		delete inf;
-
-		if (err != Z_OK)
-		{
-			return TU_FILE_CLOSE_ERROR;
-		}
-
-		return 0;
-	}
-
-
-	tu_file*	make_inflater(tu_file* in)
-	{
-		assert(in);
-
-		inflater_impl*	inflater = new inflater_impl(in);
-		return new tu_file(
-			inflater,
-			inflate_read,
-			inflate_write,
-			inflate_seek,
-			inflate_seek_to_end,
-			inflate_tell,
-			inflate_get_eof,
-			inflate_close);
-	}
-
-
-	// @@ TODO
-	// tu_file*	make_deflater(tu_file* out) { ... }
-}
-
-#endif // TU_CONFIG_LINK_TO_ZLIB
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// zlib_adapter.cpp	-- Thatcher Ulrich 2003
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Code to wrap zlib compression/decompression around a tu_file
+// stream.
+
+
+#include "zlib_adapter.h"
+#include "tu_file.h"
+#include "utility.h"
+
+
+#if !TU_CONFIG_LINK_TO_ZLIB
+
+
+// Stubs, in case client doesn't want to link to zlib.
+namespace zlib_adapter
+{
+	tu_file*	make_inflater(tu_file* in) { return NULL; }
+	tu_file*	make_deflater(tu_file* out) { return NULL; }
+}
+
+
+#else // TU_CONFIG_LINK_TO_ZLIB
+
+
+#include <zlib.h>
+
+
+namespace zlib_adapter
+{
+	const int	ZBUF_SIZE = 4096;
+
+	struct inflater_impl
+	{
+		tu_file*	m_in;
+		z_stream	m_zstream;
+		int	m_initial_stream_pos;	// position of the input stream where we started \
inflating. +		int	m_logical_stream_pos;	// current stream position of uncompressed \
data. +		bool	m_at_eof;
+
+		unsigned char	m_rawdata[ZBUF_SIZE];
+
+		int	m_error;
+
+
+		inflater_impl(tu_file* in)
+		// Constructor.
+			:
+			m_in(in),
+			m_initial_stream_pos(in->get_position()),
+			m_logical_stream_pos(0),
+			m_at_eof(false),
+			m_error(0)
+		{
+			assert(m_in);
+
+			m_zstream.zalloc = (alloc_func)0;
+			m_zstream.zfree = (free_func)0;
+			m_zstream.opaque = (voidpf)0;
+
+			m_zstream.next_in  = 0;
+			m_zstream.avail_in = 0;
+
+			m_zstream.next_out = 0;
+			m_zstream.avail_out = 0;
+
+			int	err = inflateInit(&m_zstream);
+			if (err != Z_OK) {
+				//log_error("error: inflater_impl::ctor() inflateInit() returned %d\n", err);
+				m_error = 1;
+				return;
+			}
+
+			// Ready to go!
+		}
+
+
+		void	reset()
+		// Discard current results and rewind to the beginning.
+		// Necessary in order to seek backwards.
+		{
+			m_error = 0;
+			m_at_eof = 0;
+			int	err = inflateReset(&m_zstream);
+			if (err != Z_OK) {
+				m_error = 1;
+				return;
+			}
+
+			m_zstream.next_in = 0;
+			m_zstream.avail_in = 0;
+
+			m_zstream.next_out = 0;
+			m_zstream.avail_out = 0;
+
+			// Rewind the underlying stream.
+			m_in->set_position(m_initial_stream_pos);
+
+			m_logical_stream_pos = 0;
+		}
+
+
+		int	inflate_from_stream(void* dst, int bytes)
+		{
+			if (m_error)
+			{
+				return 0;
+			}
+
+			m_zstream.next_out = (unsigned char*) dst;
+			m_zstream.avail_out = bytes;
+
+			for (;;)
+			{
+				if (m_zstream.avail_in == 0)
+				{
+					// Get more raw data.
+					int	new_bytes = m_in->read_bytes(m_rawdata, ZBUF_SIZE);
+					if (new_bytes == 0)
+					{
+						// The cupboard is bare!  We have nothing to feed to inflate().
+						break;
+					}
+					else
+					{
+						m_zstream.next_in = m_rawdata;
+						m_zstream.avail_in = new_bytes;
+					}
+				}
+
+				int	err = inflate(&m_zstream, Z_SYNC_FLUSH);
+				if (err == Z_STREAM_END)
+				{
+					m_at_eof = true;
+					break;
+				}
+				if (err != Z_OK)
+				{
+					// something's wrong.
+					m_error = 1;
+					break;
+				}
+
+				if (m_zstream.avail_out == 0)
+				{
+					break;
+				}
+			}
+
+			int	bytes_read = bytes - m_zstream.avail_out;
+			m_logical_stream_pos += bytes_read;
+
+			return bytes_read;
+		}
+
+		void	rewind_unused_bytes()
+		// If we have unused bytes in our input buffer, rewind
+		// to before they started.
+		{
+			if (m_zstream.avail_in > 0)
+			{
+				int	pos = m_in->get_position();
+				int	rewound_pos = pos - m_zstream.avail_in;
+				assert(pos >= 0);
+				assert(pos >= m_initial_stream_pos);
+				assert(rewound_pos >= 0);
+				assert(rewound_pos >= m_initial_stream_pos);
+
+				m_in->set_position(rewound_pos);
+			}
+		}
+	};
+
+
+	int	inflate_read(void* dst, int bytes, void* appdata)
+	// Return number of bytes actually read.
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+		if (inf->m_error)
+		{
+			return 0;
+		}
+
+		return inf->inflate_from_stream(dst, bytes);
+	}
+
+
+	int	inflate_write(const void* src, int bytes, void* appdata)
+	// Return number of bytes actually written.
+	{
+		// *In*flaters can't write!!!
+		assert(0);
+		return 0;
+	}
+
+
+	int	inflate_seek(int pos, void* appdata)
+	// Try to go to pos.  Return actual pos.
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+		if (inf->m_error)
+		{
+			return inf->m_logical_stream_pos;
+		}
+
+		// If we're seeking backwards, then restart from the beginning.
+		if (pos < inf->m_logical_stream_pos)
+		{
+			inf->reset();
+		}
+
+		unsigned char	temp[ZBUF_SIZE];
+
+		// Now seek forwards, by just reading data in blocks.
+		while (inf->m_logical_stream_pos < pos)
+		{
+			int	to_read = pos - inf->m_logical_stream_pos;
+			int	to_read_this_time = imin(to_read, ZBUF_SIZE);
+			assert(to_read_this_time > 0);
+
+			int	bytes_read = inf->inflate_from_stream(temp, to_read_this_time);
+			assert(bytes_read <= to_read_this_time);
+			if (bytes_read == 0)
+			{
+				// Trouble; can't seek any further.
+				break;
+			}
+		}
+
+		assert(inf->m_logical_stream_pos <= pos);
+
+		return inf->m_logical_stream_pos;
+	}
+
+
+	int	inflate_seek_to_end(void* appdata)
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+		if (inf->m_error)
+		{
+			return inf->m_logical_stream_pos;
+		}
+
+		// Keep reading until we can't read any more.
+
+		unsigned char	temp[ZBUF_SIZE];
+
+		// Seek forwards.
+		for (;;)
+		{
+			int	bytes_read = inf->inflate_from_stream(temp, ZBUF_SIZE);
+			if (bytes_read == 0)
+			{
+				// We've seeked as far as we can.
+				break;
+			}
+		}
+
+		return inf->m_logical_stream_pos;
+	}
+
+	int	inflate_tell(const void* appdata)
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+
+		return inf->m_logical_stream_pos;
+	}
+
+	bool	inflate_get_eof(void* appdata)
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+
+		return inf->m_at_eof;
+	}
+
+	int	inflate_close(void* appdata)
+	{
+		inflater_impl*	inf = (inflater_impl*) appdata;
+
+		inf->rewind_unused_bytes();
+		int	err = inflateEnd(&(inf->m_zstream));
+
+		delete inf;
+
+		if (err != Z_OK)
+		{
+			return TU_FILE_CLOSE_ERROR;
+		}
+
+		return 0;
+	}
+
+
+	tu_file*	make_inflater(tu_file* in)
+	{
+		assert(in);
+
+		inflater_impl*	inflater = new inflater_impl(in);
+		return new tu_file(
+			inflater,
+			inflate_read,
+			inflate_write,
+			inflate_seek,
+			inflate_seek_to_end,
+			inflate_tell,
+			inflate_get_eof,
+			inflate_close);
+	}
+
+
+	// @@ TODO
+	// tu_file*	make_deflater(tu_file* out) { ... }
+}
+
+#endif // TU_CONFIG_LINK_TO_ZLIB
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libgeometry/Makefile.am
diff -u gnash/libgeometry/Makefile.am:1.9 gnash/libgeometry/Makefile.am:1.10
--- gnash/libgeometry/Makefile.am:1.9	Fri Feb  3 20:50:27 2006
+++ gnash/libgeometry/Makefile.am	Sun Feb 26 15:49:30 2006
@@ -33,12 +33,10 @@
 INCLUDES = -I.. -I$(srcdir)	\
         -I$(top_srcdir) 	\
         -I$(top_srcdir)/libbase \
+	$(PTHREAD_CFLAGS)	\
         $(SDL_CFLAGS) 		\
         $(OPENGL_CFLAGS) 	\
-        $(ENGINE_INCLUDE) 	\
-        $(LIBPNG_CFLAGS) 	\
-        $(ZLIB_CFLAGS) 		\
-        $(JPEGLIB_CFLAGS)
+        $(ENGINE_INCLUDE)
 
 libgnashgeo_la_SOURCES = 	\
 	axial_box.cpp		\
Index: gnash/libgeometry/axial_box.cpp
diff -u gnash/libgeometry/axial_box.cpp:1.2 gnash/libgeometry/axial_box.cpp:1.3
--- gnash/libgeometry/axial_box.cpp:1.2	Wed Feb  1 23:58:32 2006
+++ gnash/libgeometry/axial_box.cpp	Sun Feb 26 15:49:30 2006
@@ -1,69 +1,69 @@
-// axial_box.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Simple AABB structure
-
-
-#include "axial_box.h"
-#include "tu_random.h"
-#include "utility.h"
-
-
-vec3	axial_box::get_random_point() const
-// Return a random point inside this box.
-{
-	return vec3(
-		flerp(m_min[0], m_max[0], tu_random::get_unit_float()),
-		flerp(m_min[1], m_max[1], tu_random::get_unit_float()),
-		flerp(m_min[2], m_max[2], tu_random::get_unit_float()));
-}
-
-
-void	axial_box::set_enclosing(const axial_box& a)
-// Ensure that the box encloses the box.
-{
-	m_min.x = fmin(m_min.x, a.get_min().x);
-	m_min.y = fmin(m_min.y, a.get_min().y);
-	m_min.z = fmin(m_min.z, a.get_min().z);
-	m_max.x = fmax(m_max.x, a.get_max().x);
-	m_max.y = fmax(m_max.y, a.get_max().y);
-	m_max.z = fmax(m_max.z, a.get_max().z);
-
-	assert(is_valid());
-}
-
-
-int	axial_box::get_longest_axis() const
-// Return axis with the largest size.
-{
-	vec3	size = get_size();
-	if (size.x > size.y)
-	{
-		if (size.x > size.z)
-		{
-			return 0;	// x is longest
-		}
-		return 2;	// z is longest
-	}
-	else
-	{
-		if (size.y > size.z)
-		{
-			return 1;	// y is longest
-		}
-		else return 2; 	// z is longest
-	}
-}
-
-
-
-
-
-// local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// axial_box.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Simple AABB structure
+
+
+#include "axial_box.h"
+#include "tu_random.h"
+#include "utility.h"
+
+
+vec3	axial_box::get_random_point() const
+// Return a random point inside this box.
+{
+	return vec3(
+		flerp(m_min[0], m_max[0], tu_random::get_unit_float()),
+		flerp(m_min[1], m_max[1], tu_random::get_unit_float()),
+		flerp(m_min[2], m_max[2], tu_random::get_unit_float()));
+}
+
+
+void	axial_box::set_enclosing(const axial_box& a)
+// Ensure that the box encloses the box.
+{
+	m_min.x = fmin(m_min.x, a.get_min().x);
+	m_min.y = fmin(m_min.y, a.get_min().y);
+	m_min.z = fmin(m_min.z, a.get_min().z);
+	m_max.x = fmax(m_max.x, a.get_max().x);
+	m_max.y = fmax(m_max.y, a.get_max().y);
+	m_max.z = fmax(m_max.z, a.get_max().z);
+
+	assert(is_valid());
+}
+
+
+int	axial_box::get_longest_axis() const
+// Return axis with the largest size.
+{
+	vec3	size = get_size();
+	if (size.x > size.y)
+	{
+		if (size.x > size.z)
+		{
+			return 0;	// x is longest
+		}
+		return 2;	// z is longest
+	}
+	else
+	{
+		if (size.y > size.z)
+		{
+			return 1;	// y is longest
+		}
+		else return 2; 	// z is longest
+	}
+}
+
+
+
+
+
+// local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libgeometry/axial_box.h
diff -u gnash/libgeometry/axial_box.h:1.2 gnash/libgeometry/axial_box.h:1.3
--- gnash/libgeometry/axial_box.h:1.2	Wed Feb  1 23:58:32 2006
+++ gnash/libgeometry/axial_box.h	Sun Feb 26 15:49:30 2006
@@ -1,264 +1,264 @@
-// axial_box.h	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// simple AABB structure
-
-
-#ifndef AXIAL_BOX_H
-#define AXIAL_BOX_H
-
-
-#include "geometry.h"
-
-
-struct axial_box
-{
-	axial_box();	// zero box
-	axial_box(const vec3& min, const vec3& max);
-
-	enum invalid_ctor
-	{
-		INVALID
-	};
-	axial_box(invalid_ctor e, const vec3& min, const vec3& max);
-
-	//
-	// Getters
-	//
-
-	bool	is_valid() const;
-
-	vec3	get_center() const { return (m_min + m_max) * 0.5f; }
-	vec3	get_extent() const { return (m_max - m_min) * 0.5f; }
-	vec3	get_size() const { return m_max - m_min; }
-
-	const vec3&	get_min() const { return m_min; }
-	const vec3&	get_max() const { return m_max; }
-
-	// Get one of the 8 corner verts.
-	vec3	get_corner(int i) const;
-
-	float	get_surface_area() const;
-
-	vec3	get_random_point() const;
-
-	//
-	// Setters
-	//
-
-	void	set_min_max(const vec3& min, const vec3& max);
-
-	// No validity check -- for intentionally setting an invalid box.
-	void	set_min_max_invalid(const vec3& min, const vec3& max);
-
-	void	set_center_extent(const vec3& center, const vec3& extent);
-
-	// preserve center
-	void	set_extent(const vec3& extent);
-
-	// preserve extent
-	void	set_center(const vec3& center);
-
-	// adjust bounds along one axis.
-	void	set_axis_min(int axis, float new_min);
-	void	set_axis_max(int axis, float new_max);
-
-	// Expand the box.
-	void	set_enclosing(const vec3& v);
-	void	set_enclosing(const axial_box& a);
-
-	//
-	// Etc
-	//
-
-	bool	encloses(const vec3& v, float tolerance = 1e-6f) const;
-	bool	encloses(const axial_box& b, float tolerance = 1e-6f) const;
-
-	// this = intersection(this, b)
-	void	set_intersection(const axial_box& b);
-
-	int	get_longest_axis() const;
-
-private:
-	vec3	m_min, m_max;
-};
-
-
-inline	axial_box::axial_box()
-// Construct a zero box.
-{
-	m_min = vec3::zero;
-	m_max = vec3::zero;
-
-	assert(is_valid());
-}
-
-
-inline	axial_box::axial_box(const vec3& min, const vec3& max)
-// Init from extremes.
-{
-	set_min_max(min, max);
-}
-
-
-inline	axial_box::axial_box(invalid_ctor e, const vec3& min, const vec3& max)
-// Init from extremes, don't check validity.
-{
-	set_min_max_invalid(min, max);
-}
-
-
-inline bool	axial_box::is_valid() const
-// Return true if we're OK.
-{
-	return
-		m_min.x <= m_max.x
-		&& m_min.y <= m_max.y
-		&& m_min.z <= m_max.z;
-}
-
-
-inline vec3	axial_box::get_corner(int i) const
-{
-	assert(is_valid());
-	assert(i >= 0 && i < 8);
-
-	return vec3(
-		i & 1 ? m_min.x : m_max.x,
-		i & 2 ? m_min.y : m_max.y,
-		i & 4 ? m_min.z : m_max.z);
-}
-
-
-inline float	axial_box::get_surface_area() const
-{
-	assert(is_valid());
-
-	vec3	sides(m_max);
-	sides -= m_min;
-
-	return
-		(sides.x * sides.y
-		 + sides.x * sides.z
-		 + sides.y * sides.z) * 2;
-}
-
-
-inline void	axial_box::set_min_max(const vec3& min, const vec3& max)
-{
-	m_min = min;
-	m_max = max;
-	
-	assert(is_valid());
-}
-
-
-inline void	axial_box::set_min_max_invalid(const vec3& min, const vec3& max)
-// Don't check validity.
-{
-	m_min = min;
-	m_max = max;
-}
-
-
-inline void	axial_box::set_center_extent(const vec3& center, const vec3& extent)
-{
-	set_min_max(center - extent, center + extent);
-}
-
-
-inline void	axial_box::set_extent(const vec3& extent)
-{
-	set_center_extent(get_center(), extent);
-}
-
-
-inline void	axial_box::set_center(const vec3& center)
-{
-	set_center_extent(center, get_extent());
-}
-
-
-inline void	axial_box::set_axis_min(int axis, float new_min)
-{
-	assert(is_valid());
-
-	m_min.set(axis, new_min);
-
-	assert(is_valid());
-}
-
-
-inline void	axial_box::set_axis_max(int axis, float new_max)
-{
-	assert(is_valid());
-
-	m_max.set(axis, new_max);
-
-	assert(is_valid());
-}
-
-
-// @@ should probably un-inline this...
-inline void	axial_box::set_enclosing(const vec3& v)
-// Ensure that the box encloses the point.
-{
-	m_min.x = fmin(m_min.x, v.x);
-	m_min.y = fmin(m_min.y, v.y);
-	m_min.z = fmin(m_min.z, v.z);
-	m_max.x = fmax(m_max.x, v.x);
-	m_max.y = fmax(m_max.y, v.y);
-	m_max.z = fmax(m_max.z, v.z);
-
-	assert(is_valid());
-}
-
-
-inline bool	axial_box::encloses(const vec3& v, float tolerance) const
-// Return true if the given point is inside this box.
-{
-	assert(is_valid());
-
-	return
-		m_min.x <= v.x + tolerance
-		&& m_min.y <= v.y + tolerance
-		&& m_min.z <= v.z + tolerance
-		&& m_max.x >= v.x - tolerance
-		&& m_max.y >= v.y - tolerance
-		&& m_max.z >= v.z - tolerance;
-}
-
-
-inline bool	axial_box::encloses(const axial_box& b, float tolerance) const
-// Return true if this box encloses the given box.
-{
-	assert(is_valid());
-
-	return encloses(b.m_min, tolerance) && encloses(b.m_max, tolerance);
-}
-
-
-inline void	axial_box::set_intersection(const axial_box& b)
-// Set this to intersection(this, b)
-{
-	if (b.m_min.x > m_min.x) m_min.x = b.m_min.x;
-	if (b.m_min.y > m_min.y) m_min.y = b.m_min.y;
-	if (b.m_min.z > m_min.z) m_min.z = b.m_min.z;
-
-	if (b.m_max.x < m_max.x) m_max.x = b.m_max.x;
-	if (b.m_max.y < m_max.y) m_max.y = b.m_max.y;
-	if (b.m_max.z < m_max.z) m_max.z = b.m_max.z;
-}
-
-
-#endif // AXIAL_BOX_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// axial_box.h	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// simple AABB structure
+
+
+#ifndef AXIAL_BOX_H
+#define AXIAL_BOX_H
+
+
+#include "geometry.h"
+
+
+struct axial_box
+{
+	axial_box();	// zero box
+	axial_box(const vec3& min, const vec3& max);
+
+	enum invalid_ctor
+	{
+		INVALID
+	};
+	axial_box(invalid_ctor e, const vec3& min, const vec3& max);
+
+	//
+	// Getters
+	//
+
+	bool	is_valid() const;
+
+	vec3	get_center() const { return (m_min + m_max) * 0.5f; }
+	vec3	get_extent() const { return (m_max - m_min) * 0.5f; }
+	vec3	get_size() const { return m_max - m_min; }
+
+	const vec3&	get_min() const { return m_min; }
+	const vec3&	get_max() const { return m_max; }
+
+	// Get one of the 8 corner verts.
+	vec3	get_corner(int i) const;
+
+	float	get_surface_area() const;
+
+	vec3	get_random_point() const;
+
+	//
+	// Setters
+	//
+
+	void	set_min_max(const vec3& min, const vec3& max);
+
+	// No validity check -- for intentionally setting an invalid box.
+	void	set_min_max_invalid(const vec3& min, const vec3& max);
+
+	void	set_center_extent(const vec3& center, const vec3& extent);
+
+	// preserve center
+	void	set_extent(const vec3& extent);
+
+	// preserve extent
+	void	set_center(const vec3& center);
+
+	// adjust bounds along one axis.
+	void	set_axis_min(int axis, float new_min);
+	void	set_axis_max(int axis, float new_max);
+
+	// Expand the box.
+	void	set_enclosing(const vec3& v);
+	void	set_enclosing(const axial_box& a);
+
+	//
+	// Etc
+	//
+
+	bool	encloses(const vec3& v, float tolerance = 1e-6f) const;
+	bool	encloses(const axial_box& b, float tolerance = 1e-6f) const;
+
+	// this = intersection(this, b)
+	void	set_intersection(const axial_box& b);
+
+	int	get_longest_axis() const;
+
+private:
+	vec3	m_min, m_max;
+};
+
+
+inline	axial_box::axial_box()
+// Construct a zero box.
+{
+	m_min = vec3::zero;
+	m_max = vec3::zero;
+
+	assert(is_valid());
+}
+
+
+inline	axial_box::axial_box(const vec3& min, const vec3& max)
+// Init from extremes.
+{
+	set_min_max(min, max);
+}
+
+
+inline	axial_box::axial_box(invalid_ctor e, const vec3& min, const vec3& max)
+// Init from extremes, don't check validity.
+{
+	set_min_max_invalid(min, max);
+}
+
+
+inline bool	axial_box::is_valid() const
+// Return true if we're OK.
+{
+	return
+		m_min.x <= m_max.x
+		&& m_min.y <= m_max.y
+		&& m_min.z <= m_max.z;
+}
+
+
+inline vec3	axial_box::get_corner(int i) const
+{
+	assert(is_valid());
+	assert(i >= 0 && i < 8);
+
+	return vec3(
+		i & 1 ? m_min.x : m_max.x,
+		i & 2 ? m_min.y : m_max.y,
+		i & 4 ? m_min.z : m_max.z);
+}
+
+
+inline float	axial_box::get_surface_area() const
+{
+	assert(is_valid());
+
+	vec3	sides(m_max);
+	sides -= m_min;
+
+	return
+		(sides.x * sides.y
+		 + sides.x * sides.z
+		 + sides.y * sides.z) * 2;
+}
+
+
+inline void	axial_box::set_min_max(const vec3& min, const vec3& max)
+{
+	m_min = min;
+	m_max = max;
+	
+	assert(is_valid());
+}
+
+
+inline void	axial_box::set_min_max_invalid(const vec3& min, const vec3& max)
+// Don't check validity.
+{
+	m_min = min;
+	m_max = max;
+}
+
+
+inline void	axial_box::set_center_extent(const vec3& center, const vec3& extent)
+{
+	set_min_max(center - extent, center + extent);
+}
+
+
+inline void	axial_box::set_extent(const vec3& extent)
+{
+	set_center_extent(get_center(), extent);
+}
+
+
+inline void	axial_box::set_center(const vec3& center)
+{
+	set_center_extent(center, get_extent());
+}
+
+
+inline void	axial_box::set_axis_min(int axis, float new_min)
+{
+	assert(is_valid());
+
+	m_min.set(axis, new_min);
+
+	assert(is_valid());
+}
+
+
+inline void	axial_box::set_axis_max(int axis, float new_max)
+{
+	assert(is_valid());
+
+	m_max.set(axis, new_max);
+
+	assert(is_valid());
+}
+
+
+// @@ should probably un-inline this...
+inline void	axial_box::set_enclosing(const vec3& v)
+// Ensure that the box encloses the point.
+{
+	m_min.x = fmin(m_min.x, v.x);
+	m_min.y = fmin(m_min.y, v.y);
+	m_min.z = fmin(m_min.z, v.z);
+	m_max.x = fmax(m_max.x, v.x);
+	m_max.y = fmax(m_max.y, v.y);
+	m_max.z = fmax(m_max.z, v.z);
+
+	assert(is_valid());
+}
+
+
+inline bool	axial_box::encloses(const vec3& v, float tolerance) const
+// Return true if the given point is inside this box.
+{
+	assert(is_valid());
+
+	return
+		m_min.x <= v.x + tolerance
+		&& m_min.y <= v.y + tolerance
+		&& m_min.z <= v.z + tolerance
+		&& m_max.x >= v.x - tolerance
+		&& m_max.y >= v.y - tolerance
+		&& m_max.z >= v.z - tolerance;
+}
+
+
+inline bool	axial_box::encloses(const axial_box& b, float tolerance) const
+// Return true if this box encloses the given box.
+{
+	assert(is_valid());
+
+	return encloses(b.m_min, tolerance) && encloses(b.m_max, tolerance);
+}
+
+
+inline void	axial_box::set_intersection(const axial_box& b)
+// Set this to intersection(this, b)
+{
+	if (b.m_min.x > m_min.x) m_min.x = b.m_min.x;
+	if (b.m_min.y > m_min.y) m_min.y = b.m_min.y;
+	if (b.m_min.z > m_min.z) m_min.z = b.m_min.z;
+
+	if (b.m_max.x < m_max.x) m_max.x = b.m_max.x;
+	if (b.m_max.y < m_max.y) m_max.y = b.m_max.y;
+	if (b.m_max.z < m_max.z) m_max.z = b.m_max.z;
+}
+
+
+#endif // AXIAL_BOX_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libgeometry/collision.cpp
diff -u gnash/libgeometry/collision.cpp:1.2 gnash/libgeometry/collision.cpp:1.3
--- gnash/libgeometry/collision.cpp:1.2	Wed Feb  1 23:58:32 2006
+++ gnash/libgeometry/collision.cpp	Sun Feb 26 15:49:30 2006
@@ -1,91 +1,91 @@
-// collision.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Misc helper code for doing collision tests.
-
-
-#include <float.h>
-
-#include "collision.h"
-
-
-ray_query::ray_query(const vec3& start_pos, const vec3& unit_direction, float \
                distance)
-	:
-	m_start(start_pos),
-	m_end(start_pos + unit_direction * distance),
-	m_dir(unit_direction),
-	m_length(distance)
-{
-	assert(m_length > 0);
-
-	compute_inverses();
-}
-
-
-ray_query::ray_query(start_end_enum e, const vec3& start_pos, const vec3& end_pos)
-	:
-	m_start(start_pos),
-	m_end(end_pos)
-{
-	vec3	disp = m_end - m_start;
-	m_length = disp.magnitude();
-	assert(m_length > 0);
-
-	if (m_length > 0)
-	{
-		m_dir = disp;
-		m_dir /= m_length;
-	}
-
-	compute_inverses();
-}
-
-
-void	ray_query::compute_inverses()
-// Compute m_inv_dir and m_inv_displacement
-{
-	vec3	disp(m_end);
-	disp -= m_start;
-
-	// Threshold, below which we don't want to compute 1/x.
-	static const float	DANGER_LIMIT_MIN = 1e-25f;
-
-	for (int i = 0; i < 3; i++)
-	{
-		// m_inv_dir
-		float	comp = m_dir[i];
-		if (fabsf(comp) <= DANGER_LIMIT_MIN)
-		{
-			m_inv_dir[i] = -FLT_MAX;	// arbitrary crap
-			m_dir[i] = 0;	// don't tolerate tiny tiny component.  Client code will know not \
                to use this axis.
-		}
-		else
-		{
-			m_inv_dir[i] = 1.0f / comp;
-		}
-
-		// m_inv_displacement
-		comp = disp[i];
-		if (fabsf(comp) <= DANGER_LIMIT_MIN)
-		{
-			m_inv_displacement[i] = -FLT_MAX;	// arbitrary crap
-			m_dir[i] = 0;	// don't tolerate tiny tiny component.  Client code will know not \
                to use this axis.
-		}
-		else
-		{
-			m_inv_displacement[i] = 1.0f / comp;
-		}
-	}
-}
-
-
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// collision.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Misc helper code for doing collision tests.
+
+
+#include <float.h>
+
+#include "collision.h"
+
+
+ray_query::ray_query(const vec3& start_pos, const vec3& unit_direction, float \
distance) +	:
+	m_start(start_pos),
+	m_end(start_pos + unit_direction * distance),
+	m_dir(unit_direction),
+	m_length(distance)
+{
+	assert(m_length > 0);
+
+	compute_inverses();
+}
+
+
+ray_query::ray_query(start_end_enum e, const vec3& start_pos, const vec3& end_pos)
+	:
+	m_start(start_pos),
+	m_end(end_pos)
+{
+	vec3	disp = m_end - m_start;
+	m_length = disp.magnitude();
+	assert(m_length > 0);
+
+	if (m_length > 0)
+	{
+		m_dir = disp;
+		m_dir /= m_length;
+	}
+
+	compute_inverses();
+}
+
+
+void	ray_query::compute_inverses()
+// Compute m_inv_dir and m_inv_displacement
+{
+	vec3	disp(m_end);
+	disp -= m_start;
+
+	// Threshold, below which we don't want to compute 1/x.
+	static const float	DANGER_LIMIT_MIN = 1e-25f;
+
+	for (int i = 0; i < 3; i++)
+	{
+		// m_inv_dir
+		float	comp = m_dir[i];
+		if (fabsf(comp) <= DANGER_LIMIT_MIN)
+		{
+			m_inv_dir[i] = -FLT_MAX;	// arbitrary crap
+			m_dir[i] = 0;	// don't tolerate tiny tiny component.  Client code will know not \
to use this axis. +		}
+		else
+		{
+			m_inv_dir[i] = 1.0f / comp;
+		}
+
+		// m_inv_displacement
+		comp = disp[i];
+		if (fabsf(comp) <= DANGER_LIMIT_MIN)
+		{
+			m_inv_displacement[i] = -FLT_MAX;	// arbitrary crap
+			m_dir[i] = 0;	// don't tolerate tiny tiny component.  Client code will know not \
to use this axis. +		}
+		else
+		{
+			m_inv_displacement[i] = 1.0f / comp;
+		}
+	}
+}
+
+
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libgeometry/collision.h
diff -u gnash/libgeometry/collision.h:1.2 gnash/libgeometry/collision.h:1.3
--- gnash/libgeometry/collision.h:1.2	Wed Feb  1 23:58:32 2006
+++ gnash/libgeometry/collision.h	Sun Feb 26 15:49:30 2006
@@ -1,45 +1,45 @@
-// collision.h	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Basic types needed for doing collision queries.
-
-
-#ifndef COLLISION_H
-#define COLLISION_H
-
-
-#include "geometry.h"
-
-
-// Actually a line-segment query.
-struct ray_query
-{
-	ray_query(const vec3& start_pos, const vec3& unit_direction, float distance);
-
-	enum start_end_enum { start_end };
-	ray_query(start_end_enum e, const vec3& start_pos, const vec3& end_pos);
-
-	// Internal helper to compute m_inv_*
-	void	compute_inverses();
-
-	vec3	m_start;
-	vec3	m_end;
-	vec3	m_dir;
-	vec3	m_inv_dir;	// 1/x for each component of m_dir
-	vec3	m_inv_displacement;	// 1/x for each component of (m_end - m_start)
-	float	m_length;
-};
-
-
-#endif // COLLISION_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
-
+// collision.h	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Basic types needed for doing collision queries.
+
+
+#ifndef COLLISION_H
+#define COLLISION_H
+
+
+#include "geometry.h"
+
+
+// Actually a line-segment query.
+struct ray_query
+{
+	ray_query(const vec3& start_pos, const vec3& unit_direction, float distance);
+
+	enum start_end_enum { start_end };
+	ray_query(start_end_enum e, const vec3& start_pos, const vec3& end_pos);
+
+	// Internal helper to compute m_inv_*
+	void	compute_inverses();
+
+	vec3	m_start;
+	vec3	m_end;
+	vec3	m_dir;
+	vec3	m_inv_dir;	// 1/x for each component of m_dir
+	vec3	m_inv_displacement;	// 1/x for each component of (m_end - m_start)
+	float	m_length;
+};
+
+
+#endif // COLLISION_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
+
Index: gnash/libgeometry/kd_tree_dynamic.cpp
diff -u gnash/libgeometry/kd_tree_dynamic.cpp:1.4 \
                gnash/libgeometry/kd_tree_dynamic.cpp:1.5
--- gnash/libgeometry/kd_tree_dynamic.cpp:1.4	Sat Feb 25 03:54:03 2006
+++ gnash/libgeometry/kd_tree_dynamic.cpp	Sun Feb 26 15:49:30 2006
@@ -1,1261 +1,1263 @@
-// kd_tree_dynamic.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Utility kd-tree structure, for building kd-trees from triangle
-// soup.
-
-
-#include "kd_tree_dynamic.h"
-#include "tu_file.h"
-#include <float.h>
-
-
-static const float	EPSILON = 1e-4f;
-static const int	LEAF_FACE_COUNT = 6;
-static const int	MAX_SPLIT_PLANES_TESTED = 10;
-
-//#define CARVE_OFF_SPACE
-//#define ADHOC_METRIC
-#define MACDONALD_AND_BOOTH_METRIC
-//#define SORT_VERTICES
-
-// A higher value for MAX_SPLIT_PLANES_TESTED gives faster trees;
-// e.g. on one dataset, MSPT=100 gives 10% faster queries than
-// MSPT=10.  But the tree building is much slower.
-
-// On one dataset I checked, SORT_VERTICES makes queries ~10% faster.
-// On most others, it seemed to make no difference.  It takes extra
-// time to do the sort, though.
-
-
-float	kd_tree_dynamic::face::get_min_coord(int axis, const std::vector<vec3>& verts) \
                const
-{
-	float	minval = verts[m_vi[0]][axis];
-	minval = fmin(minval, verts[m_vi[1]][axis]);
-	minval = fmin(minval, verts[m_vi[2]][axis]);
-	return minval;
-}
-
-
-float	kd_tree_dynamic::face::get_max_coord(int axis, const std::vector<vec3>& verts) \
                const
-{
-	float	maxval = verts[m_vi[0]][axis];
-	maxval = fmax(maxval, verts[m_vi[1]][axis]);
-	maxval = fmax(maxval, verts[m_vi[2]][axis]);
-	return maxval;
-}
-
-
-void split_mesh(
-	std::vector<vec3>* verts0,
-	std::vector<int>* tris0,
-	std::vector<vec3>* verts1,
-	std::vector<int>* tris1,
-	int vert_count,
-	const vec3 verts[],
-	int triangle_count,
-	const int indices[],
-	int axis,
-	float offset)
-// Divide a mesh into two pieces, roughly along the plane [axis]=offset.
-// Assign faces to one side or the other based on centroid.
-{
-	assert(verts0 && tris0 && verts1 && tris1);
-	assert(verts0->size() == 0);
-	assert(tris0->size() == 0);
-	assert(verts1->size() == 0);
-	assert(tris1->size() == 0);
-
-	// Remap table from verts array to new verts0/1 arrays.
-	hash<int, int>	verts_to_verts0;
-	hash<int, int>	verts_to_verts1;
-
-	// Divide the faces.
-	for (int i = 0; i < triangle_count; i++)
-	{
-		int	index = i * 3;
-		int	v[3] = {
-			indices[index],
-			indices[index + 1],
-			indices[index + 2]
-		};
-
-		float centroid = (verts[v[0]][axis] + verts[v[1]][axis] + verts[v[2]][axis]) / \
                3.0f;
-
-		if (centroid < offset)
-		{
-			// Put this face into verts0/tris0
-			for (int ax = 0; ax < 3; ax++)
-			{
-				int	new_index;
-				if (verts_to_verts0.get(v[ax], &new_index))
-				{
-					// OK.
-				}
-				else
-				{
-					// Must add.
-					new_index = verts0->size();
-					verts_to_verts0.add(v[ax], new_index);
-					verts0->push_back(verts[v[ax]]);
-				}
-				tris0->push_back(new_index);
-			}
-		}
-		else
-		{
-			// Put this face into verts1/tris1
-			for (int ax = 0; ax < 3; ax++)
-			{
-				int	new_index;
-				if (verts_to_verts1.get(v[ax], &new_index))
-				{
-					// OK.
-				}
-				else
-				{
-					// Must add.
-					new_index = verts1->size();
-					verts_to_verts1.add(v[ax], new_index);
-					verts1->push_back(verts[v[ax]]);
-				}
-				tris1->push_back(new_index);
-			}
-		}
-	}
-}
-
-
-static void	remap_vertex_order(kd_tree_dynamic::node* node, hash<int,int>* \
                map_indices_old_to_new, int* new_vertex_count)
-// Traverse this tree in depth-first order, and remap the vertex
-// indices to go in order.
-{
-	if (node == NULL) return;
-
-	if (node->m_leaf)
-	{
-		for (int i = 0, n = node->m_leaf->m_faces.size(); i < n; i++)
-		{
-			kd_tree_dynamic::face*	f = &node->m_leaf->m_faces[i];
-			for (int vi = 0; vi < 3; vi++)
-			{
-				int	old_index = f->m_vi[vi];
-				int	new_index = *new_vertex_count;
-				if (map_indices_old_to_new->get(old_index, &new_index))
-				{
-					// vert is already remapped; use existing mapping.
-				}
-				else
-				{
-					// vert is not remapped yet; remap it.
-					map_indices_old_to_new->add(old_index, new_index);
-					(*new_vertex_count) += 1;
-				}
-
-				// Remap.
-				f->m_vi[vi] = new_index;
-			}
-		}
-	}
-	else
-	{
-		remap_vertex_order(node->m_neg, map_indices_old_to_new, new_vertex_count);
-		remap_vertex_order(node->m_pos, map_indices_old_to_new, new_vertex_count);
-	}
-}
-
-
-/*static*/ void	kd_tree_dynamic::build_trees(
-	std::vector<kd_tree_dynamic*>* treelist,
-	int vert_count,
-	const vec3 verts[],
-	int triangle_count,
-	const int indices[]
-	)
-// Build one or more kd trees to represent the given mesh.
-{
-	if (vert_count >= 65536)
-	{
-		// Too many verts for one tree; subdivide.
-		axial_box	bound;
-		compute_actual_bounds(&bound, vert_count, verts);
-
-		int	longest_axis = bound.get_longest_axis();
-		float	offset = bound.get_center()[longest_axis];
-
-		std::vector<vec3>	verts0, verts1;
-		std::vector<int>	tris0, tris1;
-		split_mesh(
-			&verts0,
-			&tris0,
-			&verts1,
-			&tris1,
-			vert_count,
-			verts,
-			triangle_count,
-			indices,
-			longest_axis,
-			offset);
-
-		if ((int) verts0.size() >= vert_count || (int) verts1.size() >= vert_count)
-		{
-			// Trouble: couldn't reduce vert count by
-			// splitting.
-			assert(0);
-			// log error
-			return;
-		}
-
-		build_trees(treelist, verts0.size(), &verts0[0], tris0.size() / 3, &tris0[0]);
-		build_trees(treelist, verts1.size(), &verts1[0], tris1.size() / 3, &tris1[0]);
-
-		return;
-	}
-
-	treelist->push_back(new kd_tree_dynamic(vert_count, verts, triangle_count, \
                indices));
-}
-
-
-kd_tree_dynamic::kd_tree_dynamic(
-	int vert_count,
-	const vec3 verts[],
-	int triangle_count,
-	const int indices[])
-// Constructor; build the kd-tree from the given triangle soup.
-{
-	assert(vert_count > 0 && vert_count < 65536);
-	assert(triangle_count > 0);
-
-	// Copy the verts.
-	m_verts.resize(vert_count);
-	memcpy(&m_verts[0], verts, sizeof(verts[0]) * vert_count);
-
-	// Make a mutable array of faces, and also compute our bounds.
-	axial_box	bounds(axial_box::INVALID, vec3::flt_max, vec3::minus_flt_max);
-	std::vector<face>	faces;
-	for (int i = 0; i < triangle_count; i++)
-	{
-		face	f;
-		f.m_vi[0] = indices[i * 3 + 0];
-		f.m_vi[1] = indices[i * 3 + 1];
-		f.m_vi[2] = indices[i * 3 + 2];
-		f.m_flags = 0;	// @@ should be a way to initialize this
-
-		faces.push_back(f);
-
-		// Update bounds.
-		bounds.set_enclosing(m_verts[f.m_vi[0]]);
-		bounds.set_enclosing(m_verts[f.m_vi[1]]);
-		bounds.set_enclosing(m_verts[f.m_vi[2]]);
-	}
-
-	m_bound = bounds;
-
-	m_root = build_tree(1, faces.size(), &faces[0], bounds);
-
-#ifdef SORT_VERTICES
-	// Sort vertices in the order they first appear in a
-	// depth-first traversal of the tree.  Idea is to exploit
-	// cache coherency when traversing tree.
-
-	hash<int, int>	map_indices_old_to_new;
-	int	new_vertex_count = 0;
-	remap_vertex_order(m_root, &map_indices_old_to_new, &new_vertex_count);
-
-	assert(new_vertex_count == m_verts.size());
-
-	// Make the re-ordered vertex buffer.
-	std::vector<vec3>	new_verts;
-	new_verts.resize(new_vertex_count);
-	for (int i = 0; i < m_verts.size(); i++)
-	{
-		int	new_index = 0;
-		bool	found = map_indices_old_to_new.get(i, &new_index);
-		assert(found);
-		if (found)
-		{
-			new_verts[new_index] = m_verts[i];
-		}
-	}
-
-	// Use the new verts.
-	m_verts = new_verts;
-#endif // SORT_VERTICES
-}
-
-
-kd_tree_dynamic::~kd_tree_dynamic()
-// Destructor; make sure to delete the stuff we allocated.
-{
-	delete m_root;
-}
-
-
-kd_tree_dynamic::node*	kd_tree_dynamic::build_tree(int depth, int face_count, face \
                faces[], const axial_box& bounds)
-// Recursively build a kd-tree from the given set of faces.  Return
-// the root of the tree.
-{
-	assert(face_count >= 0);
-
-	if (face_count == 0)
-	{
-		return NULL;
-	}
-
-	// Should we make a leaf?
-	if (face_count <= LEAF_FACE_COUNT)
-	{
-		// Make a leaf
-		node*	n = new node;
-		n->m_leaf = new leaf;
-		n->m_leaf->m_faces.resize(face_count);
-		memcpy(&(n->m_leaf->m_faces[0]), faces, sizeof(faces[0]) * face_count);
-
-		return n;
-	}
-
-	// TODO I believe it may be better to try partitioning planes,
-	// which separate the faces according to triangle centroid (or
-	// centroid of the bound?), and then compute the actual
-	// splitting planes based on the partition.  I think this
-	// helps avoid some bad situations with large triangles, where
-	// a large tri keeps getting pushed down deeper and deeper.
-	//
-	// Currently we generate a candidate neg_offset plane
-	// directly, and include all triangles fully behind the
-	// neg_offset in one child, which may tend to be unbalanced.
-
-	// Find a good splitting plane.
-	float	best_split_quality = 0.0f;
-	int	best_split_axis = -1;
-	float	best_split_neg_offset = 0.0f;
-	float	best_split_pos_offset = 0.0f;
-
-	for (int axis = 0; axis < 3; axis++)
-	{
-		if (bounds.get_extent()[axis] < EPSILON)
-		{
-			// Don't try to divide 
-			continue;
-		}
-
-		// Try offsets that correspond to existing face boundaries.
-		int	step_size = 1;
-		if (face_count > MAX_SPLIT_PLANES_TESTED)
-		{
-			// For the sake of speed & sanity, only try the bounds
-			// of every N faces.
-			step_size = face_count / MAX_SPLIT_PLANES_TESTED;
-		}
-		assert(step_size > 0);
-
-		float	last_offset_tried = -FLT_MAX;
-		float	pos_offset = 0;
-		for (int i = 0; i < face_count; i += step_size)
-		{
-			float	neg_offset = faces[i].get_max_coord(axis, m_verts);
-
-			if (fabsf(neg_offset - last_offset_tried) < EPSILON)
-			{
-				// Already tried this.
-				continue;
-			}
-			
-			last_offset_tried = neg_offset;
-
-			// How good is this split?
-			float	quality = evaluate_split(depth, face_count, faces, bounds, axis, \
                neg_offset, &pos_offset);
-			if (quality > best_split_quality)
-			{
-				// Best so far.
-				best_split_quality = quality;
-				best_split_axis = axis;
-				best_split_neg_offset = neg_offset;
-				best_split_pos_offset = pos_offset;
-			}
-		}
-	}
-
-	if (best_split_axis == -1)
-	{
-		// Couldn't find any acceptable split!
-		// Make a leaf.
-		node*	n = new node;
-		n->m_leaf = new leaf;
-		n->m_leaf->m_faces.resize(face_count);
-		memcpy(&(n->m_leaf->m_faces[0]), faces, sizeof(faces[0]) * face_count);
-
-		return n;
-	}
-	else
-	{
-		// Make the split.
-		int	back_end = 0;
-		int	front_end = 0;
-
-		// We use the implicit node bounds, not the actual bounds of
-		// the face sets, for computing split quality etc, since that
-		// is what the run-time structures have when they are
-		// computing query results.
-
-		axial_box	back_bounds(bounds);
-		back_bounds.set_axis_max(best_split_axis, best_split_neg_offset);
-
-		axial_box	front_bounds(bounds);
-		front_bounds.set_axis_min(best_split_axis, best_split_pos_offset);
-
-		node*	n = new node;
-		n->m_axis = best_split_axis;
-		n->m_neg_offset = best_split_neg_offset;
-		n->m_pos_offset = best_split_pos_offset;
-
-		// Recursively build sub-trees.
-		do_split(&back_end, &front_end, face_count, faces, best_split_axis, \
                best_split_neg_offset, best_split_pos_offset);
-
-		n->m_neg = build_tree(depth + 1, back_end, faces + 0, back_bounds);
-		n->m_pos = build_tree(depth + 1, front_end - back_end, faces + back_end, \
                front_bounds);
-
-		return n;
-	}
-}
-
-
-kd_tree_dynamic::node::node()
-// Default constructor, null everything out.
-	:
-	m_neg(0),
-	m_pos(0),
-	m_leaf(0),
-	m_axis(0),
-	m_neg_offset(0.0f),
-	m_pos_offset(0.0f)
-{
-}
-
-
-kd_tree_dynamic::node::~node()
-// Destructor, delete children if any.
-{
-	delete m_neg;
-	delete m_pos;
-	delete m_leaf;
-}
-
-
-bool	kd_tree_dynamic::node::is_valid() const
-{
-	return
-		// internal node.
-		(m_leaf == 0
-		 && m_axis >= 0
-		 && m_axis < 3)
-		||
-		// leaf node
-		(m_leaf != 0
-		 && m_neg == 0
-		 && m_pos == 0)
-		;
-}
-
-
-void	kd_tree_dynamic::compute_actual_bounds(axial_box* result, int face_count, face \
                faces[])
-// Compute the actual bounding box around the given list of faces.
-{
-	assert(face_count > 0);
-
-	result->set_min_max_invalid(vec3::flt_max, vec3::minus_flt_max);
-	
-	for (int i = 0; i < face_count; i++)
-	{
-		const face&	f = faces[i];
-
-		// Update bounds.
-		result->set_enclosing(m_verts[f.m_vi[0]]);
-		result->set_enclosing(m_verts[f.m_vi[1]]);
-		result->set_enclosing(m_verts[f.m_vi[2]]);
-	}
-}
-
-
-/*static*/ void	kd_tree_dynamic::compute_actual_bounds(axial_box* result, int \
                vert_count, const vec3 verts[])
-// Compute the actual bounding box around the given list of faces.
-{
-	assert(vert_count > 0);
-
-	result->set_min_max_invalid(vec3::flt_max, vec3::minus_flt_max);
-	
-	for (int i = 0; i < vert_count; i++)
-	{
-		// Update bounds.
-		result->set_enclosing(verts[i]);
-	}
-}
-
-
-static int	classify_coord(float coord, float offset)
-{
-	if (coord < offset /* - EPSILON */)
-	{
-		return -1;
-	}
-	else if (coord > offset /* + EPSILON */)
-	{
-		return 1;
-	}
-	else
-	{
-		return 0;
-	}
-}
-
-
-void	kd_tree_dynamic::do_split(
-	int* back_end,
-	int* front_end,
-	int face_count,
-	face faces[],
-	int axis,
-	float neg_offset,
-	float pos_offset)
-// Classify the given faces as either negative or positive.  The faces
-// within faces[] are shuffled.  On exit, the faces[] array has the
-// following segments:
-//
-// [0, *neg_end-1]              -- the faces behind the plane axis=neg_offset
-// [neg_end, face_count-1]      -- the faces in front of axis=pos_offset (i.e. \
                everything else)
-//
-// pos_offset must be placed so that it catches everything not on the
-// negative side; this routine asserts against that.
-{
-	// We do an in-place sort.  During sorting, faces[] is divided
-	// into three segments: at the beginning are the front faces,
-	// in the middle are the unsorted faces, and at the end are
-	// the back faces.  when we sort a face, we swap it into the
-	// next position for either the back or front face segment.
-	int	back_faces_end = 0;
-	int	front_faces_start = face_count;
-	//int	next_face = 0;
-	
-	while (back_faces_end < front_faces_start)
-	{
-		const face&	f = faces[back_faces_end];
-
-		int	result = classify_face(f, axis, neg_offset);
-		if (result == -1)
-		{
-			// Behind.  Leave this face where it is, and
-			// bump back_faces_end so it's now in the back
-			// faces segment.
-			back_faces_end++;
-		}
-		else
-		{
-			// In front.
-			assert(f.get_min_coord(axis, m_verts) >= pos_offset);	// should not have any \
                crossing faces!
-
-			// Swap this face up to the beginning of the front faces.
-			front_faces_start--;
-			swap(&faces[back_faces_end], &faces[front_faces_start]);
-		}
-	}
-
-	*back_end = back_faces_end;
-	*front_end = face_count;
-	assert(*back_end <= *front_end);
-	assert(*front_end == face_count);
-
-#if 0
-	std::vector<face>	back_faces;
-	std::vector<face>	front_faces;
-
-	for (int i = 0; i < face_count; i++)
-	{
-		const face&	f = faces[i];
-
-		int	result = classify_face(f, axis, neg_offset);
-		if (result == -1)
-		{
-			// Behind.
-			back_faces.push_back(f);
-		}
-		else
-		{
-			assert(f.get_min_coord(axis, m_verts) >= pos_offset);	// should not have any \
                crossing faces!
-
-			front_faces.push_back(f);
-		}
-	}
-
-	assert(back_faces.size() + front_faces.size() == face_count);
-
-	*back_end = back_faces.size();
-	if (back_faces.size() > 0)
-	{
-		memcpy(&(faces[0]), &(back_faces[0]), back_faces.size() * sizeof(faces[0]));
-	}
-
-	*front_end = *back_end + front_faces.size();
-	if (front_faces.size() > 0)
-	{
-		memcpy(&faces[*back_end], &front_faces[0], front_faces.size() * sizeof(faces[0]));
-	}
-
-	assert(*back_end <= *front_end);
-	assert(*front_end == face_count);
-#endif // 0
-}
-
-
-float	kd_tree_dynamic::evaluate_split(
-	int depth,
-	int face_count,
-	face faces[],
-	const axial_box& bounds,
-	int axis,
-	float neg_offset,
-	float* pos_offset)
-// Compute the "value" of splitting the given set of faces, bounded by
-// the given box, along the plane [axis]=offset.  A value of 0 means
-// that a split is possible, but has no value.  A negative value means
-// that the split is not valid at all.  Positive values indicate
-// increasing goodness.
-//
-// *pos_offset is computed based on the minimum coord of the faces
-// that don't fit behind the neg_offset.  Could be greater or less
-// than neg_offset.
-//
-// This is kinda heuristicy -- it's where the "special sauce" comes
-// in.
-{
-	// Count the faces that will end up in the groups
-	// back,front.
-	int	back_count = 0;
-	int	front_count = 0;
-
-	*pos_offset = bounds.get_max()[axis];
-
-	for (int i = 0; i < face_count; i++)
-	{
-		const face&	f = faces[i];
-
-		int	result = classify_face(f, axis, neg_offset);
-		if (result == -1)
-		{
-			// Neg.
-			back_count++;
-		}
-		else
-		{
-			// Pos.
-			front_count++;
-
-			// Update *pos_offset so it contains this face.
-			float	mincoord = f.get_min_coord(axis, m_verts);
-			if (mincoord < *pos_offset)
-			{
-				*pos_offset = mincoord;
-				assert(mincoord >= bounds.get_min()[axis]);
-			}
-		}
-	}
-
-	if ((back_count == 0 && *pos_offset - EPSILON <= bounds.get_min()[axis])
-	    || (front_count == 0 && neg_offset + EPSILON >= bounds.get_max()[axis]))
-	{
-		// No faces are separated by this split; this split is
-		// entirely useless.
-		return -1;
-	}
-
-	//float	center = bounds.get_center().get(axis);
-	//float	extent = bounds.get_extent().get(axis);
-
-	axial_box	back_bounds(bounds);
-	back_bounds.set_axis_max(axis, neg_offset);
-	axial_box	front_bounds(bounds);
-	front_bounds.set_axis_min(axis, *pos_offset);
-
-// Probably not a win.
-#ifdef CARVE_OFF_SPACE
-	// Special case: if the plane carves off space at one side or the
-	// other, without orphaning any faces, then we reward a large
-	// empty space.
-	float	space_quality = 0.0f;
-	if (front_count == 0)
-	{
-		// All the faces are in back -- reward a bigger empty front volume.
-		return space_quality = back_count * front_bounds.get_surface_area();
-	}
-	else if (back_count == 0)
-	{
-		// All the faces are in front.
-		return space_quality = front_count * back_bounds.get_surface_area();
-	}
-#endif // CARVE_OFF_SPACE
-
-
-// My ad-hoc metric
-#ifdef ADHOC_METRIC
-	// compute a figure for how close to the center this splitting
-	// plane is.  Normalize in [0,1].
-	float	volume_balance = 1.0f - fabsf(center - (neg_offset + *pos_offset) / 2) / \
                extent;
-
-	// Compute a figure for how well we balance the faces.  0 == bad,
-	// 1 == good.
-	float	face_balance = 1.0f - (fabsf(float(front_count - back_count))) / face_count;
-
-	float	split_quality = bounds.get_surface_area() * volume_balance * face_balance;
-
-	return split_quality;
-#endif // ADHOC_METRIC
-
-
-#ifdef MACDONALD_AND_BOOTH_METRIC
-	// MacDonald and Booth's metric, as quoted by Havran, endorsed by
-	// Ville Miettinen and Atman Binstock:
-
-	float	cost_back = back_bounds.get_surface_area() * (back_count);
-	float	cost_front = front_bounds.get_surface_area() * (front_count);
-
-	float	havran_cost = cost_back + cost_front;
-
-	float	parent_cost = bounds.get_surface_area() * face_count;
-
-	// We need to turn the cost into a quality, so subtract it from a
-	// big number.
-	return  parent_cost - havran_cost;
-
-#endif // MACDONALD_AND_BOOTH_METRIC
-}
-
-
-int	kd_tree_dynamic::classify_face(const face& f, int axis, float offset)
-// Return -1 if the face is entirely behind the plane [axis]=offset
-// Return 0 if the face spans the plane.
-// Return 1 if the face is entirely in front of the plane.
-//
-// "behind" means on the negative side, "in front" means on the
-// positive side.
-{
-	assert(axis >= 0 && axis < 3);
-
-	bool	has_front_vert = false;
-	bool	has_back_vert = false;
-
-	for (int i = 0; i < 3; i++)
-	{
-		float	coord = m_verts[f.m_vi[i]].get(axis);
-		int	cr = classify_coord(coord, offset);
-
-		if (cr == -1)
-		{
-			has_back_vert = true;
-		}
-		else if (cr == 1)
-		{
-			has_front_vert = true;
-		}
-	}
-
-	if (has_front_vert && has_back_vert)
-	{
-		return 0;	// crossing.
-	}
-	else if (has_front_vert)
-	{
-		return 1;	// all verts in front.
-	}
-	else if (has_back_vert)
-	{
-		return -1;	// all verts in back.
-	}
-	else
-	{
-		// Face is ON the plane.
-		return 0;	// call it "crossing".
-	}
-}
-
-
-void	kd_tree_dynamic::clip_faces(std::vector<face>* faces, int axis, float offset)
-// Clip the given faces against the plane [axis]=offset.  Update the
-// *faces array with the newly clipped faces; add faces and verts as
-// necessary.
-{
-	int	original_face_count = faces->size();
-
-	for (int i = 0; i < original_face_count; i++)
-	{
-		face	f = (*faces)[i];
-
-		if (classify_face(f, axis, offset) == 0)
-		{
-			// Crossing face, probably needs to be clipped.
-
-			int	vr[3];
-			vr[0] = classify_coord(m_verts[f.m_vi[0]].get(axis), offset);
-			vr[1] = classify_coord(m_verts[f.m_vi[1]].get(axis), offset);
-			vr[2] = classify_coord(m_verts[f.m_vi[2]].get(axis), offset);
-
-			// Sort...
-			if (vr[0] > vr[1])
-			{
-				swap(&vr[0], &vr[1]);
-				swap(&f.m_vi[0], &f.m_vi[1]);
-			}
-			if (vr[1] > vr[2])
-			{
-				swap(&vr[1], &vr[2]);
-				swap(&f.m_vi[1], &f.m_vi[2]);
-			}
-			if (vr[0] > vr[1])
-			{
-				swap(&vr[0], &vr[1]);
-				swap(&f.m_vi[0], &f.m_vi[1]);
-			}
-
-			if (vr[0] == 0 || vr[2] == 0)
-			{
-				// Face doesn't actually cross; no need to clip.
-				continue;
-			}
-			
-			const vec3	v[3] = {
-				m_verts[f.m_vi[0]],
-				m_verts[f.m_vi[1]],
-				m_verts[f.m_vi[2]]
-			};
-
-			// Different cases.
-			if (vr[1] == 0)
-			{
-				// Middle vert is on the plane; make two triangles.
-
-				// One new vert.
-				float	lerper = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
-				vec3	new_vert = v[0] * (1 - lerper) + v[2] * lerper;
-				new_vert.set(axis, offset);	// make damn sure
-				assert(new_vert.checknan() == false);
-
-				int	new_vi = m_verts.size();
-				m_verts.push_back(new_vert);
-
-				// New faces.
-				face	f0 = f;
-				f0.m_vi[2] = new_vi;
-				(*faces)[i] = f0;	// replace original face
-
-				assert(classify_face(f0, axis, offset) <= 0);
-				
-				face	f1 = f;
-				f1.m_vi[0] = new_vi;
-				faces->push_back(f1);	// add a face
-
-				assert(classify_face(f1, axis, offset) >= 0);
-			}
-			else if (vr[1] < 0)
-			{
-				// Middle vert is behind the plane.
-				// Make two tris behind, one in front.
-
-				// Two new verts.
-				float	lerper0 = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
-				vec3	new_vert0 = v[0] * (1 - lerper0) + v[2] * lerper0;
-				new_vert0.set(axis, offset);	// make damn sure
-				assert(new_vert0.checknan() == false);
-				int	new_vi0 = m_verts.size();
-				m_verts.push_back(new_vert0);
-
-				float	lerper1 = (offset - v[1].get(axis)) / (v[2].get(axis) - v[1].get(axis));
-				vec3	new_vert1 = v[1] * (1 - lerper1) + v[2] * lerper1;
-				new_vert1.set(axis, offset);	// make damn sure
-				assert(new_vert1.checknan() == false);
-				int	new_vi1 = m_verts.size();
-				m_verts.push_back(new_vert1);
-
-				// New faces.
-				face	f0 = f;
-				f0.m_vi[2] = new_vi0;
-				(*faces)[i] = f0;
-
-				assert(classify_face(f0, axis, offset) <= 0);
-
-				face	f1 = f;
-				f1.m_vi[0] = new_vi0;
-				f1.m_vi[2] = new_vi1;
-				faces->push_back(f1);
-
-				assert(classify_face(f1, axis, offset) <= 0);
-
-				face	f2 = f;
-				f2.m_vi[0] = new_vi0;
-				f2.m_vi[1] = new_vi1;
-				faces->push_back(f2);
-
-				assert(classify_face(f2, axis, offset) >= 0);
-			}
-			else if (vr[1] > 0)
-			{
-				// Middle vert is in front of the plane.
-				// Make on tri behind, two in front.
-
-				// Two new verts.
-				float	lerper1 = (offset - v[0].get(axis)) / (v[1].get(axis) - v[0].get(axis));
-				vec3	new_vert1 = v[0] * (1 - lerper1) + v[1] * lerper1;
-				new_vert1.set(axis, offset);	// make damn sure
-				assert(new_vert1.checknan() == false);
-				int	new_vi1 = m_verts.size();
-				m_verts.push_back(new_vert1);
-
-				float	lerper2 = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
-				vec3	new_vert2 = v[0] * (1 - lerper2) + v[2] * lerper2;
-				new_vert2.set(axis, offset);	// make damn sure
-				assert(new_vert2.checknan() == false);
-				int	new_vi2 = m_verts.size();
-				m_verts.push_back(new_vert2);
-
-				// New faces.
-				face	f0 = f;
-				f0.m_vi[1] = new_vi1;
-				f0.m_vi[2] = new_vi2;
-				(*faces)[i] = f0;
-
-				assert(classify_face(f0, axis, offset) <= 0);
-
-				face	f1 = f;
-				f1.m_vi[0] = new_vi1;
-				f1.m_vi[2] = new_vi2;
-				faces->push_back(f1);
-
-				assert(classify_face(f1, axis, offset) >= 0);
-
-				face	f2 = f;
-				f2.m_vi[0] = new_vi2;
-				faces->push_back(f2);
-
-				assert(classify_face(f2, axis, offset) >= 0);
-			}
-		}
-		
-	}
-}
-
-
-void	kd_tree_dynamic::dump(tu_file* out) const
-// Dump some debug info.
-{
-	node*	n = m_root;
-
-	if (n) n->dump(out, 0);
-}
-
-
-void	kd_tree_dynamic::node::dump(tu_file* out, int depth) const
-{
-	for (int i = 0; i < depth; i++) { out->write_byte(' '); }
-
-	if (m_leaf)
-	{
-		int	face_count = m_leaf->m_faces.size();
-		char	c = ("0123456789X")[iclamp(face_count, 0, 10)];
-		out->write_byte(c);
-		out->write_byte('\n');
-	}
-	else
-	{
-		out->write_byte('+');
-		out->write_byte('\n');
-		if (m_neg)
-		{
-			m_neg->dump(out, depth + 1);
-		}
-		if (m_pos)
-		{
-			m_pos->dump(out, depth + 1);
-		}
-	}
-}
-
-
-#include "postscript.h"
-
-
-static const int	X_SIZE = 612;
-static const int	Y_SIZE = 792;
-static const int	MARGIN = 20;
-
-
-struct kd_diagram_dump_info
-{
-	postscript*	m_ps;
-	int	m_depth;
-	int	m_max_depth;
-	std::vector<int>	m_width;	// width of the tree at each level
-	std::vector<int>	m_max_width;
-	std::vector<int>	m_count;	// width so far, during drawing
-
-	// Some stats.
-	int	m_leaf_count;
-	int	m_node_count;
-	int	m_face_count;
-	int	m_max_faces_in_leaf;
-	int	m_null_children;
-	int	m_depth_times_faces;
-
-	kd_diagram_dump_info()
-		:
-		m_ps(0),
-		m_depth(0),
-		m_max_depth(0),
-		m_leaf_count(0),
-		m_node_count(0),
-		m_face_count(0),
-		m_max_faces_in_leaf(0),
-		m_null_children(0),
-		m_depth_times_faces(0)
-	{
-	}
-
-	void	get_node_coords(int* x, int* y)
-	{
-		float	h_spacing = (X_SIZE - MARGIN*2) / float(m_max_width.back());
-		float	adjust = 1.0f;
-		if (m_width[m_depth] > 1) adjust = (m_max_width[m_depth] + 1) / \
                float(m_width[m_depth] + 1);
-
-		*x = int(X_SIZE/2 + (m_count[m_depth] - m_width[m_depth] / 2) * h_spacing * \
                adjust);
-		*y = Y_SIZE - MARGIN - m_depth * (Y_SIZE - MARGIN*2) / (m_max_depth + 1);
-	}
-
-	void	update_stats(kd_tree_dynamic::node* n)
-	// Add this node's stats to our totals.
-	{
-		if (n == 0)
-		{
-			m_null_children++;
-		}
-		else if (n->m_leaf)
-		{
-			m_leaf_count++;
-
-			assert(n->m_leaf);
-			int	faces = n->m_leaf->m_faces.size();
-			m_face_count += faces;
-			if (faces > m_max_faces_in_leaf) m_max_faces_in_leaf = faces;
-
-			m_depth_times_faces += (m_depth + 1) * faces;
-		}
-		else
-		{
-			m_node_count++;
-		}
-	}
-
-	void	diagram_stats()
-	// Print some textual stats to the given Postscript stream.
-	{
-		float	x = MARGIN;
-		float	y = Y_SIZE - MARGIN;
-		const float	LINE = 10;
-		y -= LINE; m_ps->printf(x, y, "Loose KD-Tree");
-#ifdef MACDONALD_AND_BOOTH_METRIC
-		y -= LINE; m_ps->printf(x, y, "using MacDonald and Booth metric");
-#endif
-#ifdef ADHOC_METRIC
-		y -= LINE; m_ps->printf(x, y, "using ad-hoc metric");
-#endif
-#ifdef CARVE_OFF_SPACE
-		y -= LINE; m_ps->printf(x, y, "using carve-off-space heuristic");
-#endif
-		y -= LINE; m_ps->printf(x, y, "leaf face count limit: %d", LEAF_FACE_COUNT);
-		y -= LINE; m_ps->printf(x, y, "face ct: %d", m_face_count);
-		y -= LINE; m_ps->printf(x, y, "leaf ct: %d", m_leaf_count);
-		y -= LINE; m_ps->printf(x, y, "node ct: %d", m_node_count);
-		y -= LINE; m_ps->printf(x, y, "null ct: %d", m_null_children);
-		y -= LINE; m_ps->printf(x, y, "worst leaf: %d faces", m_max_faces_in_leaf);
-		y -= LINE; m_ps->printf(x, y, "max depth: %d", m_max_depth + 1);
-		y -= LINE; m_ps->printf(x, y, "avg face depth: %3.2f", m_depth_times_faces / \
                float(m_face_count));
-	}
-};
-
-
-static void	node_traverse(kd_diagram_dump_info* inf, kd_tree_dynamic::node* n)
-// Traverse the tree, updating inf->m_width.  That's helpful for
-// formatting the diagram.
-{
-	inf->update_stats(n);
-
-	if (inf->m_depth > inf->m_max_depth)
-	{
-		inf->m_max_depth = inf->m_depth;
-	}
-
-	while ((int) inf->m_width.size() <= inf->m_max_depth)
-	{
-		inf->m_width.push_back(0);
-	}
-
-	inf->m_width[inf->m_depth]++;	// count this node.
-
-	if (n && n->m_leaf == 0)
-	{
-		// Count children.
-		inf->m_depth++;
-		node_traverse(inf, n->m_neg);
-		node_traverse(inf, n->m_pos);
-		inf->m_depth--;
-
-		assert(inf->m_depth >= 0);
-	}
-}
-
-
-static void	node_diagram(kd_diagram_dump_info* inf, kd_tree_dynamic::node* n, int \
                parent_x, int parent_y)
-// Emit Postscript drawing commands to diagram this node in the tree.
-{
-	// Diagram this node.
-	int	x, y;
-	inf->get_node_coords(&x, &y);
-
-	// Line to parent.
-	inf->m_ps->line((float) x, (float) y, (float) parent_x, (float) parent_y);
-
-	if (n == 0)
-	{
-		// NULL --> show a circle w/ slash
-		inf->m_ps->circle((float) x, (float) y, 1);
-		inf->m_ps->line((float) x + 1, (float) y + 1, (float) x - 1, (float) y - 1);
-	}
-	else if (n->m_leaf)
-	{
-		// Leaf.  Draw concentric circles.
-		int	face_count = n->m_leaf->m_faces.size();
-		for (int i = 0; i < face_count + 1; i++)
-		{
-			inf->m_ps->circle((float) x, (float) y, 2 + i * 1.0f);
-		}
-	}
-	else
-	{
-		// Internal node.
-
-		// draw disk
-		inf->m_ps->disk((float) x, (float) y, 1);
-
-		// draw children.
-		inf->m_depth++;
-		node_diagram(inf, n->m_neg, x, y);
-		node_diagram(inf, n->m_pos, x, y);
-		inf->m_depth--;
-
-		assert(inf->m_depth >= 0);
-	}
-
-	// count this node.
-	inf->m_count[inf->m_depth]++;
-}
-
-
-void	kd_tree_dynamic::diagram_dump(tu_file* out) const
-// Generate a Postscript schematic diagram of the tree.
-{
-	postscript*	ps = new postscript(out, "kd-tree diagram");
-	
-	kd_diagram_dump_info	inf;
-	inf.m_ps = ps;
-	inf.m_depth = 0;
-
-	node_traverse(&inf, m_root);
-
-	while ((int) inf.m_count.size() <= inf.m_max_depth)
-	{
-		inf.m_count.push_back(0);
-	}
-
-	int	max_width = 1;
-	for (int i = 0; i <= inf.m_max_depth; i++)
-	{
-		if (inf.m_width[i] > max_width)
-		{
-			max_width = inf.m_width[i];
-		}
-		inf.m_max_width.push_back(max_width);
-	}
-
-	inf.diagram_stats();
-
-	int	root_x = 0, root_y = 0;
-	inf.get_node_coords(&root_x, &root_y);
-
-	node_diagram(&inf, m_root, root_x, root_y);
-
-	delete ps;
-}
-
-
-static void	mesh_node_dump(
-	postscript* ps,
-	int axis,
-	kd_tree_dynamic::node* node,
-	const axial_box& bound,
-	const std::vector<vec3>& verts)
-// Draw faces under node, projected onto given axis plane.  Scale to fit paper.
-{
-	if (node == NULL) return;
-
-	if (node->m_leaf)
-	{
-		// Draw faces.
-		for (int i = 0, n = node->m_leaf->m_faces.size(); i < n; i++)
-		{
-			vec3	v[3] = {
-				verts[node->m_leaf->m_faces[i].m_vi[0]],
-				verts[node->m_leaf->m_faces[i].m_vi[1]],
-				verts[node->m_leaf->m_faces[i].m_vi[2]]
-			};
-
-			float	x[3], y[3];
-			int	axis1 = (axis + 1) % 3;
-			int	axis2 = (axis + 2) % 3;
-			for (int vert = 0; vert < 3; vert++)
-			{
-				x[vert] = (v[vert][axis1] - bound.get_min()[axis1]) / bound.get_size()[axis1];
-				y[vert] = (v[vert][axis2] - bound.get_min()[axis2]) / bound.get_size()[axis2];
-
-				x[vert] = flerp(float(MARGIN), float(X_SIZE - MARGIN), x[vert]);
-				y[vert] = flerp(float(MARGIN), float(Y_SIZE - MARGIN), y[vert]);
-			}
-
-			// Draw triangle.
-			ps->line(x[0], y[0], x[1], y[1]);
-			ps->line(x[1], y[1], x[2], y[2]);
-			ps->line(x[2], y[2], x[0], y[0]);
-		}
-
-		return;
-	}
-	
-	mesh_node_dump(ps, axis, node->m_neg, bound, verts);
-	mesh_node_dump(ps, axis, node->m_pos, bound, verts);
-}
-
-
-void	kd_tree_dynamic::mesh_diagram_dump(tu_file* out, int axis) const
-// Generate a Postscript schematic diagram of the mesh, orthogonal to
-// the given axis.
-{
-	postscript*	ps = new postscript(out, "kd-tree diagram");
-	
-	mesh_node_dump(ps, axis, m_root, get_bound(), m_verts);
-
-	delete ps;
-}
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8 
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// kd_tree_dynamic.cpp	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Utility kd-tree structure, for building kd-trees from triangle
+// soup.
+
+
+#include <stdio.h>
+
+#include "kd_tree_dynamic.h"
+#include "tu_file.h"
+#include <float.h>
+
+
+static const float	EPSILON = 1e-4f;
+static const int	LEAF_FACE_COUNT = 6;
+static const int	MAX_SPLIT_PLANES_TESTED = 10;
+
+//#define CARVE_OFF_SPACE
+//#define ADHOC_METRIC
+#define MACDONALD_AND_BOOTH_METRIC
+//#define SORT_VERTICES
+
+// A higher value for MAX_SPLIT_PLANES_TESTED gives faster trees;
+// e.g. on one dataset, MSPT=100 gives 10% faster queries than
+// MSPT=10.  But the tree building is much slower.
+
+// On one dataset I checked, SORT_VERTICES makes queries ~10% faster.
+// On most others, it seemed to make no difference.  It takes extra
+// time to do the sort, though.
+
+
+float	kd_tree_dynamic::face::get_min_coord(int axis, const std::vector<vec3>& verts) \
const +{
+	float	minval = verts[m_vi[0]][axis];
+	minval = fmin(minval, verts[m_vi[1]][axis]);
+	minval = fmin(minval, verts[m_vi[2]][axis]);
+	return minval;
+}
+
+
+float	kd_tree_dynamic::face::get_max_coord(int axis, const std::vector<vec3>& verts) \
const +{
+	float	maxval = verts[m_vi[0]][axis];
+	maxval = fmax(maxval, verts[m_vi[1]][axis]);
+	maxval = fmax(maxval, verts[m_vi[2]][axis]);
+	return maxval;
+}
+
+
+void split_mesh(
+	std::vector<vec3>* verts0,
+	std::vector<int>* tris0,
+	std::vector<vec3>* verts1,
+	std::vector<int>* tris1,
+	int vert_count,
+	const vec3 verts[],
+	int triangle_count,
+	const int indices[],
+	int axis,
+	float offset)
+// Divide a mesh into two pieces, roughly along the plane [axis]=offset.
+// Assign faces to one side or the other based on centroid.
+{
+	assert(verts0 && tris0 && verts1 && tris1);
+	assert(verts0->size() == 0);
+	assert(tris0->size() == 0);
+	assert(verts1->size() == 0);
+	assert(tris1->size() == 0);
+
+	// Remap table from verts array to new verts0/1 arrays.
+	hash<int, int>	verts_to_verts0;
+	hash<int, int>	verts_to_verts1;
+
+	// Divide the faces.
+	for (int i = 0; i < triangle_count; i++)
+	{
+		int	index = i * 3;
+		int	v[3] = {
+			indices[index],
+			indices[index + 1],
+			indices[index + 2]
+		};
+
+		float centroid = (verts[v[0]][axis] + verts[v[1]][axis] + verts[v[2]][axis]) / \
3.0f; +
+		if (centroid < offset)
+		{
+			// Put this face into verts0/tris0
+			for (int ax = 0; ax < 3; ax++)
+			{
+				int	new_index;
+				if (verts_to_verts0.get(v[ax], &new_index))
+				{
+					// OK.
+				}
+				else
+				{
+					// Must add.
+					new_index = verts0->size();
+					verts_to_verts0.add(v[ax], new_index);
+					verts0->push_back(verts[v[ax]]);
+				}
+				tris0->push_back(new_index);
+			}
+		}
+		else
+		{
+			// Put this face into verts1/tris1
+			for (int ax = 0; ax < 3; ax++)
+			{
+				int	new_index;
+				if (verts_to_verts1.get(v[ax], &new_index))
+				{
+					// OK.
+				}
+				else
+				{
+					// Must add.
+					new_index = verts1->size();
+					verts_to_verts1.add(v[ax], new_index);
+					verts1->push_back(verts[v[ax]]);
+				}
+				tris1->push_back(new_index);
+			}
+		}
+	}
+}
+
+
+static void	remap_vertex_order(kd_tree_dynamic::node* node, hash<int,int>* \
map_indices_old_to_new, int* new_vertex_count) +// Traverse this tree in depth-first \
order, and remap the vertex +// indices to go in order.
+{
+	if (node == NULL) return;
+
+	if (node->m_leaf)
+	{
+		for (int i = 0, n = node->m_leaf->m_faces.size(); i < n; i++)
+		{
+			kd_tree_dynamic::face*	f = &node->m_leaf->m_faces[i];
+			for (int vi = 0; vi < 3; vi++)
+			{
+				int	old_index = f->m_vi[vi];
+				int	new_index = *new_vertex_count;
+				if (map_indices_old_to_new->get(old_index, &new_index))
+				{
+					// vert is already remapped; use existing mapping.
+				}
+				else
+				{
+					// vert is not remapped yet; remap it.
+					map_indices_old_to_new->add(old_index, new_index);
+					(*new_vertex_count) += 1;
+				}
+
+				// Remap.
+				f->m_vi[vi] = new_index;
+			}
+		}
+	}
+	else
+	{
+		remap_vertex_order(node->m_neg, map_indices_old_to_new, new_vertex_count);
+		remap_vertex_order(node->m_pos, map_indices_old_to_new, new_vertex_count);
+	}
+}
+
+
+/*static*/ void	kd_tree_dynamic::build_trees(
+	std::vector<kd_tree_dynamic*>* treelist,
+	int vert_count,
+	const vec3 verts[],
+	int triangle_count,
+	const int indices[]
+	)
+// Build one or more kd trees to represent the given mesh.
+{
+	if (vert_count >= 65536)
+	{
+		// Too many verts for one tree; subdivide.
+		axial_box	bound;
+		compute_actual_bounds(&bound, vert_count, verts);
+
+		int	longest_axis = bound.get_longest_axis();
+		float	offset = bound.get_center()[longest_axis];
+
+		std::vector<vec3>	verts0, verts1;
+		std::vector<int>	tris0, tris1;
+		split_mesh(
+			&verts0,
+			&tris0,
+			&verts1,
+			&tris1,
+			vert_count,
+			verts,
+			triangle_count,
+			indices,
+			longest_axis,
+			offset);
+
+		if ((int) verts0.size() >= vert_count || (int) verts1.size() >= vert_count)
+		{
+			// Trouble: couldn't reduce vert count by
+			// splitting.
+			assert(0);
+			// log error
+			return;
+		}
+
+		build_trees(treelist, verts0.size(), &verts0[0], tris0.size() / 3, &tris0[0]);
+		build_trees(treelist, verts1.size(), &verts1[0], tris1.size() / 3, &tris1[0]);
+
+		return;
+	}
+
+	treelist->push_back(new kd_tree_dynamic(vert_count, verts, triangle_count, \
indices)); +}
+
+
+kd_tree_dynamic::kd_tree_dynamic(
+	int vert_count,
+	const vec3 verts[],
+	int triangle_count,
+	const int indices[])
+// Constructor; build the kd-tree from the given triangle soup.
+{
+	assert(vert_count > 0 && vert_count < 65536);
+	assert(triangle_count > 0);
+
+	// Copy the verts.
+	m_verts.resize(vert_count);
+	memcpy(&m_verts[0], verts, sizeof(verts[0]) * vert_count);
+
+	// Make a mutable array of faces, and also compute our bounds.
+	axial_box	bounds(axial_box::INVALID, vec3::flt_max, vec3::minus_flt_max);
+	std::vector<face>	faces;
+	for (int i = 0; i < triangle_count; i++)
+	{
+		face	f;
+		f.m_vi[0] = indices[i * 3 + 0];
+		f.m_vi[1] = indices[i * 3 + 1];
+		f.m_vi[2] = indices[i * 3 + 2];
+		f.m_flags = 0;	// @@ should be a way to initialize this
+
+		faces.push_back(f);
+
+		// Update bounds.
+		bounds.set_enclosing(m_verts[f.m_vi[0]]);
+		bounds.set_enclosing(m_verts[f.m_vi[1]]);
+		bounds.set_enclosing(m_verts[f.m_vi[2]]);
+	}
+
+	m_bound = bounds;
+
+	m_root = build_tree(1, faces.size(), &faces[0], bounds);
+
+#ifdef SORT_VERTICES
+	// Sort vertices in the order they first appear in a
+	// depth-first traversal of the tree.  Idea is to exploit
+	// cache coherency when traversing tree.
+
+	hash<int, int>	map_indices_old_to_new;
+	int	new_vertex_count = 0;
+	remap_vertex_order(m_root, &map_indices_old_to_new, &new_vertex_count);
+
+	assert(new_vertex_count == m_verts.size());
+
+	// Make the re-ordered vertex buffer.
+	std::vector<vec3>	new_verts;
+	new_verts.resize(new_vertex_count);
+	for (int i = 0; i < m_verts.size(); i++)
+	{
+		int	new_index = 0;
+		bool	found = map_indices_old_to_new.get(i, &new_index);
+		assert(found);
+		if (found)
+		{
+			new_verts[new_index] = m_verts[i];
+		}
+	}
+
+	// Use the new verts.
+	m_verts = new_verts;
+#endif // SORT_VERTICES
+}
+
+
+kd_tree_dynamic::~kd_tree_dynamic()
+// Destructor; make sure to delete the stuff we allocated.
+{
+	delete m_root;
+}
+
+
+kd_tree_dynamic::node*	kd_tree_dynamic::build_tree(int depth, int face_count, face \
faces[], const axial_box& bounds) +// Recursively build a kd-tree from the given set \
of faces.  Return +// the root of the tree.
+{
+	assert(face_count >= 0);
+
+	if (face_count == 0)
+	{
+		return NULL;
+	}
+
+	// Should we make a leaf?
+	if (face_count <= LEAF_FACE_COUNT)
+	{
+		// Make a leaf
+		node*	n = new node;
+		n->m_leaf = new leaf;
+		n->m_leaf->m_faces.resize(face_count);
+		memcpy(&(n->m_leaf->m_faces[0]), faces, sizeof(faces[0]) * face_count);
+
+		return n;
+	}
+
+	// TODO I believe it may be better to try partitioning planes,
+	// which separate the faces according to triangle centroid (or
+	// centroid of the bound?), and then compute the actual
+	// splitting planes based on the partition.  I think this
+	// helps avoid some bad situations with large triangles, where
+	// a large tri keeps getting pushed down deeper and deeper.
+	//
+	// Currently we generate a candidate neg_offset plane
+	// directly, and include all triangles fully behind the
+	// neg_offset in one child, which may tend to be unbalanced.
+
+	// Find a good splitting plane.
+	float	best_split_quality = 0.0f;
+	int	best_split_axis = -1;
+	float	best_split_neg_offset = 0.0f;
+	float	best_split_pos_offset = 0.0f;
+
+	for (int axis = 0; axis < 3; axis++)
+	{
+		if (bounds.get_extent()[axis] < EPSILON)
+		{
+			// Don't try to divide 
+			continue;
+		}
+
+		// Try offsets that correspond to existing face boundaries.
+		int	step_size = 1;
+		if (face_count > MAX_SPLIT_PLANES_TESTED)
+		{
+			// For the sake of speed & sanity, only try the bounds
+			// of every N faces.
+			step_size = face_count / MAX_SPLIT_PLANES_TESTED;
+		}
+		assert(step_size > 0);
+
+		float	last_offset_tried = -FLT_MAX;
+		float	pos_offset = 0;
+		for (int i = 0; i < face_count; i += step_size)
+		{
+			float	neg_offset = faces[i].get_max_coord(axis, m_verts);
+
+			if (fabsf(neg_offset - last_offset_tried) < EPSILON)
+			{
+				// Already tried this.
+				continue;
+			}
+			
+			last_offset_tried = neg_offset;
+
+			// How good is this split?
+			float	quality = evaluate_split(depth, face_count, faces, bounds, axis, \
neg_offset, &pos_offset); +			if (quality > best_split_quality)
+			{
+				// Best so far.
+				best_split_quality = quality;
+				best_split_axis = axis;
+				best_split_neg_offset = neg_offset;
+				best_split_pos_offset = pos_offset;
+			}
+		}
+	}
+
+	if (best_split_axis == -1)
+	{
+		// Couldn't find any acceptable split!
+		// Make a leaf.
+		node*	n = new node;
+		n->m_leaf = new leaf;
+		n->m_leaf->m_faces.resize(face_count);
+		memcpy(&(n->m_leaf->m_faces[0]), faces, sizeof(faces[0]) * face_count);
+
+		return n;
+	}
+	else
+	{
+		// Make the split.
+		int	back_end = 0;
+		int	front_end = 0;
+
+		// We use the implicit node bounds, not the actual bounds of
+		// the face sets, for computing split quality etc, since that
+		// is what the run-time structures have when they are
+		// computing query results.
+
+		axial_box	back_bounds(bounds);
+		back_bounds.set_axis_max(best_split_axis, best_split_neg_offset);
+
+		axial_box	front_bounds(bounds);
+		front_bounds.set_axis_min(best_split_axis, best_split_pos_offset);
+
+		node*	n = new node;
+		n->m_axis = best_split_axis;
+		n->m_neg_offset = best_split_neg_offset;
+		n->m_pos_offset = best_split_pos_offset;
+
+		// Recursively build sub-trees.
+		do_split(&back_end, &front_end, face_count, faces, best_split_axis, \
best_split_neg_offset, best_split_pos_offset); +
+		n->m_neg = build_tree(depth + 1, back_end, faces + 0, back_bounds);
+		n->m_pos = build_tree(depth + 1, front_end - back_end, faces + back_end, \
front_bounds); +
+		return n;
+	}
+}
+
+
+kd_tree_dynamic::node::node()
+// Default constructor, null everything out.
+	:
+	m_neg(0),
+	m_pos(0),
+	m_leaf(0),
+	m_axis(0),
+	m_neg_offset(0.0f),
+	m_pos_offset(0.0f)
+{
+}
+
+
+kd_tree_dynamic::node::~node()
+// Destructor, delete children if any.
+{
+	delete m_neg;
+	delete m_pos;
+	delete m_leaf;
+}
+
+
+bool	kd_tree_dynamic::node::is_valid() const
+{
+	return
+		// internal node.
+		(m_leaf == 0
+		 && m_axis >= 0
+		 && m_axis < 3)
+		||
+		// leaf node
+		(m_leaf != 0
+		 && m_neg == 0
+		 && m_pos == 0)
+		;
+}
+
+
+void	kd_tree_dynamic::compute_actual_bounds(axial_box* result, int face_count, face \
faces[]) +// Compute the actual bounding box around the given list of faces.
+{
+	assert(face_count > 0);
+
+	result->set_min_max_invalid(vec3::flt_max, vec3::minus_flt_max);
+	
+	for (int i = 0; i < face_count; i++)
+	{
+		const face&	f = faces[i];
+
+		// Update bounds.
+		result->set_enclosing(m_verts[f.m_vi[0]]);
+		result->set_enclosing(m_verts[f.m_vi[1]]);
+		result->set_enclosing(m_verts[f.m_vi[2]]);
+	}
+}
+
+
+/*static*/ void	kd_tree_dynamic::compute_actual_bounds(axial_box* result, int \
vert_count, const vec3 verts[]) +// Compute the actual bounding box around the given \
list of faces. +{
+	assert(vert_count > 0);
+
+	result->set_min_max_invalid(vec3::flt_max, vec3::minus_flt_max);
+	
+	for (int i = 0; i < vert_count; i++)
+	{
+		// Update bounds.
+		result->set_enclosing(verts[i]);
+	}
+}
+
+
+static int	classify_coord(float coord, float offset)
+{
+	if (coord < offset /* - EPSILON */)
+	{
+		return -1;
+	}
+	else if (coord > offset /* + EPSILON */)
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+
+void	kd_tree_dynamic::do_split(
+	int* back_end,
+	int* front_end,
+	int face_count,
+	face faces[],
+	int axis,
+	float neg_offset,
+	float pos_offset)
+// Classify the given faces as either negative or positive.  The faces
+// within faces[] are shuffled.  On exit, the faces[] array has the
+// following segments:
+//
+// [0, *neg_end-1]              -- the faces behind the plane axis=neg_offset
+// [neg_end, face_count-1]      -- the faces in front of axis=pos_offset (i.e. \
everything else) +//
+// pos_offset must be placed so that it catches everything not on the
+// negative side; this routine asserts against that.
+{
+	// We do an in-place sort.  During sorting, faces[] is divided
+	// into three segments: at the beginning are the front faces,
+	// in the middle are the unsorted faces, and at the end are
+	// the back faces.  when we sort a face, we swap it into the
+	// next position for either the back or front face segment.
+	int	back_faces_end = 0;
+	int	front_faces_start = face_count;
+	//int	next_face = 0;
+	
+	while (back_faces_end < front_faces_start)
+	{
+		const face&	f = faces[back_faces_end];
+
+		int	result = classify_face(f, axis, neg_offset);
+		if (result == -1)
+		{
+			// Behind.  Leave this face where it is, and
+			// bump back_faces_end so it's now in the back
+			// faces segment.
+			back_faces_end++;
+		}
+		else
+		{
+			// In front.
+			assert(f.get_min_coord(axis, m_verts) >= pos_offset);	// should not have any \
crossing faces! +
+			// Swap this face up to the beginning of the front faces.
+			front_faces_start--;
+			swap(&faces[back_faces_end], &faces[front_faces_start]);
+		}
+	}
+
+	*back_end = back_faces_end;
+	*front_end = face_count;
+	assert(*back_end <= *front_end);
+	assert(*front_end == face_count);
+
+#if 0
+	std::vector<face>	back_faces;
+	std::vector<face>	front_faces;
+
+	for (int i = 0; i < face_count; i++)
+	{
+		const face&	f = faces[i];
+
+		int	result = classify_face(f, axis, neg_offset);
+		if (result == -1)
+		{
+			// Behind.
+			back_faces.push_back(f);
+		}
+		else
+		{
+			assert(f.get_min_coord(axis, m_verts) >= pos_offset);	// should not have any \
crossing faces! +
+			front_faces.push_back(f);
+		}
+	}
+
+	assert(back_faces.size() + front_faces.size() == face_count);
+
+	*back_end = back_faces.size();
+	if (back_faces.size() > 0)
+	{
+		memcpy(&(faces[0]), &(back_faces[0]), back_faces.size() * sizeof(faces[0]));
+	}
+
+	*front_end = *back_end + front_faces.size();
+	if (front_faces.size() > 0)
+	{
+		memcpy(&faces[*back_end], &front_faces[0], front_faces.size() * sizeof(faces[0]));
+	}
+
+	assert(*back_end <= *front_end);
+	assert(*front_end == face_count);
+#endif // 0
+}
+
+
+float	kd_tree_dynamic::evaluate_split(
+	int depth,
+	int face_count,
+	face faces[],
+	const axial_box& bounds,
+	int axis,
+	float neg_offset,
+	float* pos_offset)
+// Compute the "value" of splitting the given set of faces, bounded by
+// the given box, along the plane [axis]=offset.  A value of 0 means
+// that a split is possible, but has no value.  A negative value means
+// that the split is not valid at all.  Positive values indicate
+// increasing goodness.
+//
+// *pos_offset is computed based on the minimum coord of the faces
+// that don't fit behind the neg_offset.  Could be greater or less
+// than neg_offset.
+//
+// This is kinda heuristicy -- it's where the "special sauce" comes
+// in.
+{
+	// Count the faces that will end up in the groups
+	// back,front.
+	int	back_count = 0;
+	int	front_count = 0;
+
+	*pos_offset = bounds.get_max()[axis];
+
+	for (int i = 0; i < face_count; i++)
+	{
+		const face&	f = faces[i];
+
+		int	result = classify_face(f, axis, neg_offset);
+		if (result == -1)
+		{
+			// Neg.
+			back_count++;
+		}
+		else
+		{
+			// Pos.
+			front_count++;
+
+			// Update *pos_offset so it contains this face.
+			float	mincoord = f.get_min_coord(axis, m_verts);
+			if (mincoord < *pos_offset)
+			{
+				*pos_offset = mincoord;
+				assert(mincoord >= bounds.get_min()[axis]);
+			}
+		}
+	}
+
+	if ((back_count == 0 && *pos_offset - EPSILON <= bounds.get_min()[axis])
+	    || (front_count == 0 && neg_offset + EPSILON >= bounds.get_max()[axis]))
+	{
+		// No faces are separated by this split; this split is
+		// entirely useless.
+		return -1;
+	}
+
+	//float	center = bounds.get_center().get(axis);
+	//float	extent = bounds.get_extent().get(axis);
+
+	axial_box	back_bounds(bounds);
+	back_bounds.set_axis_max(axis, neg_offset);
+	axial_box	front_bounds(bounds);
+	front_bounds.set_axis_min(axis, *pos_offset);
+
+// Probably not a win.
+#ifdef CARVE_OFF_SPACE
+	// Special case: if the plane carves off space at one side or the
+	// other, without orphaning any faces, then we reward a large
+	// empty space.
+	float	space_quality = 0.0f;
+	if (front_count == 0)
+	{
+		// All the faces are in back -- reward a bigger empty front volume.
+		return space_quality = back_count * front_bounds.get_surface_area();
+	}
+	else if (back_count == 0)
+	{
+		// All the faces are in front.
+		return space_quality = front_count * back_bounds.get_surface_area();
+	}
+#endif // CARVE_OFF_SPACE
+
+
+// My ad-hoc metric
+#ifdef ADHOC_METRIC
+	// compute a figure for how close to the center this splitting
+	// plane is.  Normalize in [0,1].
+	float	volume_balance = 1.0f - fabsf(center - (neg_offset + *pos_offset) / 2) / \
extent; +
+	// Compute a figure for how well we balance the faces.  0 == bad,
+	// 1 == good.
+	float	face_balance = 1.0f - (fabsf(float(front_count - back_count))) / face_count;
+
+	float	split_quality = bounds.get_surface_area() * volume_balance * face_balance;
+
+	return split_quality;
+#endif // ADHOC_METRIC
+
+
+#ifdef MACDONALD_AND_BOOTH_METRIC
+	// MacDonald and Booth's metric, as quoted by Havran, endorsed by
+	// Ville Miettinen and Atman Binstock:
+
+	float	cost_back = back_bounds.get_surface_area() * (back_count);
+	float	cost_front = front_bounds.get_surface_area() * (front_count);
+
+	float	havran_cost = cost_back + cost_front;
+
+	float	parent_cost = bounds.get_surface_area() * face_count;
+
+	// We need to turn the cost into a quality, so subtract it from a
+	// big number.
+	return  parent_cost - havran_cost;
+
+#endif // MACDONALD_AND_BOOTH_METRIC
+}
+
+
+int	kd_tree_dynamic::classify_face(const face& f, int axis, float offset)
+// Return -1 if the face is entirely behind the plane [axis]=offset
+// Return 0 if the face spans the plane.
+// Return 1 if the face is entirely in front of the plane.
+//
+// "behind" means on the negative side, "in front" means on the
+// positive side.
+{
+	assert(axis >= 0 && axis < 3);
+
+	bool	has_front_vert = false;
+	bool	has_back_vert = false;
+
+	for (int i = 0; i < 3; i++)
+	{
+		float	coord = m_verts[f.m_vi[i]].get(axis);
+		int	cr = classify_coord(coord, offset);
+
+		if (cr == -1)
+		{
+			has_back_vert = true;
+		}
+		else if (cr == 1)
+		{
+			has_front_vert = true;
+		}
+	}
+
+	if (has_front_vert && has_back_vert)
+	{
+		return 0;	// crossing.
+	}
+	else if (has_front_vert)
+	{
+		return 1;	// all verts in front.
+	}
+	else if (has_back_vert)
+	{
+		return -1;	// all verts in back.
+	}
+	else
+	{
+		// Face is ON the plane.
+		return 0;	// call it "crossing".
+	}
+}
+
+
+void	kd_tree_dynamic::clip_faces(std::vector<face>* faces, int axis, float offset)
+// Clip the given faces against the plane [axis]=offset.  Update the
+// *faces array with the newly clipped faces; add faces and verts as
+// necessary.
+{
+	int	original_face_count = faces->size();
+
+	for (int i = 0; i < original_face_count; i++)
+	{
+		face	f = (*faces)[i];
+
+		if (classify_face(f, axis, offset) == 0)
+		{
+			// Crossing face, probably needs to be clipped.
+
+			int	vr[3];
+			vr[0] = classify_coord(m_verts[f.m_vi[0]].get(axis), offset);
+			vr[1] = classify_coord(m_verts[f.m_vi[1]].get(axis), offset);
+			vr[2] = classify_coord(m_verts[f.m_vi[2]].get(axis), offset);
+
+			// Sort...
+			if (vr[0] > vr[1])
+			{
+				swap(&vr[0], &vr[1]);
+				swap(&f.m_vi[0], &f.m_vi[1]);
+			}
+			if (vr[1] > vr[2])
+			{
+				swap(&vr[1], &vr[2]);
+				swap(&f.m_vi[1], &f.m_vi[2]);
+			}
+			if (vr[0] > vr[1])
+			{
+				swap(&vr[0], &vr[1]);
+				swap(&f.m_vi[0], &f.m_vi[1]);
+			}
+
+			if (vr[0] == 0 || vr[2] == 0)
+			{
+				// Face doesn't actually cross; no need to clip.
+				continue;
+			}
+			
+			const vec3	v[3] = {
+				m_verts[f.m_vi[0]],
+				m_verts[f.m_vi[1]],
+				m_verts[f.m_vi[2]]
+			};
+
+			// Different cases.
+			if (vr[1] == 0)
+			{
+				// Middle vert is on the plane; make two triangles.
+
+				// One new vert.
+				float	lerper = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
+				vec3	new_vert = v[0] * (1 - lerper) + v[2] * lerper;
+				new_vert.set(axis, offset);	// make damn sure
+				assert(new_vert.checknan() == false);
+
+				int	new_vi = m_verts.size();
+				m_verts.push_back(new_vert);
+
+				// New faces.
+				face	f0 = f;
+				f0.m_vi[2] = new_vi;
+				(*faces)[i] = f0;	// replace original face
+
+				assert(classify_face(f0, axis, offset) <= 0);
+				
+				face	f1 = f;
+				f1.m_vi[0] = new_vi;
+				faces->push_back(f1);	// add a face
+
+				assert(classify_face(f1, axis, offset) >= 0);
+			}
+			else if (vr[1] < 0)
+			{
+				// Middle vert is behind the plane.
+				// Make two tris behind, one in front.
+
+				// Two new verts.
+				float	lerper0 = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
+				vec3	new_vert0 = v[0] * (1 - lerper0) + v[2] * lerper0;
+				new_vert0.set(axis, offset);	// make damn sure
+				assert(new_vert0.checknan() == false);
+				int	new_vi0 = m_verts.size();
+				m_verts.push_back(new_vert0);
+
+				float	lerper1 = (offset - v[1].get(axis)) / (v[2].get(axis) - v[1].get(axis));
+				vec3	new_vert1 = v[1] * (1 - lerper1) + v[2] * lerper1;
+				new_vert1.set(axis, offset);	// make damn sure
+				assert(new_vert1.checknan() == false);
+				int	new_vi1 = m_verts.size();
+				m_verts.push_back(new_vert1);
+
+				// New faces.
+				face	f0 = f;
+				f0.m_vi[2] = new_vi0;
+				(*faces)[i] = f0;
+
+				assert(classify_face(f0, axis, offset) <= 0);
+
+				face	f1 = f;
+				f1.m_vi[0] = new_vi0;
+				f1.m_vi[2] = new_vi1;
+				faces->push_back(f1);
+
+				assert(classify_face(f1, axis, offset) <= 0);
+
+				face	f2 = f;
+				f2.m_vi[0] = new_vi0;
+				f2.m_vi[1] = new_vi1;
+				faces->push_back(f2);
+
+				assert(classify_face(f2, axis, offset) >= 0);
+			}
+			else if (vr[1] > 0)
+			{
+				// Middle vert is in front of the plane.
+				// Make on tri behind, two in front.
+
+				// Two new verts.
+				float	lerper1 = (offset - v[0].get(axis)) / (v[1].get(axis) - v[0].get(axis));
+				vec3	new_vert1 = v[0] * (1 - lerper1) + v[1] * lerper1;
+				new_vert1.set(axis, offset);	// make damn sure
+				assert(new_vert1.checknan() == false);
+				int	new_vi1 = m_verts.size();
+				m_verts.push_back(new_vert1);
+
+				float	lerper2 = (offset - v[0].get(axis)) / (v[2].get(axis) - v[0].get(axis));
+				vec3	new_vert2 = v[0] * (1 - lerper2) + v[2] * lerper2;
+				new_vert2.set(axis, offset);	// make damn sure
+				assert(new_vert2.checknan() == false);
+				int	new_vi2 = m_verts.size();
+				m_verts.push_back(new_vert2);
+
+				// New faces.
+				face	f0 = f;
+				f0.m_vi[1] = new_vi1;
+				f0.m_vi[2] = new_vi2;
+				(*faces)[i] = f0;
+
+				assert(classify_face(f0, axis, offset) <= 0);
+
+				face	f1 = f;
+				f1.m_vi[0] = new_vi1;
+				f1.m_vi[2] = new_vi2;
+				faces->push_back(f1);
+
+				assert(classify_face(f1, axis, offset) >= 0);
+
+				face	f2 = f;
+				f2.m_vi[0] = new_vi2;
+				faces->push_back(f2);
+
+				assert(classify_face(f2, axis, offset) >= 0);
+			}
+		}
+		
+	}
+}
+
+
+void	kd_tree_dynamic::dump(tu_file* out) const
+// Dump some debug info.
+{
+	node*	n = m_root;
+
+	if (n) n->dump(out, 0);
+}
+
+
+void	kd_tree_dynamic::node::dump(tu_file* out, int depth) const
+{
+	for (int i = 0; i < depth; i++) { out->write_byte(' '); }
+
+	if (m_leaf)
+	{
+		int	face_count = m_leaf->m_faces.size();
+		char	c = ("0123456789X")[iclamp(face_count, 0, 10)];
+		out->write_byte(c);
+		out->write_byte('\n');
+	}
+	else
+	{
+		out->write_byte('+');
+		out->write_byte('\n');
+		if (m_neg)
+		{
+			m_neg->dump(out, depth + 1);
+		}
+		if (m_pos)
+		{
+			m_pos->dump(out, depth + 1);
+		}
+	}
+}
+
+
+#include "postscript.h"
+
+
+static const int	X_SIZE = 612;
+static const int	Y_SIZE = 792;
+static const int	MARGIN = 20;
+
+
+struct kd_diagram_dump_info
+{
+	postscript*	m_ps;
+	int	m_depth;
+	int	m_max_depth;
+	std::vector<int>	m_width;	// width of the tree at each level
+	std::vector<int>	m_max_width;
+	std::vector<int>	m_count;	// width so far, during drawing
+
+	// Some stats.
+	int	m_leaf_count;
+	int	m_node_count;
+	int	m_face_count;
+	int	m_max_faces_in_leaf;
+	int	m_null_children;
+	int	m_depth_times_faces;
+
+	kd_diagram_dump_info()
+		:
+		m_ps(0),
+		m_depth(0),
+		m_max_depth(0),
+		m_leaf_count(0),
+		m_node_count(0),
+		m_face_count(0),
+		m_max_faces_in_leaf(0),
+		m_null_children(0),
+		m_depth_times_faces(0)
+	{
+	}
+
+	void	get_node_coords(int* x, int* y)
+	{
+		float	h_spacing = (X_SIZE - MARGIN*2) / float(m_max_width.back());
+		float	adjust = 1.0f;
+		if (m_width[m_depth] > 1) adjust = (m_max_width[m_depth] + 1) / \
float(m_width[m_depth] + 1); +
+		*x = int(X_SIZE/2 + (m_count[m_depth] - m_width[m_depth] / 2) * h_spacing * \
adjust); +		*y = Y_SIZE - MARGIN - m_depth * (Y_SIZE - MARGIN*2) / (m_max_depth + 1);
+	}
+
+	void	update_stats(kd_tree_dynamic::node* n)
+	// Add this node's stats to our totals.
+	{
+		if (n == 0)
+		{
+			m_null_children++;
+		}
+		else if (n->m_leaf)
+		{
+			m_leaf_count++;
+
+			assert(n->m_leaf);
+			int	faces = n->m_leaf->m_faces.size();
+			m_face_count += faces;
+			if (faces > m_max_faces_in_leaf) m_max_faces_in_leaf = faces;
+
+			m_depth_times_faces += (m_depth + 1) * faces;
+		}
+		else
+		{
+			m_node_count++;
+		}
+	}
+
+	void	diagram_stats()
+	// Print some textual stats to the given Postscript stream.
+	{
+		float	x = MARGIN;
+		float	y = Y_SIZE - MARGIN;
+		const float	LINE = 10;
+		y -= LINE; m_ps->printf(x, y, "Loose KD-Tree");
+#ifdef MACDONALD_AND_BOOTH_METRIC
+		y -= LINE; m_ps->printf(x, y, "using MacDonald and Booth metric");
+#endif
+#ifdef ADHOC_METRIC
+		y -= LINE; m_ps->printf(x, y, "using ad-hoc metric");
+#endif
+#ifdef CARVE_OFF_SPACE
+		y -= LINE; m_ps->printf(x, y, "using carve-off-space heuristic");
+#endif
+		y -= LINE; m_ps->printf(x, y, "leaf face count limit: %d", LEAF_FACE_COUNT);
+		y -= LINE; m_ps->printf(x, y, "face ct: %d", m_face_count);
+		y -= LINE; m_ps->printf(x, y, "leaf ct: %d", m_leaf_count);
+		y -= LINE; m_ps->printf(x, y, "node ct: %d", m_node_count);
+		y -= LINE; m_ps->printf(x, y, "null ct: %d", m_null_children);
+		y -= LINE; m_ps->printf(x, y, "worst leaf: %d faces", m_max_faces_in_leaf);
+		y -= LINE; m_ps->printf(x, y, "max depth: %d", m_max_depth + 1);
+		y -= LINE; m_ps->printf(x, y, "avg face depth: %3.2f", m_depth_times_faces / \
float(m_face_count)); +	}
+};
+
+
+static void	node_traverse(kd_diagram_dump_info* inf, kd_tree_dynamic::node* n)
+// Traverse the tree, updating inf->m_width.  That's helpful for
+// formatting the diagram.
+{
+	inf->update_stats(n);
+
+	if (inf->m_depth > inf->m_max_depth)
+	{
+		inf->m_max_depth = inf->m_depth;
+	}
+
+	while ((int) inf->m_width.size() <= inf->m_max_depth)
+	{
+		inf->m_width.push_back(0);
+	}
+
+	inf->m_width[inf->m_depth]++;	// count this node.
+
+	if (n && n->m_leaf == 0)
+	{
+		// Count children.
+		inf->m_depth++;
+		node_traverse(inf, n->m_neg);
+		node_traverse(inf, n->m_pos);
+		inf->m_depth--;
+
+		assert(inf->m_depth >= 0);
+	}
+}
+
+
+static void	node_diagram(kd_diagram_dump_info* inf, kd_tree_dynamic::node* n, int \
parent_x, int parent_y) +// Emit Postscript drawing commands to diagram this node in \
the tree. +{
+	// Diagram this node.
+	int	x, y;
+	inf->get_node_coords(&x, &y);
+
+	// Line to parent.
+	inf->m_ps->line((float) x, (float) y, (float) parent_x, (float) parent_y);
+
+	if (n == 0)
+	{
+		// NULL --> show a circle w/ slash
+		inf->m_ps->circle((float) x, (float) y, 1);
+		inf->m_ps->line((float) x + 1, (float) y + 1, (float) x - 1, (float) y - 1);
+	}
+	else if (n->m_leaf)
+	{
+		// Leaf.  Draw concentric circles.
+		int	face_count = n->m_leaf->m_faces.size();
+		for (int i = 0; i < face_count + 1; i++)
+		{
+			inf->m_ps->circle((float) x, (float) y, 2 + i * 1.0f);
+		}
+	}
+	else
+	{
+		// Internal node.
+
+		// draw disk
+		inf->m_ps->disk((float) x, (float) y, 1);
+
+		// draw children.
+		inf->m_depth++;
+		node_diagram(inf, n->m_neg, x, y);
+		node_diagram(inf, n->m_pos, x, y);
+		inf->m_depth--;
+
+		assert(inf->m_depth >= 0);
+	}
+
+	// count this node.
+	inf->m_count[inf->m_depth]++;
+}
+
+
+void	kd_tree_dynamic::diagram_dump(tu_file* out) const
+// Generate a Postscript schematic diagram of the tree.
+{
+	postscript*	ps = new postscript(out, "kd-tree diagram");
+	
+	kd_diagram_dump_info	inf;
+	inf.m_ps = ps;
+	inf.m_depth = 0;
+
+	node_traverse(&inf, m_root);
+
+	while ((int) inf.m_count.size() <= inf.m_max_depth)
+	{
+		inf.m_count.push_back(0);
+	}
+
+	int	max_width = 1;
+	for (int i = 0; i <= inf.m_max_depth; i++)
+	{
+		if (inf.m_width[i] > max_width)
+		{
+			max_width = inf.m_width[i];
+		}
+		inf.m_max_width.push_back(max_width);
+	}
+
+	inf.diagram_stats();
+
+	int	root_x = 0, root_y = 0;
+	inf.get_node_coords(&root_x, &root_y);
+
+	node_diagram(&inf, m_root, root_x, root_y);
+
+	delete ps;
+}
+
+
+static void	mesh_node_dump(
+	postscript* ps,
+	int axis,
+	kd_tree_dynamic::node* node,
+	const axial_box& bound,
+	const std::vector<vec3>& verts)
+// Draw faces under node, projected onto given axis plane.  Scale to fit paper.
+{
+	if (node == NULL) return;
+
+	if (node->m_leaf)
+	{
+		// Draw faces.
+		for (int i = 0, n = node->m_leaf->m_faces.size(); i < n; i++)
+		{
+			vec3	v[3] = {
+				verts[node->m_leaf->m_faces[i].m_vi[0]],
+				verts[node->m_leaf->m_faces[i].m_vi[1]],
+				verts[node->m_leaf->m_faces[i].m_vi[2]]
+			};
+
+			float	x[3], y[3];
+			int	axis1 = (axis + 1) % 3;
+			int	axis2 = (axis + 2) % 3;
+			for (int vert = 0; vert < 3; vert++)
+			{
+				x[vert] = (v[vert][axis1] - bound.get_min()[axis1]) / bound.get_size()[axis1];
+				y[vert] = (v[vert][axis2] - bound.get_min()[axis2]) / bound.get_size()[axis2];
+
+				x[vert] = flerp(float(MARGIN), float(X_SIZE - MARGIN), x[vert]);
+				y[vert] = flerp(float(MARGIN), float(Y_SIZE - MARGIN), y[vert]);
+			}
+
+			// Draw triangle.
+			ps->line(x[0], y[0], x[1], y[1]);
+			ps->line(x[1], y[1], x[2], y[2]);
+			ps->line(x[2], y[2], x[0], y[0]);
+		}
+
+		return;
+	}
+	
+	mesh_node_dump(ps, axis, node->m_neg, bound, verts);
+	mesh_node_dump(ps, axis, node->m_pos, bound, verts);
+}
+
+
+void	kd_tree_dynamic::mesh_diagram_dump(tu_file* out, int axis) const
+// Generate a Postscript schematic diagram of the mesh, orthogonal to
+// the given axis.
+{
+	postscript*	ps = new postscript(out, "kd-tree diagram");
+	
+	mesh_node_dump(ps, axis, m_root, get_bound(), m_verts);
+
+	delete ps;
+}
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/libgeometry/kd_tree_dynamic.h
diff -u gnash/libgeometry/kd_tree_dynamic.h:1.3 \
                gnash/libgeometry/kd_tree_dynamic.h:1.4
--- gnash/libgeometry/kd_tree_dynamic.h:1.3	Sat Feb 25 03:54:03 2006
+++ gnash/libgeometry/kd_tree_dynamic.h	Sun Feb 26 15:49:30 2006
@@ -1,150 +1,150 @@
-// kd_tree_dynamic.h	-- by Thatcher Ulrich <tu@tulrich.com>
-
-// This source code has been donated to the Public Domain.  Do
-// whatever you want with it.
-
-// Data structure for building a kd-tree from a triangle mesh.
-
-
-#ifndef KD_TREE_DYNAMIC_H
-#define KD_TREE_DYNAMIC_H
-
-
-#include "container.h"
-#include "geometry.h"
-#include "axial_box.h"
-
-
-class tu_file;
-struct kd_diagram_dump_info;
-
-
-struct kd_tree_dynamic
-{
-	// Build tree(s) from the given mesh.
-	static void	build_trees(
-		std::vector<kd_tree_dynamic*>* treelist,
-		int vert_count,
-		const vec3 verts[],
-		int triangle_count,
-		const int indices[]
-		);
-
-	// vert count must be under 64K
-	kd_tree_dynamic(
-		int vert_count,
-		const vec3 verts[],
-		int triangle_count,
-		const int indices[]
-		);
-	~kd_tree_dynamic();
-
-	struct face
-	{
-		Uint16	m_vi[3];	// indices of verts
-		Uint16	m_flags;
-
-		float	get_min_coord(int axis, const std::vector<vec3>& verts) const;
-		float	get_max_coord(int axis, const std::vector<vec3>& verts) const;
-	};
-
-	struct leaf
-	{
-		std::vector<face>	m_faces;
-	};
-
-	// Internal node.  Not too tidy; would use unions etc. if it were
-	// important.
-	//
-	// This is a "loose" kdtree in the sense that there are two
-	// independent splitting planes on the chosen axis.  This
-	// ensures that all faces can be classified onto one side or
-	// the other.  Almost the same as a binary AABB tree.
-	//
-	//                   |   |
-	//    +--------------+---+----------------+
-	//    |     /   /  \ |   |/       --   \  |
-	//    |    /   /    \+---/     \        \ |
-	//    | |  --- \     |  /|--\   \    /    |
-	//    | |       \ -- | / |   \      /  ---|
-	//    +--------------+---+----------------+
-	//                   |   |
-	//  axis *--> +     neg pos
-	//
-	// So the idea here is that the neg node contains all faces
-	// that are strictly on the negative side of the neg_offset,
-	// and the pos node has all the rest of the faces, and the
-	// pos_offset is placed so that all the pos node faces are
-	// strictly on the positive side of pos_offset.
-	//
-	// Note that the pos and neg nodes could overlap, or could be
-	// disjoint.
-	struct node
-	{
-		node*	m_neg;
-		node*	m_pos;
-		leaf*	m_leaf;
-		int	m_axis;	// split axis: 0 = x, 1 = y, 2 = z
-		float	m_neg_offset;	// where the back split occurs
-		float	m_pos_offset;	// where the front split occurs
-
-		node();
-		~node();
-		bool	is_valid() const;
-		void	dump(tu_file* out, int depth) const;
-	};
-
-	const std::vector<vec3>&	get_verts() const { return m_verts; }
-	const node*	get_root() const { return m_root; }
-	const axial_box&	get_bound() const { return m_bound; }
-
-	// For debugging/evaluating.
-	void	dump(tu_file* out) const;
-	void	diagram_dump(tu_file* out) const;	// make a Postscript diagram.
-	void	mesh_diagram_dump(tu_file* out, int axis) const;	// make a Postscript diagram \
                of the mesh data.
-
-private:
-	static void	compute_actual_bounds(axial_box* result, int vert_count, const vec3 \
                verts[]);
-
-	void	compute_actual_bounds(axial_box* result, int face_count, face faces[]);
-	node*	build_tree(int depth, int face_count, face faces[], const axial_box& bounds);
-
-	void	do_split(
-		int* neg_end,
-		int* pos_end,
-		int face_count,
-		face faces[],
-		int axis,
-		float neg_offset,
-		float pos_offset);
-
-	float	evaluate_split(
-		int depth,
-		int face_count,
-		face faces[],
-		const axial_box& bounds,
-		int axis,
-		float neg_offset,
-		float* pos_offset);
-
-	int	classify_face(const face& f, int axis, float offset);
-
-	// Utility, for  testing a clipping  non-loose kdtree.  Duping
-	// is probably much preferable to clipping though.
-	void	clip_faces(std::vector<face>* faces, int axis, float offset);
-
-	std::vector<vec3>	m_verts;
-	node*	m_root;
-	axial_box	m_bound;
-};
-
-
-#endif // KD_TREE_DYNAMIC_H
-
-
-// Local Variables:
-// mode: C++
-// c-basic-offset: 8
-// tab-width: 8
-// indent-tabs-mode: t
-// End:
+// kd_tree_dynamic.h	-- by Thatcher Ulrich <tu@tulrich.com>
+
+// This source code has been donated to the Public Domain.  Do
+// whatever you want with it.
+
+// Data structure for building a kd-tree from a triangle mesh.
+
+
+#ifndef KD_TREE_DYNAMIC_H
+#define KD_TREE_DYNAMIC_H
+
+
+#include "container.h"
+#include "geometry.h"
+#include "axial_box.h"
+
+
+class tu_file;
+struct kd_diagram_dump_info;
+
+
+struct kd_tree_dynamic
+{
+	// Build tree(s) from the given mesh.
+	static void	build_trees(
+		std::vector<kd_tree_dynamic*>* treelist,
+		int vert_count,
+		const vec3 verts[],
+		int triangle_count,
+		const int indices[]
+		);
+
+	// vert count must be under 64K
+	kd_tree_dynamic(
+		int vert_count,
+		const vec3 verts[],
+		int triangle_count,
+		const int indices[]
+		);
+	~kd_tree_dynamic();
+
+	struct face
+	{
+		Uint16	m_vi[3];	// indices of verts
+		Uint16	m_flags;
+
+		float	get_min_coord(int axis, const std::vector<vec3>& verts) const;
+		float	get_max_coord(int axis, const std::vector<vec3>& verts) const;
+	};
+
+	struct leaf
+	{
+		std::vector<face>	m_faces;
+	};
+
+	// Internal node.  Not too tidy; would use unions etc. if it were
+	// important.
+	//
+	// This is a "loose" kdtree in the sense that there are two
+	// independent splitting planes on the chosen axis.  This
+	// ensures that all faces can be classified onto one side or
+	// the other.  Almost the same as a binary AABB tree.
+	//
+	//                   |   |
+	//    +--------------+---+----------------+
+	//    |     /   /  \ |   |/       --   \  |
+	//    |    /   /    \+---/     \        \ |
+	//    | |  --- \     |  /|--\   \    /    |
+	//    | |       \ -- | / |   \      /  ---|
+	//    +--------------+---+----------------+
+	//                   |   |
+	//  axis *--> +     neg pos
+	//
+	// So the idea here is that the neg node contains all faces
+	// that are strictly on the negative side of the neg_offset,
+	// and the pos node has all the rest of the faces, and the
+	// pos_offset is placed so that all the pos node faces are
+	// strictly on the positive side of pos_offset.
+	//
+	// Note that the pos and neg nodes could overlap, or could be
+	// disjoint.
+	struct node
+	{
+		node*	m_neg;
+		node*	m_pos;
+		leaf*	m_leaf;
+		int	m_axis;	// split axis: 0 = x, 1 = y, 2 = z
+		float	m_neg_offset;	// where the back split occurs
+		float	m_pos_offset;	// where the front split occurs
+
+		node();
+		~node();
+		bool	is_valid() const;
+		void	dump(tu_file* out, int depth) const;
+	};
+
+	const std::vector<vec3>&	get_verts() const { return m_verts; }
+	const node*	get_root() const { return m_root; }
+	const axial_box&	get_bound() const { return m_bound; }
+
+	// For debugging/evaluating.
+	void	dump(tu_file* out) const;
+	void	diagram_dump(tu_file* out) const;	// make a Postscript diagram.
+	void	mesh_diagram_dump(tu_file* out, int axis) const;	// make a Postscript diagram \
of the mesh data. +
+private:
+	static void	compute_actual_bounds(axial_box* result, int vert_count, const vec3 \
verts[]); +
+	void	compute_actual_bounds(axial_box* result, int face_count, face faces[]);
+	node*	build_tree(int depth, int face_count, face faces[], const axial_box& bounds);
+
+	void	do_split(
+		int* neg_end,
+		int* pos_end,
+		int face_count,
+		face faces[],
+		int axis,
+		float neg_offset,
+		float pos_offset);
+
+	float	evaluate_split(
+		int depth,
+		int face_count,
+		face faces[],
+		const axial_box& bounds,
+		int axis,
+		float neg_offset,
+		float* pos_offset);
+
+	int	classify_face(const face& f, int axis, float offset);
+
+	// Utility, for  testing a clipping  non-loose kdtree.  Duping
+	// is probably much preferable to clipping though.
+	void	clip_faces(std::vector<face>* faces, int axis, float offset);
+
+	std::vector<vec3>	m_verts;
+	node*	m_root;
+	axial_box	m_bound;
+};
+
+
+#endif // KD_TREE_DYNAMIC_H
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8
+// tab-width: 8
+// indent-tabs-mode: t
+// End:
Index: gnash/macros/jpeg.m4
diff -u gnash/macros/jpeg.m4:1.7 gnash/macros/jpeg.m4:1.8
--- gnash/macros/jpeg.m4:1.7	Fri Feb 24 00:06:21 2006
+++ gnash/macros/jpeg.m4	Sun Feb 26 15:49:30 2006
@@ -85,7 +85,7 @@
 
       dnl If the header doesn't exist, there is no point looking for the library.
       if test x"${ac_cv_path_jpeg_lib}" = x; then
-        AC_CHECK_LIB(jpeg, jpeg_mem_init, [ac_cv_path_jpeg_lib="-ljpeg"],[
+        AC_CHECK_LIB(jpeg, jpeg_mem_init, [ac_cv_path_jpeg_lib=""],[
           AC_MSG_CHECKING([for libjpeg library])
           libslist="${prefix}/lib64 ${prefix}/lib /usr/lib64 /usr/lib /sw/lib \
/usr/local/lib /home/latest/lib /opt/lib /usr/pkg/lib .. ../.."  for i in $libslist; \
do @@ -121,7 +121,9 @@
   fi
 
   if test x"${ac_cv_path_jpeg_lib}" != x ; then
-      JPEG_LIBS="${ac_cv_path_jpeg_lib}"
+      JPEG_LIBS="${ac_cv_path_jpeg_lib} -ljpeg"
+  else
+      JPEG_LIBS="-ljpeg"
   fi
 
   AM_CONDITIONAL(HAVE_JPEG, [test x$jpeg = xyes])
Index: gnash/macros/opengl.m4
diff -u gnash/macros/opengl.m4:1.10 gnash/macros/opengl.m4:1.11
--- gnash/macros/opengl.m4:1.10	Fri Feb 24 00:06:21 2006
+++ gnash/macros/opengl.m4	Sun Feb 26 15:49:30 2006
@@ -85,13 +85,13 @@
 
     dnl If the header doesn't exist, there is no point looking for the library.
     if test x"${ac_cv_path_opengl_libraries}" = x; then
-      AC_CHECK_LIB(GL, glBegin, [ac_cv_path_opengl_libraries="-lGL -lGLU"],[
+      AC_CHECK_LIB(GL, glBegin, [ac_cv_path_opengl_libraries=""],[
         AC_MSG_CHECKING([for libGL library])
         libslist="${prefix}/lib64 ${prefix}/lib /usr/X11R6/lib /usr/lib64 /usr/lib \
/usr/local/lib /opt/lib /usr/pkg/lib .. ../.."  for i in $libslist; do
           if test -f $i/libGL.a -o -f $i/libGL.so; then
             if test x"$i" != x"/usr/lib"; then
-              ac_cv_path_opengl_libraries="-L$i"
+              ac_cv_path_opengl_libraries="$i"
               AC_MSG_RESULT(${ac_cv_path_opengl_libraries})
               break
             else
@@ -104,7 +104,7 @@
     else
       if test -f ${ac_cv_path_opengl_libraries}/libGL.a -o -f \
${ac_cv_path_opengl_libraries}/libGL.so; then  if test \
                x"${ac_cv_path_opengl_libraries}" != x"/usr/lib"; then
-          ac_cv_path_opengl_libraries="-L${ac_cv_path_opengl_libraries}"
+          ac_cv_path_opengl_libraries="${ac_cv_path_opengl_libraries}"
          else
           ac_cv_path_opengl_libraries=""
         fi
@@ -119,7 +119,9 @@
   fi
 
   if test x"${ac_cv_path_opengl_libraries}" != x ; then
-      OPENGL_LIBS="${ac_cv_path_opengl_libraries}"
+      OPENGL_LIBS="-L${ac_cv_path_opengl_libraries} -lGL -lGLU"
+  else
+      OPENGL_LIBS="-lGL -lGLU"
   fi
 
   AM_CONDITIONAL(opengl, [test x$opengl = xyes])
Index: gnash/macros/png.m4
diff -u gnash/macros/png.m4:1.9 gnash/macros/png.m4:1.10
--- gnash/macros/png.m4:1.9	Fri Feb 24 00:06:21 2006
+++ gnash/macros/png.m4	Sun Feb 26 15:49:30 2006
@@ -51,25 +51,31 @@
         for i in $incllist; do
 	  if test -f $i/png.h; then
 	    if test x"$i" != x"/usr/include"; then
-	      ac_cv_path_png_incl="-I$i"
+	      ac_cv_path_png_incl="$i"
 	      break
             else
 	      ac_cv_path_png_incl=""
 	      break
 	    fi
+          else
+dnl 
+	    if test -f $i/libpng/png.h; then
+	      ac_cv_path_png_incl="$i/libpng"
+	      break
+	    fi
 	  fi
         done
       fi])
     else
       if test x"${ac_cv_path_png_incl}" != x"/usr/include"; then
-	ac_cv_path_png_incl="-I${ac_cv_path_png_incl}"
+	ac_cv_path_png_incl="${ac_cv_path_png_incl}"
        else
 	ac_cv_path_png_incl=""
       fi
     fi
 
     if test x"${ac_cv_path_png_incl}" != x ; then
-      PNG_CFLAGS="${ac_cv_path_png_incl}"
+      PNG_CFLAGS="-I${ac_cv_path_png_incl}"
     else
       PNG_CFLAGS=""
     fi
@@ -92,7 +98,7 @@
 
       dnl If the header doesn't exist, there is no point looking for the library.
       if test x"${ac_cv_path_png_lib}" = x; then
-        AC_CHECK_LIB(png, png_check_sig, [ac_cv_path_png_lib="-lpng"],[
+        AC_CHECK_LIB(png, png_check_sig, [ac_cv_path_png_lib=""],[
           AC_MSG_CHECKING([for libpng library])
           libslist="${prefix}/lib64 ${prefix}/lib /usr/lib64 /usr/lib /sw/lib \
/usr/local/lib /home/latest/lib /opt/lib /usr/pkg/lib /usr/X11R6/lib .. ../.."  for i \
in $libslist; do @@ -112,7 +118,9 @@
     fi
 
   if test x"${ac_cv_path_png_lib}" != x ; then
-      PNG_LIBS="${ac_cv_path_png_lib}"
+      PNG_LIBS="${ac_cv_path_png_lib} -lpng"
+  else
+      PNG_LIBS="-lpng"
   fi
 
   AM_CONDITIONAL(HAVE_PNG, [test x$png = xyes])
Index: gnash/macros/pthreads.m4
diff -u gnash/macros/pthreads.m4:1.4 gnash/macros/pthreads.m4:1.5
--- gnash/macros/pthreads.m4:1.4	Mon Feb 20 17:05:34 2006
+++ gnash/macros/pthreads.m4	Sun Feb 26 15:49:30 2006
@@ -26,89 +26,70 @@
 
   if test x"$pthreads" = x"yes"; then
     dnl Look for the header
-  AC_ARG_WITH(pthreads_incl, [  --with-pthreads_incl    directory where libpthreads \
header is], with_pthreads_incl=${withval}) +  AC_ARG_WITH(pthreads_incl, [  \
--with-pthread-incl    directory where Pthread header is], \
with_pthread_incl=${withval})  AC_CACHE_VAL(ac_cv_path_pthread_incl,[
-    if test x"${with_pthreads_incl}" != x ; then
-      if test -f ${with_pthreads_incl}/pthread.h ; then
-	ac_cv_path_pthread_incl=`(cd ${with_pthreads_incl}; pwd)`
+    if test x"${with_pthread_incl}" != x ; then
+      if test -f ${with_pthread_incl}/pthread.h ; then
+	ac_cv_path_pthread_incl=`(cd ${with_pthread_incl}; pwd)`
       else
-	AC_MSG_ERROR([${with_pthreads_incl} directory doesn't contain pthread.h])
+	AC_MSG_ERROR([${with_pthread_incl} directory doesn't contain pthread.h])
       fi
     fi
     ])
 
     dnl If the path hasn't been specified, go look for it.
     if test x"${ac_cv_path_pthread_incl}" = x; then
-      if test -d /usr/pkg/pthreads; then
+      AC_CHECK_HEADERS(pthread.h, [ac_cv_path_pthread_incl=""], [
+      if test x"${ac_cv_path_pthread_incl}" = x; then
         AC_MSG_CHECKING([for libpthread header])
-	if test -f /usr/pkg/pthreads/include/pthread.h; then
-	  ac_cv_path_pthread_incl="-I/usr/pkg/pthreads/include"
-	fi
-      else
-        AC_CHECK_HEADERS(pthread.h, [ac_cv_path_pthread_incl=""], [
-        if test x"${ac_cv_path_pthread_incl}" = x; then
-          AC_MSG_CHECKING([for libpthread header])
-          incllist="/usr/pkg/pthreads/include /sw/include /usr/local/include \
                /home/latest/include /opt/include /usr/include /usr/pkg/include .. \
                ../.."
-
-          for i in $incllist; do
-	    if test -f $i/pthreads/pthread.h -o -f $i/pthread.h; then
-	      if test x"$i" != x"/usr/include"; then
-	        ac_cv_path_pthread_incl="-I$i"
-	        break
-              else
-	        ac_cv_path_pthread_incl=""
-	        break
-	      fi
+        incllist="${prefix}/include /sw/include  /usr/pkg/pthreads/include \
/usr/local/include /home/latest/include /opt/include /usr/include .. ../.." +        \
for i in $incllist; do +	  if test -f $i/pthreads/pthread.h -o -f $i/pthread.h; then
+	    if test x"$i" != x"/usr/include"; then
+	      ac_cv_path_pthread_incl="$i"
+	      break
+            else
+	      ac_cv_path_pthread_incl=""
+	      break
 	    fi
-          done
-        fi])
-      fi	
+	  fi
+        done
+      fi], [INCLUDES = -I/usr/pkg/pthreads/include])
     else
-      AC_MSG_RESULT(-I${ac_cv_path_pthread_incl})
+      AC_MSG_RESULT(${ac_cv_path_pthread_incl})
       if test x"${ac_cv_path_pthread_incl}" != x"/usr/include"; then
-	ac_cv_path_pthread_incl="-I${ac_cv_path_pthread_incl}"
+	ac_cv_path_pthread_incl="${ac_cv_path_pthread_incl}"
        else
 	ac_cv_path_pthread_incl=""
       fi
     fi
 
     if test x"${ac_cv_path_pthread_incl}" != x ; then
-      PTHREAD_CFLAGS="${ac_cv_path_pthread_incl}"
+      PTHREAD_CFLAGS="-I${ac_cv_path_pthread_incl}"
       AC_MSG_RESULT(yes)
     else
       PTHREAD_CFLAGS=""
     fi
 
       dnl Look for the library
-      AC_ARG_WITH(pthreads_lib, [  --with-pthreads-lib     directory where pthreads \
                library is], with_pthreads_lib=${withval})
-      AC_CACHE_VAL(ac_cv_path_pthreads_lib,[
-      if test x"${with_pthreads_lib}" != x ; then
-        if test -f ${with_pthreads_lib}/libpthread.a -o -f \
                ${with_pthreads_lib}/libpthread.so; then
-	  ac_cv_path_pthreads_lib=`(cd ${with_pthreads_incl}; pwd)`
+      AC_ARG_WITH(pthread_lib, [  --with-pthread-lib     directory where pthreads \
library is], with_pthread_lib=${withval}) +      \
AC_CACHE_VAL(ac_cv_path_pthread_lib,[ +      if test x"${with_pthread_lib}" != x ; \
then +        if test -f ${with_pthread_lib}/libpthread.a -o -f \
${with_pthread_lib}/libpthread.so; then +	  ac_cv_path_pthread_lib=`(cd \
${with_pthread_incl}; pwd)`  else
-	  AC_MSG_ERROR([${with_pthreads_lib} directory doesn't contain libpthreads.])
+	  AC_MSG_ERROR([${with_pthread_lib} directory doesn't contain Pthread library.])
         fi
       fi
       ])
 
       dnl If the header doesn't exist, there is no point looking for the library.
       if test x"${ac_cv_path_pthread_lib}" = x; then
-        if test -d /usr/pkg/pthreads; then
-          AC_MSG_CHECKING([for libpthreads library])
-	  if test -f /usr/pkg/pthreads/lib/libpthreads.a -o -f \
                /usr/pkg/pthreads/lib/libpthreads.so; then
-	    ac_cv_path_pthread_lib="-L/usr/pkg/pthreads/lib -lpthreads"
-	  fi
-	  if test x"${ac_cv_path_pthread_lib}" != x ; then
-	    AC_MSG_RESULT(yes)
-	  else
-	    AC_MSG_RESULT(yes)
-	  fi
-	else
-        AC_CHECK_LIB(pthread, pthread_kill, [ac_cv_path_pthread_lib="-lpthreads"],[
+        AC_CHECK_LIB(pthread, pthread_kill, [ac_cv_path_pthread_lib="-lpthread"],[
           AC_MSG_CHECKING([for libpthreads library])
-          libslist="/usr/lib64 /usr/lib /usr/pkg/pthreads/lib /sw/lib /usr/local/lib \
/home/latest/lib /opt/lib /usr/pkg/lib .. ../.." +          libslist="${prefix}/lib64 \
${prefix}/lib /usr/lib64 /usr/lib /usr/pkg/pthreads/lib /sw/lib /usr/local/lib \
/home/latest/lib /opt/lib /usr/pkg/lib .. ../.."  for i in $libslist; do
-	    if test -f $i/libpthreads.a -o -f $i/libpthreads.so; then
+	    if test -f $i/libpthread.a -o -f $i/libpthread.so; then
 	      if test x"$i" != x"/usr/lib"; then
 	        ac_cv_path_pthread_lib="-L$i"
                 AC_MSG_RESULT(${ac_cv_path_pthread_lib})
@@ -121,9 +102,8 @@
 	    fi
           done
 	])
-	fi
       else
-        if test -f ${ac_cv_path_pthread_lib}/libpthreads.a -o -f \
${ac_cv_path_pthread_lib}/libpthreads.so; then +        if test -f \
${ac_cv_path_pthread_lib}/libpthread.a -o -f ${ac_cv_path_pthread_lib}/libpthread.so; \
then  
           if test x"${ac_cv_path_pthread_lib}" != x"/usr/lib"; then
 	    ac_cv_path_pthread_lib="-L${ac_cv_path_pthread_lib} -lpthread"
@@ -134,7 +114,7 @@
       fi
 
       if test x"${ac_cv_path_pthread_lib}" != x ; then
-        PTHREAD_LIBS="${ac_cv_path_pthread_lib} -lpthreads"
+        PTHREAD_LIBS="${ac_cv_path_pthread_lib} -lpthread"
       else
         PTHREAD_LIBS="-lpthread"
       fi
Index: gnash/macros/sdl.m4
diff -u gnash/macros/sdl.m4:1.9 gnash/macros/sdl.m4:1.10
--- gnash/macros/sdl.m4:1.9	Fri Feb 24 00:06:21 2006
+++ gnash/macros/sdl.m4	Sun Feb 26 15:49:30 2006
@@ -1,188 +1,112 @@
-# Configure paths for SDL
-# Sam Lantinga 9/21/99
-# stolen from Manish Singh
-# stolen back from Frank Belew
-# stolen from Manish Singh
-# Shamelessly stolen from Owen Taylor
-
-dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
-dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
 dnl
-AC_DEFUN([GNASH_PATH_SDL],
-[dnl 
-dnl Get the cflags and libraries from the sdl-config script
+dnl  Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 dnl
-AC_ARG_WITH(sdl-prefix,[  --with-sdl-prefix=PFX   Prefix where SDL is installed \
                (optional)],
-            sdl_prefix="$withval", sdl_prefix="")
-AC_ARG_WITH(sdl-exec-prefix,[  --with-sdl-exec-prefix=PFX Exec prefix where SDL is \
                installed (optional)],
-            sdl_exec_prefix="$withval", sdl_exec_prefix="")
-AC_ARG_ENABLE(sdltest, [  --disable-sdltest       Do not try to compile and run a \
                test SDL program],
-		    , enable_sdltest=yes)
-
-  if test x$sdl_exec_prefix != x ; then
-     sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
-     if test x${SDL_CONFIG+set} != xset ; then
-        SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
-     fi
-  fi
-  if test x$sdl_prefix != x ; then
-     sdl_args="$sdl_args --prefix=$sdl_prefix"
-     if test x${SDL_CONFIG+set} != xset ; then
-        SDL_CONFIG=$sdl_prefix/bin/sdl-config
-     fi
-  fi
-
-  AC_REQUIRE([AC_CANONICAL_TARGET])
-  PATH="$prefix/bin:$prefix/usr/bin:/usr/bin/X11:$PATH"
-  AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH])
-  min_sdl_version=ifelse([$1], ,0.11.0,$1)
-  AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
-  no_sdl=""
-  if test "$SDL_CONFIG" = "no" ; then
-    no_sdl=yes
-  else
-    SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
-    SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
-
-    sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
-           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
-    sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
-           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
-    sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
-           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
-    if test "x$enable_sdltest" = "xyes" ; then
-      ac_save_CFLAGS="$CFLAGS"
-      ac_save_CXXFLAGS="$CXXFLAGS"
-      ac_save_LIBS="$LIBS"
-      CFLAGS="$CFLAGS $SDL_CFLAGS"
-      CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
-      LIBS="$LIBS $SDL_LIBS"
+dnl  This program is free software; you can redistribute it and/or modify
+dnl  it under the terms of the GNU General Public License as published by
+dnl  the Free Software Foundation; either version 2 of the License, or
+dnl  (at your option) any later version.
 dnl
-dnl Now check if the installed SDL is sufficiently new. (Also sanity
-dnl checks the results of sdl-config to some extent
+dnl  This program is distributed in the hope that it will be useful,
+dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl  GNU General Public License for more details.
 dnl
-      rm -f conf.sdltest
-      AC_TRY_RUN([
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "SDL.h"
-
-char*
-my_strdup (char *str)
-{
-  char *new_str;
-  
-  if (str)
-    {
-      new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
-      strcpy (new_str, str);
-    }
-  else
-    new_str = NULL;
-  
-  return new_str;
-}
-
-int main (int argc, char *argv[])
-{
-  int major, minor, micro;
-  char *tmp_version;
-
-  /* This hangs on some systems (?)
-  system ("touch conf.sdltest");
-  */
-  { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); }
-
-  /* HP/UX 9 (%@#!) writes to sscanf strings */
-  tmp_version = my_strdup("$min_sdl_version");
-  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
-     printf("%s, bad version string\n", "$min_sdl_version");
-     exit(1);
-   }
-
-   if (($sdl_major_version > major) ||
-      (($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
-      (($sdl_major_version == major) && ($sdl_minor_version == minor) && \
                ($sdl_micro_version >= micro)))
-    {
-      return 0;
-    }
-  else
-    {
-      printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum \
                version\n", $sdl_major_version, $sdl_minor_version, \
                $sdl_micro_version);
-      printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it \
                is\n", major, minor, micro);
-      printf("*** best to upgrade to the required version.\n");
-      printf("*** If sdl-config was wrong, set the environment variable \
                SDL_CONFIG\n");
-      printf("*** to point to the correct copy of sdl-config, and remove the \
                file\n");
-      printf("*** config.cache before re-running configure\n");
-      return 1;
-    }
-}
-
-],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
-       CFLAGS="$ac_save_CFLAGS"
-       CXXFLAGS="$ac_save_CXXFLAGS"
-       LIBS="$ac_save_LIBS"
-     fi
-  fi
-  if test "x$no_sdl" = x ; then
-     AC_MSG_RESULT(yes)
-     ifelse([$2], , :, [$2])     
-  else
-     AC_MSG_RESULT(no)
-     if test "$SDL_CONFIG" = "no" ; then
-       echo "*** The sdl-config script installed by SDL could not be found"
-       echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
-       echo "*** your path, or set the SDL_CONFIG environment variable to the"
-       echo "*** full path to sdl-config."
-     else
-       if test -f conf.sdltest ; then
-        :
-       else
-          echo "*** Could not run SDL test program, checking why..."
-          CFLAGS="$CFLAGS $SDL_CFLAGS"
-          CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
-          LIBS="$LIBS $SDL_LIBS"
-          AC_TRY_LINK([
-#include <stdio.h>
-#include "SDL.h"
-
-int main(int argc, char *argv[])
-{ return 0; }
-#undef  main
-#define main K_and_R_C_main
-],      [ return 0; ],
-        [ echo "*** The test program compiled, but did not run. This usually means"
-          echo "*** that the run-time linker is not finding SDL or finding the \
                wrong"
-          echo "*** version of SDL. If it is not finding SDL, you'll need to set \
                your"
-          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to \
                point"
-          echo "*** to the installed location  Also, make sure you have run ldconfig \
                if that"
-          echo "*** is required on your system"
-	  echo "***"
-          echo "*** If you have an old version installed, it is best to remove it, \
                although"
-          echo "*** you may also be able to get things to work by modifying \
                LD_LIBRARY_PATH"],
-        [ echo "*** The test program failed to compile or link. See the file \
                config.log for the"
-          echo "*** exact error that occured. This usually means SDL was incorrectly \
                installed"
-          echo "*** or that you have moved SDL since it was installed. In the latter \
                case, you"
-          echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
-          CFLAGS="$ac_save_CFLAGS"
-          CXXFLAGS="$ac_save_CXXFLAGS"
-          LIBS="$ac_save_LIBS"
-       fi
-     fi
-     SDL_CFLAGS=""
-     SDL_LIBS=""
-     ifelse([$3], , :, [$3])
+dnl  You should have received a copy of the GNU General Public License
+dnl  along with this program; if not, write to the Free Software
+dnl  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+AC_DEFUN([GNASH_PATH_SDL],
+[dnl 
+  dnl Lool for the header
+  AC_ARG_WITH(sdl_incl, [  --with-sdl-incl   directory where sdl header is], \
with_sdl_incl=${withval}) +  AC_CACHE_VAL(ac_cv_path_sdl_incl,[
+  if test x"${with_sdl_incl}" != x ; then
+    if test -f ${with_sdl_incl}/SDL.h ; then
+      ac_cv_path_sdl_incl=`(cd ${with_sdl_incl}; pwd)`
+    else
+      AC_MSG_ERROR([${with_sdl_incl} directory doesn't contain SDL.h])
+    fi
+  fi
+  ])
+  if test x"${ac_cv_path_sdl_incl}" = x ; then
+    AC_MSG_CHECKING([for SDL header])
+    incllist="${prefix} /usr /usr/pkg /sw /usr/local /home/latest /opt /usr .. \
../.." +
+    for i in $incllist; do
+      if test -f $i/SDL/include/SDL.h; then
+        ac_cv_path_sdl_incl=$i/SDL/include
+        break
+      fi
+      if test -f $i/include/SDL/SDL.h; then
+        ac_cv_path_sdl_incl=$i/include/SDL
+        break
+      fi
+    done
+
+    SDL_CFLAGS=""
+    if test x"${ac_cv_path_sdl_incl}" = x ; then
+      AC_MSG_RESULT(none)
+      AC_CHECK_HEADERS(SDL.h, [ac_cv_path_sdl_incl=""])
+    else
+      AC_MSG_RESULT(${ac_cv_path_sdl_incl})
+      if test x"${ac_cv_path_sdl_incl}" != x"/usr/include"; then
+        ac_cv_path_sdl_incl="${ac_cv_path_sdl_incl}"
+      else
+        ac_cv_path_sdl_incl=""
+      fi
+    fi
   fi
+
+  if test x"${ac_cv_path_sdl_incl}" != x ; then
+    SDL_CFLAGS="-I${ac_cv_path_sdl_incl}"
+  fi
+
+  dnl Look for the library
+  AC_ARG_WITH(sdl_lib, [  --with-sdl-lib    directory where sdl library is], \
with_sdl_lib=${withval}) +  AC_MSG_CHECKING([for sdl library])
+  AC_CACHE_VAL(ac_cv_path_sdl_lib,[
+  if test x"${with_sdl_libs}" != x ; then
+    if test -f ${with_sdl_libs}/libSDL.a -o -f ${with_sdl_libs}/libSDL.so; then
+      ac_cv_path_sdl_lib=`(cd ${with_sdl_libs}; pwd)`
+    else
+      AC_MSG_ERROR([${with_sdl_libs} directory doesn't contain libsdl.a])
+    fi
+  fi
+  ])
+
+  SDL_LIBS=""
+  if test x"${ac_cv_path_sdl_lib}" = x ; then
+    AC_CHECK_LIB(SDL, SDL_Init, [ac_cv_path_sdl_lib="-lSDL"],[
+      AC_MSG_CHECKING([for SDL library])
+      liblist="${prefix}/lib64 ${prefix}/lib /usr/lib64 /usr/lib /usr/pkg/lib \
/sw/lib /usr/local/lib /home/latest/lib /opt/lib.. ../.." +      for i in $liblist; \
do +        if test -f $i/libSDL.a -o -f $i/libSDl.so; then
+          if test x"$i" != x"/usr/lib"; then
+            ac_cv_path_sdl_lib="-L$i -lSDL"
+            AC_MSG_RESULT(${ac_cv_path_sdl_lib})
+            break
+          else
+            ac_cv_path_sdl_lib="-lSDL"
+            AC_MSG_RESULT([yes])
+            break
+          fi
+        fi
+      done
+    ])
+  fi
+
+  if test x"${ac_cv_path_sdl_lib}" != x ; then
+    SDL_LIBS="${ac_cv_path_sdl_lib}"
+    AC_DEFINE(HAVE_SDL_H, [], [We have SDL support])
+  fi
+
   AC_SUBST(SDL_CFLAGS)
   AC_SUBST(SDL_LIBS)
-  rm -f conf.sdltest
 ])
 
 AC_DEFUN([GNASH_PATH_SDL_MIXER],
 [
   dnl Lool for the header
-  AC_ARG_WITH(sdl_mixer_incl, [  --with-sdl_mixer-incl   directory where sdl_mixer \
header is], with_sdl_mixer_incl=${withval}) +  AC_ARG_WITH(sdl_mixer_incl, [  \
--with-sdl-mixer-incl   directory where sdl_mixer header is], \
with_sdl_mixer_incl=${withval})  AC_CACHE_VAL(ac_cv_path_sdl_mixer_incl,[
   if test x"${with_sdl_mixer_incl}" != x ; then
     if test -f ${with_sdl_mixer_incl}/SDL_mixer.h ; then
@@ -192,7 +116,6 @@
     fi
   fi
   ])
-
   if test x"${ac_cv_path_sdl_mixer_incl}" = x ; then
     AC_MSG_CHECKING([for SDL_mixer header])
     incllist="${prefix} /usr/pkg /sw /usr/local /home/latest /opt /usr .. ../.."
@@ -214,16 +137,17 @@
       AC_CHECK_HEADERS(SDL_mixer.h, [ac_cv_path_sdl_mixer_incl=""])
     else
       AC_MSG_RESULT(${ac_cv_path_sdl_mixer_incl})
-      if test x"${ac_cv_path_sdl_mixer_incl}" != x"/usr/include"; then
-        ac_cv_path_sdl_mixer_incl="${ac_cv_path_sdl_mixer_incl}"
-      else
-        ac_cv_path_sdl_mixer_incl=""
-      fi
     fi
   fi
 
   if test x"${ac_cv_path_sdl_mixer_incl}" != x ; then
-    SDL_MIXER_CFLAGS="-I${ac_cv_path_sdl_mixer_incl}"
+    if test x"${ac_cv_path_sdl_mixer_incl}" != x"/usr/include"; then
+      ac_cv_path_sdl_mixer_incl="${ac_cv_path_sdl_mixer_incl}"
+      SDL_MIXER_CFLAGS="-I${ac_cv_path_sdl_mixer_incl}"
+      AC_DEFINE(HAVE_SDL_MIXER_H, [], [We have SDL Mixer support])
+    else
+      ac_cv_path_sdl_mixer_incl=""
+    fi
   fi
 
   dnl Look for the library
@@ -231,7 +155,7 @@
   AC_MSG_CHECKING([for sdl_mixer library])
   AC_CACHE_VAL(ac_cv_path_sdl_mixer_lib,[
   if test x"${with_sdl_mixer_libs}" != x ; then
-    if test -f ${with_sdl_mixer_libs}/libSDL_mixer.a -o -f \
${with_sdl_mixer_libs}/libSDL_mixer.so; then +    if test -f \
${with_sdl_mixer_libs}/libSDL_mixer.a -o -f ${with_sdl_mixer_libs}/libSDL_mixer.so -o \
-f $i/libSDL_mixer-1.2.a -o -f $i/libSDL_mixer-1.2.so; then  \
ac_cv_path_sdl_mixer_lib=`(cd ${with_sdl_mixer_libs}; pwd)`  else
       AC_MSG_ERROR([${with_sdl_mixer_libs} directory doesn't contain \
libsdl_mixer.a]) @@ -239,41 +163,53 @@
   fi
   ])
 
+      dnl Some systems ubnfortunately use the version on this library,
+      dnl and don't have a symbolic link without a version number,
+dnl     if test -f $i/libSDL_mixer-1.2.a -o -f $i/libSDL_mixer-1.2.so; then
+dnl          ac_cv_path_sdl_mixer_lib=$i
+dnl 	 withver="-1.2"
+
+  SDL_MIXER_LIBS=""
+
   if test x"${ac_cv_path_sdl_mixer_lib}" = x ; then
-    liblist="${prefix}/lib64 ${prefix}/lib /usr/lib64 /usr/lib /usr/pkg/lib /sw/lib \
/usr/local/lib /home/latest/lib /opt/lib.. ../.." +    AC_CHECK_LIB(SDL_mixer, \
Mix_Linked_Version, [], AC_MSG_RESULT([no])) +    if test \
x"${ac_cv_path_sdl_mixer_lib}" = x ; then +      AC_CHECK_LIB(SDL_mixer-1.2, \
Mix_Linked_Version, [ac_cv_path_sdl_mixer_lib="-lSDL_mixer-1.2"], \
AC_MSG_RESULT([no])) +    fi
+  else
+    AC_MSG_RESULT([yes])
+  fi
 
+  if test x"${ac_cv_path_sdl_mixer_lib}" = x ; then
+    AC_MSG_CHECKING([for SDL_mixer library])
+    liblist="${prefix}/lib64 ${prefix}/lib /usr/lib64 /usr/lib /usr/pkg/lib /sw/lib \
/usr/local/lib /home/latest/lib /opt/lib.. ../.."  for i in $liblist; do
-    if test -f $i/libSDL_mixer.a -o -f $i/libSDL_mixer.so -o -f \
                $i/libSDL_mixer.dylib; then
-       ac_cv_path_sdl_mixer_lib=$i
-       break
-    else
-dnl Some systems ubnfortunately use the version on this library, and don't
-dnl have a symbolic link without a version number,
-      if test -f $i/libSDL_mixer-1.2.a -o -f $i/libSDL_mixer-1.2.so -o -f \
                $i/libSDL_mixer.dylib; then
-         ac_cv_path_sdl_mixer_lib=$i
-         break
+      if test -f $i/libSDL_mixer.a -o -f $i/libSDl_mixer.so; then
+        if test x"$i" != x"/usr/lib"; then
+          ac_cv_path_sdl_mixer_lib="-L$i -lSDL_mixer"
+          break
+        else
+          ac_cv_path_sdl_mixer_lib="-lSDL_mixer"
+          break
+        fi
       fi
-    fi
-    done
-
-    SDL_MIXER_LIBS=""
-    if test x"${ac_cv_path_sdl_mixer_lib}" = x ; then
-      AC_MSG_RESULT(none)
-      dnl if we can't find libsdl_mixer via the path, see if it's in the compiler \
                path
-      AC_CHECK_LIB(SDL_mixer, Mix_Linked_Version, SDL_MIXER_LIBS="-lSDL_mixer")
-    else
-      AC_MSG_RESULT(${ac_cv_path_sdl_mixer_lib})
-      if test x"${ac_cv_path_sdl_mixer_lib}" != x"/usr/lib"; then
-        ac_cv_path_sdl_mixer_lib="-L${ac_cv_path_sdl_mixer_lib} -lSDL_mixer"
-      else
-        ac_cv_path_sdl_mixer_lib="-lSDL_mixer"
+      if test -f $i/libSDL_mixer-1.2.a -o -f $i/libSDl_mixer-1.2.so; then
+        if test x"$i" != x"/usr/lib"; then
+          ac_cv_path_sdl_mixer_lib="-L$i -lSDL_mixer-1.2"
+          AC_MSG_RESULT(${ac_cv_path_sdl_mixer_lib})
+          break
+        else
+          ac_cv_path_sdl_mixer_lib="-lSDL_mixer-1.2"
+          AC_MSG_RESULT([yes])
+          break
+        fi
       fi
-    fi
+    done
   fi
 
   if test x"${ac_cv_path_sdl_mixer_lib}" != x ; then
     SDL_MIXER_LIBS="${ac_cv_path_sdl_mixer_lib}"
-    AC_DEFINE(HAVE_SDL_MIXER_H, [], [We have SDL Mixer support])
+    AC_DEFINE(HAVE_SDL_MIXER, [], [We have full SDL Mixer support])
   fi
 
   AC_SUBST(SDL_MIXER_CFLAGS)
Index: gnash/server/Makefile.am
diff -u gnash/server/Makefile.am:1.21 gnash/server/Makefile.am:1.22
--- gnash/server/Makefile.am:1.21	Mon Feb 13 10:44:12 2006
+++ gnash/server/Makefile.am	Sun Feb 26 15:49:30 2006
@@ -30,6 +30,7 @@
         -I$(top_srcdir)		\
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)		\
+	$(PTHREAD_CFLAGS)	\
         $(ENGINE_INCLUDE)	\
         $(ZLIB_CFLAGS)		\
         $(OGG_CFLAGS)		\
Index: gnash/utilities/Makefile.am
diff -u gnash/utilities/Makefile.am:1.9 gnash/utilities/Makefile.am:1.10
--- gnash/utilities/Makefile.am:1.9	Fri Feb  3 20:50:27 2006
+++ gnash/utilities/Makefile.am	Sun Feb 26 15:49:30 2006
@@ -41,13 +41,16 @@
         $(LIBXML_LIBS)      \
 	$(DMALLOC_LIBS)	    \
 	$(MP3_LIBS)	    \
-	$(OGG_LIBS)
+	$(OGG_LIBS)	    \
+	$(PTHREAD_LIBS)
+
 
 INCLUDES = -I.. \
         -I$(top_srcdir)		\
         -I$(top_srcdir)/libbase \
         -I$(top_srcdir)/server  \
         -I$(top_srcdir)/libgeometry \
+	$(PTHREAD_CFLAGS)        \
 	$(LIBXML_CFLAGS)        \
 	$(OPENGL_CFLAGS)	\
 	$(DMALLOC_CFLAGS)	\


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic