gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] gnash ./ChangeLog backend/Makefile.am backend/r...


From: Rob Savoye
Subject: [Gnash-commit] gnash ./ChangeLog backend/Makefile.am backend/r...
Date: Sun, 26 Feb 2006 15:49:30 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Branch:         
Changes by:     Rob Savoye <address@hidden>     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  <address@hidden>
+
+       * 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  <address@hidden>
 
        * 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden> 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 <address@hidden> 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 <address@hidden>
-
-// 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 (address@hidden)
-// -- 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 <address@hidden>
+
+// 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 (address@hidden)
+// -- 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden> 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 <address@hidden> 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 <address@hidden> 
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 <address@hidden> 
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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 <address@hidden>
-
-// 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 <address@hidden>
+
+// 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 (address@hidden) 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)       \




reply via email to

[Prev in Thread] Current Thread [Next in Thread]