gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog server/Makefile.am server/butto...


From: Sandro Santilli
Subject: [Gnash-commit] gnash ChangeLog server/Makefile.am server/butto...
Date: Wed, 11 Apr 2007 14:20:21 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Sandro Santilli <strk>  07/04/11 14:20:21

Modified files:
        .              : ChangeLog 
        server         : Makefile.am button_character_instance.cpp 
                         character.cpp character.h dlist.cpp dlist.h 
                         event_id.h execute_tag.h gnash.h impl.h 
                         movie_root.cpp movie_root.h sprite_instance.cpp 
                         sprite_instance.h swf_event.h types.cpp 
        server/parser  : button_character_def.h shape_character_def.h 
        server/swf     : tag_loaders.cpp 
        server/vm      : ExecutableCode.h action.cpp 
        testsuite/actionscript.all: MovieClip.as dejagnu_so_init.as 
        testsuite/misc-ming.all: action_execution_order_extend_test.c 
                                 displaylist_depths_test.c 
Added files:
        server         : cxform.cpp cxform.h 
        server/swf     : PlaceObject2Tag.cpp PlaceObject2Tag.h 

Log message:
                * server/: Makefile.am, gnash.h, types.cpp, cxform.{cpp,h},
                  swf/PlaceObject2Tag.{cpp,h}, swf/tag_loaders.cpp:
                  Extract PlaceObject2Tag from tag_loaders
                  and cxform from gnash.h and types.cpp.
                * server/character.{cpp,h}: add getUserDefinedEventHandler
                  function, change static event handlers function to allow
                  for multiple handlers for the same event.
                * server/vm/ExecutableCode.h: add EventCode class.
                * server/swf_event.h: drop the 'function' member, provide better
                  members protection.
                * testsuite/actionscript.all/MovieClip.as: add tests for
                  user defined events not being proper properties.
                * testsuite/actionscript.all/dejagnu_so_init.as: delete the
                  user-defined onEnterFrame when finished with it.
                * server/execute_tag.h: add missing include.
                * server/event_id.h: add setKeyCode method, for better 
protection.
                * server/button_character_instance.cpp (on_button_event): look 
for
                  user-defined event handlers.
                * server/dlist.{cpp,h}, server/impl.h,
                  server/parser/shape_character_def.h,
                  server/parser/button_character_def.h:
                  Update after addition of new files
                * testsuite/misc-ming.all/action_execution_order_extend_test.c:
                  Two unexpected successes, one unexpected failures (due to 
scrabling
                  of event handling).
                * server/movie_root.{cpp,h}: add pushAction(ExecutableCode).
                * server/sprite_instance.{cpp,h}: stop using gettersetter for 
event
                  handlers
                * testsuite/misc-ming.all/displaylist_depths_test.c: test that
                  event handlers need to be duplicated too.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2846&r2=1.2847
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.108&r2=1.109
http://cvs.savannah.gnu.org/viewcvs/gnash/server/button_character_instance.cpp?cvsroot=gnash&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/gnash/server/character.cpp?cvsroot=gnash&r1=1.29&r2=1.30
http://cvs.savannah.gnu.org/viewcvs/gnash/server/character.h?cvsroot=gnash&r1=1.63&r2=1.64
http://cvs.savannah.gnu.org/viewcvs/gnash/server/dlist.cpp?cvsroot=gnash&r1=1.57&r2=1.58
http://cvs.savannah.gnu.org/viewcvs/gnash/server/dlist.h?cvsroot=gnash&r1=1.32&r2=1.33
http://cvs.savannah.gnu.org/viewcvs/gnash/server/event_id.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/execute_tag.h?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/server/gnash.h?cvsroot=gnash&r1=1.90&r2=1.91
http://cvs.savannah.gnu.org/viewcvs/gnash/server/impl.h?cvsroot=gnash&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.55&r2=1.56
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.h?cvsroot=gnash&r1=1.46&r2=1.47
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.231&r2=1.232
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.93&r2=1.94
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf_event.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/types.cpp?cvsroot=gnash&r1=1.20&r2=1.21
http://cvs.savannah.gnu.org/viewcvs/gnash/server/cxform.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/cxform.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/button_character_def.h?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/shape_character_def.h?cvsroot=gnash&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/tag_loaders.cpp?cvsroot=gnash&r1=1.87&r2=1.88
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/PlaceObject2Tag.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/PlaceObject2Tag.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ExecutableCode.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/action.cpp?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/MovieClip.as?cvsroot=gnash&r1=1.50&r2=1.51
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/dejagnu_so_init.as?cvsroot=gnash&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_extend_test.c?cvsroot=gnash&r1=1.6&r2=1.7
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/displaylist_depths_test.c?cvsroot=gnash&r1=1.4&r2=1.5

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.2846
retrieving revision 1.2847
diff -u -b -r1.2846 -r1.2847
--- ChangeLog   11 Apr 2007 14:04:59 -0000      1.2846
+++ ChangeLog   11 Apr 2007 14:20:20 -0000      1.2847
@@ -1,3 +1,36 @@
+2007-04-11 Sandro Santilli <address@hidden>
+
+       * server/: Makefile.am, gnash.h, types.cpp, cxform.{cpp,h},
+         swf/PlaceObject2Tag.{cpp,h}, swf/tag_loaders.cpp:
+         Extract PlaceObject2Tag from tag_loaders
+         and cxform from gnash.h and types.cpp.
+       * server/character.{cpp,h}: add getUserDefinedEventHandler
+         function, change static event handlers function to allow
+         for multiple handlers for the same event.
+       * server/vm/ExecutableCode.h: add EventCode class.
+       * server/swf_event.h: drop the 'function' member, provide better
+         members protection.
+       * testsuite/actionscript.all/MovieClip.as: add tests for
+         user defined events not being proper properties.
+       * testsuite/actionscript.all/dejagnu_so_init.as: delete the
+         user-defined onEnterFrame when finished with it.
+       * server/execute_tag.h: add missing include.
+       * server/event_id.h: add setKeyCode method, for better protection.
+       * server/button_character_instance.cpp (on_button_event): look for
+         user-defined event handlers.
+       * server/dlist.{cpp,h}, server/impl.h,
+         server/parser/shape_character_def.h,
+         server/parser/button_character_def.h:
+         Update after addition of new files
+       * testsuite/misc-ming.all/action_execution_order_extend_test.c:
+         Two unexpected successes, one unexpected failures (due to scrabling
+         of event handling).
+       * server/movie_root.{cpp,h}: add pushAction(ExecutableCode).
+       * server/sprite_instance.{cpp,h}: stop using gettersetter for event
+         handlers
+       * testsuite/misc-ming.all/displaylist_depths_test.c: test that
+         event handlers need to be duplicated too.
+
 2007-04-11 Ann Barcomb <address@hidden>
 
        * testsuite/actionscript.all/gen-index-wiki.sh doc/C/sources.xml:

Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -b -r1.108 -r1.109
--- server/Makefile.am  28 Mar 2007 23:42:19 -0000      1.108
+++ server/Makefile.am  11 Apr 2007 14:20:20 -0000      1.109
@@ -18,7 +18,7 @@
 # 
 #
 
-# $Id: Makefile.am,v 1.108 2007/03/28 23:42:19 rsavoye Exp $
+# $Id: Makefile.am,v 1.109 2007/04/11 14:20:20 strk Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -57,6 +57,7 @@
        as_object.cpp \
        as_value.cpp \
        character.cpp \
+       cxform.cpp \
        DynamicShape.cpp        \
        edit_text_character.cpp \
        generic_character.cpp \
@@ -69,6 +70,7 @@
        swf/TagLoadersTable.cpp \
        swf/tag_loaders.cpp \
        swf/DefineFontAlignZonesTag.cpp \
+       swf/PlaceObject2Tag.cpp \
        swf_function.cpp \
        video_stream_instance.cpp \
        StreamProvider.cpp \
@@ -110,6 +112,7 @@
        builtin_function.h \
        button_character_instance.h \
        character.h \
+       cxform.h \
        debugger.h \
        DynamicShape.h  \
        dlist.h \
@@ -140,6 +143,7 @@
        swf/TagLoadersTable.h \
        swf/tag_loaders.h \
        swf/DefineFontAlignZonesTag.h \
+       swf/PlaceObject2Tag.h \
        swf_event.h \
        swf_function.h \
        tesselate.h \

Index: server/button_character_instance.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/button_character_instance.cpp,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- server/button_character_instance.cpp        2 Apr 2007 17:22:29 -0000       
1.39
+++ server/button_character_instance.cpp        11 Apr 2007 14:20:20 -0000      
1.40
@@ -22,6 +22,7 @@
 #include "builtin_function.h"
 #include "fn_call.h" // for shared ActionScript getter-setters
 #include "GnashException.h" // for shared ActionScript getter-setters
+#include "ExecutableCode.h"
 
 /** \page buttons Buttons and mouse behaviour
 
@@ -204,6 +205,7 @@
        gettersetter = new builtin_function(&character::parent_getset, NULL);
        o.init_property("_parent", *gettersetter, *gettersetter);
 
+#if 0
        gettersetter = new builtin_function(&character::onrollover_getset, 
NULL);
        o.init_property("onRollOver", *gettersetter, *gettersetter);
 
@@ -221,6 +223,7 @@
 
        gettersetter = new builtin_function(&character::onload_getset, NULL);
        o.init_property("onLoad", *gettersetter, *gettersetter);
+#endif
 
        //--
 
@@ -303,7 +306,6 @@
 bool
 button_character_instance::on_event(const event_id& id)
 {
-
 #if 0
        if (id.m_id != event_id::KEY_PRESS)
        {
@@ -613,10 +615,10 @@
        }
 
        // check for built-in event handler.
-       as_value method = get_event_handler(event);
-       if ( ! method.is_undefined() )
+       std::auto_ptr<ExecutableCode> code ( get_event_handler(event) );
+       if ( code.get() )
        {
-               call_method0(method, &(get_environment()), this);
+               code->execute();
        }
        else
        {
@@ -625,7 +627,11 @@
 
 
        // Call conventional attached method.
-       // @@ TODO
+       boost::intrusive_ptr<as_function> method = 
getUserDefinedEventHandler(event.get_function_name());
+       if ( method )
+       {
+               call_method0(as_value(method.get()), &(get_environment()), 
this);
+       }
 }
 
 void 

Index: server/character.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/character.cpp,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -b -r1.29 -r1.30
--- server/character.cpp        6 Apr 2007 19:56:16 -0000       1.29
+++ server/character.cpp        11 Apr 2007 14:20:20 -0000      1.30
@@ -18,7 +18,7 @@
 //
 //
 
-/* $Id: character.cpp,v 1.29 2007/04/06 19:56:16 strk Exp $ */
+/* $Id: character.cpp,v 1.30 2007/04/11 14:20:20 strk Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -30,6 +30,7 @@
 #include "VM.h" // for do_mouse_drag (to be moved in movie_root)
 #include "fn_call.h" // for shared ActionScript getter-setters
 #include "GnashException.h" // for shared ActionScript getter-setters 
(ensure_character)
+#include "ExecutableCode.h"
 
 #include <boost/algorithm/string/case_conv.hpp>
 
@@ -236,160 +237,6 @@
 //---------------------------------------------------------------------
 
 as_value
-character::onrollover_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::ROLL_OVER);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::ROLL_OVER, fn.arg(0));
-       }
-       return rv;
-
-}
-
-as_value
-character::onrollout_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::ROLL_OUT);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::ROLL_OUT, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onpress_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::PRESS);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::PRESS, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onrelease_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::RELEASE);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::RELEASE, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onreleaseoutside_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::RELEASE_OUTSIDE);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::RELEASE_OUTSIDE, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onmouseup_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::MOUSE_UP);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::MOUSE_UP, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onmousedown_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::MOUSE_DOWN);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::MOUSE_DOWN, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onmousemove_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::MOUSE_MOVE);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::MOUSE_MOVE, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
-character::onload_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
-
-       as_value rv;
-       if ( fn.nargs == 0 ) // getter
-       {
-               rv = ptr->get_event_handler(event_id::LOAD);
-       }
-       else // setter
-       {
-               ptr->set_event_handler(event_id::LOAD, fn.arg(0));
-       }
-       return rv;
-}
-
-as_value
 character::x_getset(const fn_call& fn)
 {
        boost::intrusive_ptr<character> ptr = 
ensureType<character>(fn.this_ptr);
@@ -718,16 +565,31 @@
 }
 
 void
-character::set_event_handler(const event_id& id, const as_value& method)
+character::set_event_handlers(const Events& copyfrom)
 {
-       _event_handlers[id] = method;
+       for (Events::const_iterator it=copyfrom.begin(), itE=copyfrom.end();
+                       it != itE; ++it)
+       {
+               const event_id& ev = it->first;
+               const BufferList& bufs = it->second;
+               for (size_t i=0; i<bufs.size(); ++i)
+               {
+                       const action_buffer* buf = bufs[i];
+                       assert(buf);
+                       add_event_handler(ev, *buf);
+               }       
+       }
+}
+
+void
+character::add_event_handler(const event_id& id, const action_buffer& code)
+{
+       _event_handlers[id].push_back(&code);
 
        //log_msg("Setting handler for event %s", 
id.get_function_name().c_str());
 
        // Set the character as a listener iff the
        // kind of event is a KEY or MOUSE one 
-       if ( method.is_function() )
-       {
                switch (id.m_id)
                {
                        case event_id::KEY_PRESS:
@@ -742,12 +604,31 @@
                        default:
                                break;
                }
-       }
+
        // todo: drop the character as a listener
        //       if it gets no valid handlers for
        //       mouse or keypress events.
 }
 
+std::auto_ptr<ExecutableCode>
+character::get_event_handler(const event_id& id) const
+{
+       std::auto_ptr<ExecutableCode> handler;
+
+       Events::const_iterator it = _event_handlers.find(id);
+       if ( it == _event_handlers.end() ) return handler;
+
+       assert(get_ref_count() > 0);
+       boost::intrusive_ptr<character> this_ptr = const_cast<character*>(this);
+
+       handler.reset( new EventCode(this_ptr, it->second) );
+       return handler;
+}
+
+character::~character()
+{
+}
+
 void
 character::unload()
 {
@@ -760,18 +641,14 @@
 void
 character::queueEventHandler(const event_id& id)
 {
-       //testInvariant();
-
        bool called=false;
 
        movie_root& root = VM::get().getRoot();
 
-       // First, check for built-in event handler.
-       boost::intrusive_ptr<as_function> method = 
get_event_handler(id).to_as_function();
-          
-       if (method)
+       std::auto_ptr<ExecutableCode> code ( get_event_handler(id) );
+       if ( code.get() )
        {
-               root.pushAction(method, boost::intrusive_ptr<character>(this));
+               root.pushAction(code);
                called=true;
        }
 
@@ -780,35 +657,40 @@
        // ActionScript and SWF defined events
        // (for example: onClipLoad vs. onLoad)
        //
-       if (called) return;
+       //if (called) return;
 
        // Check for member function.
-       // In ActionScript 2.0, event method names are CASE SENSITIVE.
-       // In ActionScript 1.0, event method names are CASE INSENSITIVE.
-       // TODO: move to get_function_name directly ?
-       std::string method_name = id.get_function_name();
-       if ( _vm.getSWFVersion() < 7 )
-       {
-               boost::to_lower(method_name, _vm.getLocale());
-       }
-
-       if (method_name.length() > 0)
-       {
-               as_value method_val;
-               if ( get_member(method_name, &method_val) )
-               {
-                       method = method_val.to_as_function();
+       boost::intrusive_ptr<as_function> method = 
getUserDefinedEventHandler(id.get_function_name());
                        if ( method )
                        {
                                root.pushAction(method, 
boost::intrusive_ptr<character>(this));
                        }
+
+}
+
+boost::intrusive_ptr<as_function>
+character::getUserDefinedEventHandler(const std::string& name) const
+{
+       std::string method_name = name;
+       if ( _vm.getSWFVersion() < 7 )
+       {
+               boost::to_lower(method_name, _vm.getLocale());
                }
-       }
 
-       //testInvariant();
+       as_value tmp;
+
+       boost::intrusive_ptr<as_function> func;
 
+       // const cast is needed due to getter/setter members possibly
+       // modifying this object even when only get !
+       if ( const_cast<character*>(this)->get_member(method_name, &tmp) )
+       {
+               func = tmp.to_as_function();
+       }
+       return func;
 }
 
+
 } // namespace gnash
 
 // local variables:

Index: server/character.h
===================================================================
RCS file: /sources/gnash/gnash/server/character.h,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -b -r1.63 -r1.64
--- server/character.h  11 Apr 2007 08:55:05 -0000      1.63
+++ server/character.h  11 Apr 2007 14:20:20 -0000      1.64
@@ -18,7 +18,7 @@
 //
 //
 
-/* $Id: character.h,v 1.63 2007/04/11 08:55:05 strk Exp $ */
+/* $Id: character.h,v 1.64 2007/04/11 14:20:20 strk Exp $ */
 
 #ifndef GNASH_CHARACTER_H
 #define GNASH_CHARACTER_H
@@ -35,6 +35,7 @@
 #include "as_object.h" // for inheritance
 #include "rect.h" // for composition (invalidated bounds)
 #include "matrix.h" // for composition
+#include "cxform.h" // for composition
 #include "log.h"
 #include "snappingrange.h"
 
@@ -48,6 +49,7 @@
 namespace gnash {
        class sprite_instance;
        class movie_instance;
+       class ExecutableCode;
 }
 
 namespace gnash {
@@ -62,7 +64,9 @@
 
 public:
 
-       typedef std::map<event_id, as_value> Events;
+       // action_buffer is externally owned
+       typedef std::vector<const action_buffer*> BufferList;
+       typedef std::map<event_id, BufferList> Events;
 
 private:
 
@@ -91,10 +95,20 @@
            return _event_handlers;
        }
        
-       void set_event_handlers(const Events& copyfrom) 
-       {
-               _event_handlers = copyfrom;
-       }
+       /// Return a user defined event handler, if any
+       //
+       /// @param name
+       ///     Function name to fetch. It will be converted to 
+       ///     lowercase if current VM has been initialized against
+       ///     an SWF version inferior to 7.
+       ///
+       /// @return
+       ///     A function if a member with the given name exists and
+       ///     casts to an as_function. A NULL pointer otherwise.
+       ///
+       boost::intrusive_ptr<as_function> getUserDefinedEventHandler(const 
std::string& name) const;
+       
+       void set_event_handlers(const Events& copyfrom);
 
        /// Used to assign a name to unnamed instances
        static std::string getNextUnnamedInstanceName();
@@ -157,6 +171,7 @@
 
 public:  // TODO: make protected
 
+#if 0
        static as_value onrollover_getset(const fn_call& fn);
 
        static as_value onrollout_getset(const fn_call& fn);
@@ -174,6 +189,7 @@
        static as_value onmousedown_getset(const fn_call& fn);
 
        static as_value onmousemove_getset(const fn_call& fn);
+#endif
 
        static as_value x_getset(const fn_call& fn);
 
@@ -213,6 +229,8 @@
     ///
     static const int staticDepthOffset = -16384;
 
+    ~character();
+
     character(character* parent, int id)
        :
        m_id(id),
@@ -323,7 +341,7 @@
        /// Maps from our local space into normal color space.
        virtual cxform  get_world_cxform() const;
 
-       /// Get a built-in function handler for the given event
+       /// Get the built-in function handlers code for the given event
        //
        /// NOTE: this function is only for getting statically-defined
        ///       event handlers, which are the ones attached to a character
@@ -331,13 +349,7 @@
        ///       to properly fetch any user-defined event handler, which 
        ///       are the ones attached to a character with ActionScript code.
        ///
-       as_value get_event_handler(const event_id& id) const
-       {
-               std::map<event_id, as_value>::const_iterator it = \
-                       _event_handlers.find(id);
-               if ( it == _event_handlers.end() ) return as_value();
-               return it->second;
-       }
+       std::auto_ptr<ExecutableCode> get_event_handler(const event_id& id) 
const;
 
        /// Set a built-in function handler for the given event
        //
@@ -351,10 +363,14 @@
        ///       are the ones attached to a character with ActionScript code.
        ///
        /// @param id
+       ///     The event triggering the handler.
        ///
-       /// @param method
+       /// @param code
+       ///     An action buffer to execute when given event is triggered.
+       ///     The buffer is externally owned (not copied), make sure it
+       ///     is kept alive for the whole lifetime of this character.
        ///
-       void set_event_handler(const event_id& id, const as_value& method);
+       void add_event_handler(const event_id& id, const action_buffer& code);
 
        /// \brief
        /// Call this when a character get equipped

Index: server/dlist.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/dlist.cpp,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -b -r1.57 -r1.58
--- server/dlist.cpp    6 Apr 2007 11:43:44 -0000       1.57
+++ server/dlist.cpp    11 Apr 2007 14:20:20 -0000      1.58
@@ -1,5 +1,5 @@
 // 
-//   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+//   Copyright (C) 2005, 2006, 2007 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

Index: server/dlist.h
===================================================================
RCS file: /sources/gnash/gnash/server/dlist.h,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- server/dlist.h      6 Apr 2007 11:43:44 -0000       1.32
+++ server/dlist.h      11 Apr 2007 14:20:20 -0000      1.33
@@ -33,6 +33,10 @@
 #include <iosfwd>
 
 namespace gnash {
+       class cxform;
+}
+
+namespace gnash {
 
 /// A DisplayItem is simply a character object 
 typedef boost::intrusive_ptr<character> DisplayItem;

Index: server/event_id.h
===================================================================
RCS file: /sources/gnash/gnash/server/event_id.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/event_id.h   8 Feb 2007 16:23:28 -0000       1.4
+++ server/event_id.h   11 Apr 2007 14:20:20 -0000      1.5
@@ -108,6 +108,11 @@
                        || (m_key_code != key::INVALID && (m_id == KEY_PRESS)));
        }
 
+       void setKeyCode(unsigned char key)
+       {
+               m_key_code = key;
+       }
+
        bool    operator==(const event_id& id) const { return m_id == id.m_id 
&& m_key_code == id.m_key_code; }
 
        bool operator< (const event_id& id) const

Index: server/execute_tag.h
===================================================================
RCS file: /sources/gnash/gnash/server/execute_tag.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- server/execute_tag.h        21 Feb 2007 08:22:04 -0000      1.9
+++ server/execute_tag.h        11 Apr 2007 14:20:20 -0000      1.10
@@ -25,6 +25,8 @@
 #include "config.h"
 #endif
 
+#include "tu_types.h" // for uint32 typedef
+
 #include <cstdarg>
 #include <cassert>
 

Index: server/gnash.h
===================================================================
RCS file: /sources/gnash/gnash/server/gnash.h,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -b -r1.90 -r1.91
--- server/gnash.h      6 Apr 2007 07:58:16 -0000       1.90
+++ server/gnash.h      11 Apr 2007 14:20:20 -0000      1.91
@@ -17,7 +17,7 @@
 // 
 //
 
-/* $Id: gnash.h,v 1.90 2007/04/06 07:58:16 jgilmore Exp $ */
+/* $Id: gnash.h,v 1.91 2007/04/11 14:20:20 strk Exp $ */
 
 /// \mainpage
 ///
@@ -435,52 +435,6 @@
 };
 
 
-/// Color transform type, used by render handler
-class DSOEXPORT cxform
-{
-public:
-    /// [RGBA][multiply, add]
-    float      m_[4][2];
-    
-    /// Initialize to the identity color transform (no transform)
-    cxform();
-    
-    /// Concatenate c's transform onto ours. 
-    //
-    /// When transforming colors, c's transform is applied
-    /// first, then ours.
-    ///
-    void concatenate(const cxform& c);
-    
-    /// Apply our transform to the given color; return the result.
-    rgba transform(const rgba in) const;
-    
-    /// Faster transform() method for loops (avoids creation of rgba object)
-    void transform(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const;    
-    
-    /// Read RGB from the SWF input stream.
-    void read_rgb(stream* in);
-    
-    /// Read RGBA from the SWF input stream.
-    void read_rgba(stream* in);
-    
-    /// Force component values to be in range.
-    void clamp();
-    
-    /// Debug log.
-    void print() const;
-    
-    /// Returns true when the cxform equals identity (no transform)
-    bool is_identity() const;
-    
-    /// Returns true when the cxform leads to alpha == 0
-    bool is_invisible() const;
-    
-    /// The identity color transform (no transform)
-    static cxform      identity;
-};
-
-
 //
 // texture and render callback handler.
 //

Index: server/impl.h
===================================================================
RCS file: /sources/gnash/gnash/server/impl.h,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- server/impl.h       27 Feb 2007 09:10:20 -0000      1.42
+++ server/impl.h       11 Apr 2007 14:20:20 -0000      1.43
@@ -18,7 +18,7 @@
 //
 //
 
-/* $Id: impl.h,v 1.42 2007/02/27 09:10:20 strk Exp $ */
+/* $Id: impl.h,v 1.43 2007/04/11 14:20:20 strk Exp $ */
 
 #ifndef GNASH_IMPL_H
 #define GNASH_IMPL_H
@@ -30,6 +30,7 @@
 #include "tu_config.h"
 
 #include "gnash.h"
+#include "cxform.h" // for composition of display_info
 #include "types.h"
 #include "container.h"
 #include "utility.h"

Index: server/movie_root.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.cpp,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- server/movie_root.cpp       4 Apr 2007 20:30:45 -0000       1.55
+++ server/movie_root.cpp       11 Apr 2007 14:20:20 -0000      1.56
@@ -825,6 +825,12 @@
 }
 
 void
+movie_root::pushAction(std::auto_ptr<ExecutableCode> code)
+{
+       _actionQueue.push_back(code->clone());
+}
+
+void
 movie_root::pushAction(const action_buffer& buf, 
boost::intrusive_ptr<character> target)
 {
 #ifdef GNASH_DEBUG

Index: server/movie_root.h
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.h,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -b -r1.46 -r1.47
--- server/movie_root.h 3 Apr 2007 16:32:05 -0000       1.46
+++ server/movie_root.h 11 Apr 2007 14:20:20 -0000      1.47
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: movie_root.h,v 1.46 2007/04/03 16:32:05 strk Exp $ */
+/* $Id: movie_root.h,v 1.47 2007/04/11 14:20:20 strk Exp $ */
 
 /// \page events_handling Handling of user events
 ///
@@ -415,6 +415,9 @@
        }
 
        /// Push an executable code to the ActionQueue
+       void pushAction(std::auto_ptr<ExecutableCode> code);
+
+       /// Push an executable code to the ActionQueue
        void pushAction(const action_buffer& buf, 
boost::intrusive_ptr<character> target);
 
        /// Push a function code to the ActionQueue

Index: server/sprite_instance.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v
retrieving revision 1.231
retrieving revision 1.232
diff -u -b -r1.231 -r1.232
--- server/sprite_instance.cpp  11 Apr 2007 08:55:05 -0000      1.231
+++ server/sprite_instance.cpp  11 Apr 2007 14:20:20 -0000      1.232
@@ -51,6 +51,7 @@
 #include "StreamProvider.h"
 #include "URLAccessManager.h" // for loadVariables
 #include "LoadVariablesThread.h" 
+#include "ExecutableCode.h"
 
 #include <vector>
 #include <string>
@@ -1352,6 +1353,7 @@
        gettersetter = new builtin_function(&sprite_soundbuftime_getset, NULL);
        o.init_property("_soundbuftime", *gettersetter, *gettersetter);
 
+#if 0
        gettersetter = new builtin_function(&character::onrollover_getset, 
NULL);
        o.init_property("onRollOver", *gettersetter, *gettersetter);
 
@@ -1369,6 +1371,7 @@
 
        gettersetter = new builtin_function(&character::onmousemove_getset, 
NULL);
        o.init_property("onMouseMove", *gettersetter, *gettersetter);
+#endif
 
 }
 
@@ -1943,12 +1946,11 @@
                        
        // First, check for built-in event handler.
        {
-               as_value        method = get_event_handler(id);
-                   
-               if (!method.is_undefined())
+               std::auto_ptr<ExecutableCode> code ( get_event_handler(id) );
+               if ( code.get() )
                {
                        // Dispatch.
-                       call_method0(method, &m_as_environment, this);
+                       code->execute();
 
                        called = true;
                        // Fall through and call the function also, if it's 
defined!
@@ -1967,25 +1969,15 @@
 
        // Check for member function.
        {
-               // In ActionScript 2.0, event method names are CASE SENSITIVE.
-               // In ActionScript 1.0, event method names are CASE INSENSITIVE.
-               // TODO: move to get_function_name directly ?
-               std::string method_name = id.get_function_name();
-               if ( _vm.getSWFVersion() < 7 )
-               {
-                       boost::to_lower(method_name, _vm.getLocale());
-               }
+               boost::intrusive_ptr<as_function> method = 
+                       getUserDefinedEventHandler(id.get_function_name());
 
-               if (method_name.length() > 0)
-               {
-                       as_value        method;
-                       if (get_member(method_name, &method) && ! 
method.is_undefined() )
+               if ( method )
                        {
-                               call_method0(method, &m_as_environment, this);
+                       call_method0(as_value(method.get()), &m_as_environment, 
this);
                                called = true;
                        }
                }
-       }
 
        testInvariant();
 
@@ -2013,6 +2005,11 @@
        log_msg("sprite[%p]::set_member(%s, %s)", (void*)this, name.c_str(), 
val.to_string());
 #endif
 
+       if ( val.is_function() )
+       {
+               checkForKeyPressOrMouseEvent(name);
+       }
+
        // Try textfield variables
        //
        // FIXME: Turn textfield variables into Getter/Setters (Properties)
@@ -2706,7 +2703,9 @@
        // Attach event handlers (if any).
        for (size_t i = 0, n = event_handlers.size(); i < n; i++)
        {
-               event_handlers[i]->attach_to(ch.get());
+               swf_event* ev = event_handlers[i];
+               ch->add_event_handler(ev->event(), ev->action());
+               //event_handlers[i]->attach_to(*ch);
        }
 
        m_display_list.place_character(
@@ -2891,8 +2890,6 @@
 bool
 sprite_instance::can_handle_mouse_event() const
 {
-       as_value dummy;
-
        // Event handlers that qualify as mouse event handlers.
        static const event_id EH[] =
        {
@@ -2903,45 +2900,20 @@
                event_id(event_id::ROLL_OUT),
                event_id(event_id::DRAG_OVER),
                event_id(event_id::DRAG_OUT),
-               // MOUSE_{DOWN,UP,MOVE} are handled
-               // differently, in that they are called
-               // reguardles of mouse position
-               // See has_mouse_event
-               //event_id(event_id::MOUSE_DOWN),
-               //event_id(event_id::MOUSE_UP)
-               //event_id(event_id::MOUSE_MOVE)
        };
 
-       int swfversion =  _vm.getSWFVersion();
        for (unsigned int i = 0; i < ARRAYSIZE(EH); i++)
        {
                const event_id &event = EH[i];
 
                // Check event handlers
-               dummy = get_event_handler(event.id());
-               if (!dummy.is_undefined())
+               if ( get_event_handler(event.id()).get() )
                {
                        return true;
                }
 
                // Check user-defined event handlers
-               // TODO: check if it's possible to actually
-               //       have an hard-coded handler and a user-defined
-               //       one. If this is not the case we should add
-               //       gettersetter memebers for all these handlers.
-               //
-               std::string fname = event.get_function_name();
-               if ( swfversion < 7 )
-               {
-                       // TODO: have event.get_function_name()
-                       //       return an SWF-contextual string  instead!
-                       boost::to_lower(fname, _vm.getLocale());
-               }
-
-               // The const_cast is needed because get_member, due to
-               // possible "getter" methods executing stuff, is a non-const
-               // function. We take the "risk" here...
-               if (const_cast<sprite_instance*>(this)->get_member(fname, 
&dummy))
+               if ( getUserDefinedEventHandler(event.get_function_name()) )
                {
                        return true;
                }
@@ -3301,28 +3273,6 @@
        _target_dot.clear();
 }
 
-/* private static */
-bool
-sprite_instance::sameEvents(const Events& eventsMap, const SWFEventsVector& 
eventsVect)
-{
-       size_t n = eventsVect.size();
-       if (eventsMap.size() != n) return false;
-
-       for (size_t i = 0; i < n; i++)
-       {
-               Events::const_iterator it = 
eventsMap.find(eventsVect[i]->m_event);
-
-               if ( it == eventsMap.end() ) return false;
-
-               as_value result = it->second;
-               // compare actionscipt in event
-               if (eventsVect[i]->m_method != result) return false;
-       }
-
-       return true;
-       
-}
-
 bool
 sprite_instance::loadMovie(const URL& url)
 {
@@ -3498,4 +3448,32 @@
 
 }
 
+void
+sprite_instance::checkForKeyPressOrMouseEvent(const std::string& name)
+{
+       // short-cut
+       if ( name.size() < 9 ) return;
+
+       // TODO: don't use strcmp/strcasecmp, we're a C++ application after all 
!
+
+       typedef int (*cmp_t) (const char*, const char*);
+       cmp_t cmp = strcmp;
+       if ( _vm.getSWFVersion() < 7 ) cmp = strcasecmp;
+
+       const char* ptr = name.c_str();
+
+       if ( ! cmp(ptr, "onkeypress") )
+       {
+               has_keypress_event();
+       }
+       else if ( ! cmp(ptr, "onMouseDown")
+               || ! cmp(ptr, "onMouseUp") 
+               || ! cmp(ptr, "onMouseMove") )
+       {
+               has_mouse_event();
+       }
+
+}
+
+
 } // namespace gnash

Index: server/sprite_instance.h
===================================================================
RCS file: /sources/gnash/gnash/server/sprite_instance.h,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -b -r1.93 -r1.94
--- server/sprite_instance.h    10 Apr 2007 21:44:14 -0000      1.93
+++ server/sprite_instance.h    11 Apr 2007 14:20:20 -0000      1.94
@@ -17,7 +17,7 @@
 // 
 //
 
-/* $Id: sprite_instance.h,v 1.93 2007/04/10 21:44:14 strk Exp $ */
+/* $Id: sprite_instance.h,v 1.94 2007/04/11 14:20:20 strk Exp $ */
 
 // Stateful live Sprite instance
 
@@ -749,6 +749,17 @@
 
 private:
 
+       /// \brief
+       /// Call has_keypress_event() or has_mouse_event()
+       /// if the given string correspond to an event handler
+       /// for which registering as a listener of Mouse or Key is needed
+       //
+       ///
+       /// @param name
+       ///     Member name. 
+       ///
+       void checkForKeyPressOrMouseEvent(const std::string& name);
+
        /// Duplicate the object with the specified name
        /// and add it with a new name  at a new depth.
        void clone_display_object(const std::string& name,
@@ -878,15 +889,6 @@
        /// Build the _target member recursive on parent
        std::string computeTargetPath() const;
 
-       /// Compare two events sets 
-       //
-       /// @return 
-       ///     true if the two sets contain the same values, false otherwise.
-       ///     Note that in the eventsMap, only the value is compared, and
-       ///     the key is discarded.
-       ///
-       static bool sameEvents(const Events& eventsMap, const SWFEventsVector& 
eventsVect);
-
        /// The DisplayList resulting by execution of tags in first frame.
        //
        /// It will be used to reinitialized actual DisplayList on restart.

Index: server/swf_event.h
===================================================================
RCS file: /sources/gnash/gnash/server/swf_event.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/swf_event.h  7 Feb 2007 00:59:59 -0000       1.4
+++ server/swf_event.h  11 Apr 2007 14:20:20 -0000      1.5
@@ -23,7 +23,7 @@
 
 #include "as_value.h" // for composition
 #include "action_buffer.h" // for composition
-#include "action.h" // for event_id
+#include "event_id.h" // for composition
 
 #include <cassert>
 
@@ -34,28 +34,43 @@
 //
 
 /// For embedding event handlers in place_object_2
+//
+/// TODO: move under parser dir !
+///
 class swf_event
 {
 public:
-    // NOTE: DO NOT USE THESE AS VALUE TYPES IN AN
-    // std::vector<>!  They cannot be moved!  The private
-    // operator=(const swf_event&) should help guard
-    // against that.
 
-    event_id   m_event;
-    action_buffer      m_action_buffer;
-    as_value   m_method;
+       swf_event(const event_id& ev, std::auto_ptr<action_buffer> buf)
+               :
+               m_event(ev),
+               m_action_buffer(buf)
+       {
+       }
 
     swf_event()
        {
        }
 
-    void       attach_to(character* ch) const
+       const action_buffer& action()
+       {
+               return *m_action_buffer;
+       }
+
+       event_id& event()
        {
-           ch->set_event_handler(m_event, m_method);
+               return m_event;
        }
 
 private:
+
+    // NOTE: DO NOT USE THESE AS VALUE TYPES IN AN
+    // std::vector<>!  They cannot be moved!  The private
+    // operator=(const swf_event&) should help guard
+    // against that.
+
+    event_id   m_event;
+    std::auto_ptr<action_buffer> m_action_buffer;
     // DON'T USE THESE
     swf_event(const swf_event& /*s*/) { assert(0); }
     void       operator=(const swf_event& /*s*/) { assert(0); }

Index: server/types.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/types.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -b -r1.20 -r1.21
--- server/types.cpp    1 Mar 2007 11:06:32 -0000       1.20
+++ server/types.cpp    11 Apr 2007 14:20:20 -0000      1.21
@@ -38,160 +38,6 @@
 
 
        //
-       // cxform
-       //
-
-
-       cxform  cxform::identity;
-
-
-       cxform::cxform()
-       // Initialize to identity transform.
-       {
-               m_[0][0] = 1;
-               m_[1][0] = 1;
-               m_[2][0] = 1;
-               m_[3][0] = 1;
-               m_[0][1] = 0;
-               m_[1][1] = 0;
-               m_[2][1] = 0;
-               m_[3][1] = 0;
-       }
-
-       void    cxform::concatenate(const cxform& c)
-       // Concatenate c's transform onto ours.  When
-       // transforming colors, c's transform is applied
-       // first, then ours.
-       {
-               m_[0][1] += m_[0][0] * c.m_[0][1];
-               m_[1][1] += m_[1][0] * c.m_[1][1];
-               m_[2][1] += m_[2][0] * c.m_[2][1];
-               m_[3][1] += m_[3][0] * c.m_[3][1];
-
-               m_[0][0] *= c.m_[0][0];
-               m_[1][0] *= c.m_[1][0];
-               m_[2][0] *= c.m_[2][0];
-               m_[3][0] *= c.m_[3][0];
-       }
-
-       
-       rgba    cxform::transform(const rgba in) const
-       // Apply our transform to the given color; return the result.
-       {
-               rgba    result(in.m_r, in.m_g, in.m_b, in.m_a);
-               
-               transform(result.m_r, result.m_g, result.m_b, result.m_a);
-
-               return result;
-       }
-
-  void cxform::transform(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const
-  // Faster transform() method for loops (avoids creation of rgba object)
-  {
-               r = (uint8_t) fclamp(r * m_[0][0] + m_[0][1], 0, 255);
-               g = (uint8_t) fclamp(g * m_[1][0] + m_[1][1], 0, 255);
-               b = (uint8_t) fclamp(b * m_[2][0] + m_[2][1], 0, 255);
-               a = (uint8_t) fclamp(a * m_[3][0] + m_[3][1], 0, 255);
-  }
-
-       void    cxform::read_rgb(stream* in)
-       {
-               in->align();
-
-               int     has_add = in->read_uint(1);
-               int     has_mult = in->read_uint(1);
-               int     nbits = in->read_uint(4);
-
-               if (has_mult) {
-                       m_[0][0] = in->read_sint(nbits) / 255.0f;
-                       m_[1][0] = in->read_sint(nbits) / 255.0f;
-                       m_[2][0] = in->read_sint(nbits) / 255.0f;
-                       m_[3][0] = 1;
-               }
-               else {
-                       for (int i = 0; i < 4; i++) { m_[i][0] = 1; }
-               }
-               if (has_add) {
-                       m_[0][1] = (float) in->read_sint(nbits);
-                       m_[1][1] = (float) in->read_sint(nbits);
-                       m_[2][1] = (float) in->read_sint(nbits);
-                       m_[3][1] = 1;
-               }
-               else {
-                       for (int i = 0; i < 4; i++) { m_[i][1] = 0; }
-               }
-       }
-
-       void    cxform::read_rgba(stream* in)
-       {
-               in->align();
-
-               int     has_add = in->read_uint(1);
-               int     has_mult = in->read_uint(1);
-               int     nbits = in->read_uint(4);
-
-               if (has_mult) {
-                       m_[0][0] = in->read_sint(nbits) / 256.0f;
-                       m_[1][0] = in->read_sint(nbits) / 256.0f;
-                       m_[2][0] = in->read_sint(nbits) / 256.0f;
-                       m_[3][0] = in->read_sint(nbits) / 256.0f;
-               }
-               else {
-                       for (int i = 0; i < 4; i++) { m_[i][0] = 1; }
-               }
-               if (has_add) {
-                       m_[0][1] = (float) in->read_sint(nbits);
-                       m_[1][1] = (float) in->read_sint(nbits);
-                       m_[2][1] = (float) in->read_sint(nbits);
-                       m_[3][1] = (float) in->read_sint(nbits);
-               }
-               else {
-                       for (int i = 0; i < 4; i++) { m_[i][1] = 0; }
-               }
-       }
-
-        /// Force component values to be in legal range.
-        void cxform::clamp()
-       {
-               m_[0][0] = fclamp(m_[0][0], 0, 1);
-               m_[1][0] = fclamp(m_[1][0], 0, 1);
-               m_[2][0] = fclamp(m_[2][0], 0, 1);
-               m_[3][0] = fclamp(m_[3][0], 0, 1);
-               
-               m_[0][1] = fclamp(m_[0][1], -255.0f, 255.0f);
-               m_[1][1] = fclamp(m_[1][1], -255.0f, 255.0f);
-               m_[2][1] = fclamp(m_[2][1], -255.0f, 255.0f);
-               m_[3][1] = fclamp(m_[3][1], -255.0f, 255.0f);
-       }
-
-       void    cxform::print() const
-       // Debug log.
-       {
-               log_parse("    *         +");
-               log_parse("| %4.4f %4.4f|", m_[0][0], m_[0][1]);
-               log_parse("| %4.4f %4.4f|", m_[1][0], m_[1][1]);
-               log_parse("| %4.4f %4.4f|", m_[2][0], m_[2][1]);
-               log_parse("| %4.4f %4.4f|", m_[3][0], m_[3][1]);
-       }
-       
-       bool    cxform::is_identity() const
-       // Returns true when the cxform equals identity (no transform)
-       {          
-         for (int a=0; a<4; a++)
-          for (int b=0; b<2; b++)
-           if (m_[a][b] != identity.m_[a][b])
-            return false;
-         
-         return true;
-  }
-
-       bool    cxform::is_invisible() const
-       // Returns true when the cxform leads to alpha == 0
-       {
-               return (255.0 * m_[3][0] + m_[3][1]) <= 0.0;    
-  }
-
-       //
        // rgba
        //
 

Index: server/parser/button_character_def.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/button_character_def.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/parser/button_character_def.h        27 Feb 2007 09:10:20 -0000      
1.11
+++ server/parser/button_character_def.h        11 Apr 2007 14:20:20 -0000      
1.12
@@ -14,7 +14,7 @@
 #include "sound_definition.h"
 #include "rect.h" // for get_bound
 #include "matrix.h" // for composition
-#include "gnash.h" // for class cxform :(
+#include "cxform.h" // for composition
 
 #ifndef UNUSED
 #define UNUSED(x) ((x) = (x))
@@ -23,6 +23,7 @@
 // Forward declarations
 namespace gnash {
        class sprite_instance;
+       class action_buffer;
 }
 
 namespace gnash {

Index: server/parser/shape_character_def.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/shape_character_def.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- server/parser/shape_character_def.h 19 Feb 2007 11:08:23 -0000      1.10
+++ server/parser/shape_character_def.h 11 Apr 2007 14:20:20 -0000      1.11
@@ -5,7 +5,7 @@
 
 // Quadratic bezier outline shapes, the basis for most SWF rendering.
 
-/* $Id: shape_character_def.h,v 1.10 2007/02/19 11:08:23 strk Exp $ */
+/* $Id: shape_character_def.h,v 1.11 2007/04/11 14:20:20 strk Exp $ */
 
 #ifndef GNASH_SHAPE_CHARACTER_DEF_H
 #define GNASH_SHAPE_CHARACTER_DEF_H
@@ -18,6 +18,11 @@
 
 
 namespace gnash {
+       class cxform;
+       class matrix;
+}
+
+namespace gnash {
 
        /// \brief
        /// Represents the outline of one or more shapes, along with

Index: server/swf/tag_loaders.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/tag_loaders.cpp,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -b -r1.87 -r1.88
--- server/swf/tag_loaders.cpp  10 Apr 2007 21:09:00 -0000      1.87
+++ server/swf/tag_loaders.cpp  11 Apr 2007 14:20:21 -0000      1.88
@@ -14,14 +14,12 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: tag_loaders.cpp,v 1.87 2007/04/10 21:09:00 strk Exp $ */
+/* $Id: tag_loaders.cpp,v 1.88 2007/04/11 14:20:21 strk Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <zlib.h>
-
 #include "tu_file.h"
 #include "utility.h"
 #include "action.h"
@@ -54,6 +52,9 @@
 #include "GnashException.h"
 #include "video_stream_def.h"
 #include "sound_definition.h"
+#include "PlaceObject2Tag.h"
+
+#include <zlib.h>
 
 namespace gnash {
 
@@ -766,430 +767,6 @@
        }
 }
 
-/// SWF Tag PlaceObject (4) or PlaceObject2 (9) 
-class place_object_2 : public execute_tag
-{
-public:
-    int        m_tag_type;
-    char*      m_name;
-    float      m_ratio;
-    cxform     m_color_transform;
-    matrix     m_matrix;
-    bool       m_has_matrix;
-    bool       m_has_cxform;
-    int                m_depth;
-    uint16_t   m_character_id;
-    int        m_clip_depth;
-    enum place_type {
-       PLACE,
-       MOVE,
-       REPLACE
-    } m_place_type;
-    std::vector<swf_event*>    m_event_handlers;
-
-
-    place_object_2()
-       :
-       m_tag_type(0),
-       m_name(NULL),
-       m_ratio(0),
-       m_has_matrix(false),
-       m_has_cxform(false),
-       m_depth(0),
-       m_character_id(0),
-       m_clip_depth(0),
-       m_place_type(PLACE)
-       {
-       }
-
-       ~place_object_2()
-       {
-           delete [] m_name;
-           m_name = NULL;
-
-           for (int i = 0, n = m_event_handlers.size(); i < n; i++)
-               {
-                   delete m_event_handlers[i];
-               }
-           m_event_handlers.resize(0);
-       }
-
-       // read SWF::PLACEOBJECT 
-       void readPlaceObject(stream* in)
-       {
-               // Original place_object tag; very simple.
-               m_character_id = in->read_u16();
-               m_depth = in->read_u16()+character::staticDepthOffset;
-               m_matrix.read(in);
-
-               IF_VERBOSE_PARSE
-               (
-                       log_parse("  char_id = %d", m_character_id);
-                       log_parse("  depth = %d (%d)", m_depth, 
m_depth-character::staticDepthOffset);
-                       m_matrix.print();
-               );
-
-               if (in->get_position() < in->get_tag_end_position())
-               {
-                       m_color_transform.read_rgb(in);
-
-                       IF_VERBOSE_PARSE
-                       (
-                               log_parse("  cxform:");
-                               m_color_transform.print();
-                       );
-
-               }
-       }
-
-       // read placeObject2 actions
-       void readPlaceActions(stream* in, int movie_version)
-       {
-
-               uint16_t reserved = in->read_u16();
-               assert(reserved == 0);  // must be 0
-
-               // The logical 'or' of all the following handlers.
-               // I don't think we care about this...
-               uint32_t all_flags = (movie_version >= 6) ?
-                       in->read_u32() : in->read_u16();
-               UNUSED(all_flags);
-
-               IF_VERBOSE_PARSE (
-                       log_parse("  actions: flags = 0x%X", all_flags);
-               );
-
-               // Read swf_events.
-               for (;;)
-               {
-                       // Read event.
-                       in->align();
-
-                       uint32_t flags = (movie_version >= 6) ? in->read_u32() 
: in->read_u16();
-
-                       if (flags == 0)
-                       {
-                               // Done with events.
-                               break;
-                       }
-
-                       uint32_t event_length = in->read_u32();
-                       if ( in->get_tag_end_position()-in->get_position() <  
event_length )
-                       {
-                               IF_VERBOSE_MALFORMED_SWF(
-                               log_swferror("swf_event::read(), "
-                                       "even_length = %u, but only %lu bytes 
left "
-                                       "to the end of current tag."
-                                       " Breaking for safety.",
-                                       event_length, 
in->get_tag_end_position()-in->get_position());
-                               );
-                               break;
-                       }
-
-                       uint8 ch = key::INVALID;
-
-                       if (flags & (1 << 17))  // has keypress event
-                       {
-                               ch = in->read_u8();
-                               event_length--;
-                       }
-
-                       // Read the actions for event(s)
-                       action_buffer action;
-                       action.read(in);
-
-                       size_t readlen = action.size();
-                       if (readlen > event_length)
-                       {
-                               IF_VERBOSE_MALFORMED_SWF(
-                               log_swferror("swf_event::read(), "
-                                       "event_length = %d, "
-                                       "but read " SIZET_FMT
-                                       ". Breaking for safety.",
-                                       event_length, readlen);
-                               );
-                               // or should we just continue here ?
-                               break;
-                       }
-                       else if ( readlen < event_length )
-                       {
-                               IF_VERBOSE_MALFORMED_SWF(
-                               log_swferror("swf_event::read(), "
-                                       "event_length = %d, "
-                                       "but read " SIZET_FMT 
-                                       ". Skipping excessive bytes.",
-                                       event_length, readlen);
-                               );
-                               in->skip_bytes(event_length - readlen);
-                       }
-
-                       // 13 bits reserved, 19 bits used
-                       static const event_id s_code_bits[19] =
-                       {
-                               event_id::LOAD,
-                               event_id::ENTER_FRAME,
-                               event_id::UNLOAD,
-                               event_id::MOUSE_MOVE,
-                               event_id::MOUSE_DOWN,
-                               event_id::MOUSE_UP,
-                               event_id::KEY_DOWN,
-                               event_id::KEY_UP,
-
-                               event_id::DATA,
-                               event_id::INITIALIZE,
-                               event_id::PRESS,
-                               event_id::RELEASE,
-                               event_id::RELEASE_OUTSIDE,
-                               event_id::ROLL_OVER,
-                               event_id::ROLL_OUT,
-                               event_id::DRAG_OVER,
-
-                               event_id::DRAG_OUT,
-                               event_id(event_id::KEY_PRESS, key::CONTROL),
-                               event_id::CONSTRUCT
-                       };
-
-                       // Let's see if the event flag we received is for an 
event that we know of
-                       if ((pow(2.0, int( sizeof(s_code_bits) / 
sizeof(s_code_bits[0]) )) - 1) < flags)
-                       {
-                               IF_VERBOSE_MALFORMED_SWF(
-                               log_swferror("swf_event::read() -- unknown / 
unhandled event type received, flags = 0x%x", flags);
-                               );
-                       }
-
-                       for (int i = 0, mask = 1; i < 
int(sizeof(s_code_bits)/sizeof(s_code_bits[0])); i++, mask <<= 1)
-                       {
-                               if (flags & mask)
-                               {
-                                       swf_event*      ev = new swf_event;
-                                       ev->m_event = s_code_bits[i];
-                                       ev->m_action_buffer = action;
-//                                     log_action("---- actions for event %s", 
ev->m_event.get_function_name().c_str());
-
-                                       // hack
-                                       if (i == 17)    // has keypress event ?
-                                       {
-                                               ev->m_event.m_key_code = ch;
-                                       }
-
-                                       // Create a function to execute the 
actions.
-                                       std::vector<with_stack_entry>   
empty_with_stack;
-                                       swf_function*   func = new 
swf_function(&ev->m_action_buffer, NULL, 0, empty_with_stack);
-                                       
func->set_length(ev->m_action_buffer.get_length());
-
-                                       ev->m_method.set_as_function(func);
-
-                                       m_event_handlers.push_back(ev);
-                               }
-                       }
-               }
-       }
-
-
-       // read SWF::PLACEOBJECT2
-       void readPlaceObject2(stream* in, int movie_version)
-       {
-               in->align();
-
-               bool    has_actions = in->read_uint(1) ? true : false;
-               bool    has_clip_bracket = in->read_uint(1) ? true : false;
-               bool    has_name = in->read_uint(1) ? true : false;
-               bool    has_ratio = in->read_uint(1) ? true : false;
-               bool    has_cxform = in->read_uint(1) ? true : false;
-               bool    has_matrix = in->read_uint(1) ? true : false;
-               bool    has_char = in->read_uint(1) ? true : false;
-               bool    flag_move = in->read_uint(1) ? true : false;
-
-               m_depth = in->read_u16()+character::staticDepthOffset;
-
-               if (has_char) m_character_id = in->read_u16();
-
-               if (has_matrix)
-               {
-                       m_has_matrix = true;
-                       m_matrix.read(in);
-               }
-
-               if (has_cxform)
-               {
-                       m_has_cxform = true;
-                       m_color_transform.read_rgba(in);
-               }
-                               
-               if (has_ratio) m_ratio = (float)in->read_u16() / (float)65535;
-
-               if (has_name) m_name = in->read_string();
-
-               if (has_clip_bracket) m_clip_depth = 
in->read_u16()+character::staticDepthOffset; 
-
-               if (has_actions)
-               {
-                       readPlaceActions(in, movie_version);
-               }
-
-
-               if (has_char == true && flag_move == true)
-               {
-                       // Remove whatever's at m_depth, and put m_character 
there.
-                       m_place_type = REPLACE;
-               }
-               else if (has_char == false && flag_move == true)
-               {
-                       // Moves the object at m_depth to the new location.
-                       m_place_type = MOVE;
-               }
-               else if (has_char == true && flag_move == false)
-               {
-                       // Put m_character at m_depth.
-                       m_place_type = PLACE;
-               }
-
-               IF_VERBOSE_PARSE (
-                       log_parse("  PLACEOBJECT2: depth = %d (%d)", m_depth, 
m_depth-character::staticDepthOffset);
-                       if ( has_char ) log_parse("  char id = %d", 
m_character_id);
-                       if ( has_matrix ) 
-                       {
-                               log_parse("  mat:");
-                               m_matrix.print();
-                       }
-                       if ( has_cxform )
-                       {
-                               log_parse("  cxform:");
-                               m_color_transform.print();
-                       }
-                       if ( has_ratio ) log_parse("  ratio: %f", m_ratio);
-                       if ( has_name ) log_parse("  name = %s", m_name ? 
m_name : "<null>");
-                       if ( has_clip_bracket ) log_parse("  clip_depth = %d 
(%d)", m_clip_depth, m_clip_depth-character::staticDepthOffset);
-                       log_parse(" m_place_type: %d", m_place_type);
-               );
-                               
-
-                                
-               //log_msg("place object at depth %i", m_depth);
-       }
-
-       // read SWF::PLACEOBJECT or SWF::PLACEOBJECT2
-       void read(stream* in, tag_type tag, int movie_version)
-       {
-
-               m_tag_type = tag;
-
-               if (tag == SWF::PLACEOBJECT)
-               {
-                       readPlaceObject(in);
-               }
-               else
-               {
-                       readPlaceObject2(in, movie_version);
-               }
-       }
-
-               
-       /// Place/move/whatever our object in the given movie.
-       void execute(sprite_instance* m)
-       {
-           switch (m_place_type) {
-             case PLACE:
-                 m->add_display_object(
-                     m_character_id,
-                     m_name,
-                     m_event_handlers,
-                     m_depth,
-                     m->is_reverse_execution(),        // place_object doesn't 
do replacement when not in reverse execution
-                     m_color_transform,
-                     m_matrix,
-                     m_ratio,
-                     m_clip_depth);
-                 break;
-                 
-             case MOVE:
-                 m->move_display_object(
-                     m_depth,
-                     m_has_cxform,
-                     m_color_transform,
-                     m_has_matrix,
-                     m_matrix,
-                     m_ratio,
-                     m_clip_depth);
-                 break;
-                 
-             case REPLACE:
-                 m->replace_display_object(
-                     m_character_id,
-                     m_name,
-                     m_depth,
-                     m_has_cxform,
-                     m_color_transform,
-                     m_has_matrix,
-                     m_matrix,
-                     m_ratio,
-                     m_clip_depth);
-                 break;
-           }
-       }
-    
-       /// Proxy for execute(sprite_instance*)
-       void execute_state(sprite_instance* m)
-       {
-           execute(m);
-       }
-    
-       void execute_state_reverse(sprite_instance* m, int frame)
-       {
-           switch (m_place_type) {
-             case PLACE:
-                 // reverse of add is remove
-                 m->remove_display_object(m_depth, m_tag_type == 4 ? 
m_character_id : -1);
-                 break;
-                 
-             case MOVE:
-                 // reverse of move is move
-                 m->move_display_object(
-                     m_depth,
-                     m_has_cxform,
-                     m_color_transform,
-                     m_has_matrix,
-                     m_matrix,
-                     m_ratio,
-                     m_clip_depth);
-                 break;
-                 
-             case REPLACE:
-             {
-                 // reverse of replace is to re-add the previous object.
-                 execute_tag*  last_add = 
m->find_previous_replace_or_add_tag(frame, m_depth, -1);
-                 if (last_add) {
-                     last_add->execute_state(m);
-                 } else {
-                     log_error("reverse REPLACE can't find previous replace or 
add tag(%d, %d)",
-                               frame, m_depth);
-                     
-                 }
-                 break;
-             }
-           }
-       }
-    
-       virtual uint32  get_depth_id_of_replace_or_add_tag() const
-       {
-               uint32 depthid = 0;
-               if (m_place_type == PLACE || m_place_type == REPLACE)
-               {
-                       int id = -1;
-                       if (m_tag_type == SWF::PLACEOBJECT)
-                       {
-                           // Old-style PlaceObject; the corresponding Remove
-                           // is specific to the character_id.
-                           id = m_character_id;
-                       }
-                       depthid = ((m_depth & 0x0FFFF) << 16) | (id & 0x0FFFF);
-               }
-               return depthid;
-       }
-};
-
-
-       
 void
 place_object_2_loader(stream* in, tag_type tag, movie_definition* m)
 {
@@ -1200,7 +777,8 @@
     log_parse("  place_object_2");
                );
 
-    place_object_2*    ch = new place_object_2;
+    // TODO: who owns and is going to remove this tag ?
+    PlaceObject2Tag* ch = new PlaceObject2Tag(*m);
     ch->read(in, tag, m->get_version());
 
     m->add_execute_tag(ch);

Index: server/vm/ExecutableCode.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/ExecutableCode.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/vm/ExecutableCode.h  2 Apr 2007 17:22:29 -0000       1.3
+++ server/vm/ExecutableCode.h  11 Apr 2007 14:20:21 -0000      1.4
@@ -14,7 +14,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: ExecutableCode.h,v 1.3 2007/04/02 17:22:29 strk Exp $ */
+/* $Id: ExecutableCode.h,v 1.4 2007/04/11 14:20:21 strk Exp $ */
 
 #ifndef GNASH_EXECUTABLECODE_H
 #define GNASH_EXECUTABLECODE_H
@@ -42,6 +42,8 @@
 
        virtual void execute()=0;
 
+       virtual ExecutableCode* clone() const=0;
+
        virtual ~ExecutableCode() {}
 };
 
@@ -56,6 +58,11 @@
                target(nTarget)
        {}
 
+       ExecutableCode* clone() const
+       {
+               return new GlobalCode(*this);
+       }
+
        virtual void execute()
        {
                if ( ! target->isUnloaded() )
@@ -76,6 +83,66 @@
        boost::intrusive_ptr<character> target;
 };
 
+/// Event code 
+class EventCode: public ExecutableCode {
+
+public:
+
+       typedef vector<const action_buffer*> BufferList;
+
+       EventCode(boost::intrusive_ptr<character> nTarget)
+               :
+               _target(nTarget)
+       {}
+
+       EventCode(boost::intrusive_ptr<character> nTarget, const BufferList& 
buffers)
+               :
+               _target(nTarget),
+               _buffers(buffers)
+       {}
+
+
+       ExecutableCode* clone() const
+       {
+               return new EventCode(*this);
+       }
+
+       /// Add an action buffer to this event handler
+       //
+       /// @param buffer
+       ///     An action buffer to execute. Externally owned
+       ///     and not copied, so make sure it's kept
+       ///     alive for the whole EventCode lifetime.
+       ///
+       void addAction(const action_buffer& buffer)
+       {
+               _buffers.push_back(&buffer);
+       }
+
+       virtual void execute()
+       {
+               // We do want to call the onUnload event handler !!
+               //if ( _target->isUnloaded() )
+               //{
+                       //log_msg("Sprite %s unloaded, won't execute global 
code in it", target->getTargetPath().c_str());
+               //      return;
+               //}
+               for (BufferList::iterator it=_buffers.begin(), 
itEnd=_buffers.end();
+                               it != itEnd; ++it)
+               {
+                       ActionExec exec(*(*it), _target->get_environment());
+                       exec();
+               }
+       }
+
+private:
+
+       boost::intrusive_ptr<character> _target;
+
+       BufferList _buffers;
+
+};
+
 /// Function code
 class FunctionCode: public ExecutableCode {
 
@@ -87,9 +154,13 @@
                target(nTarget)
        {}
 
+       ExecutableCode* clone() const
+       {
+               return new FunctionCode(*this);
+       }
+
        virtual void execute()
        {
-               //log_msg("Execution of FunctionCode unimplemented yet");
                as_environment env; env.set_target(target.get());
                func->call(fn_call(target.get(), &env, 0, 0));
        }

Index: server/vm/action.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/action.cpp,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- server/vm/action.cpp        22 Mar 2007 11:38:57 -0000      1.11
+++ server/vm/action.cpp        11 Apr 2007 14:20:21 -0000      1.12
@@ -485,10 +485,10 @@
                "onPress",               // PRESS
                "onRelease",             // RELEASE
                "onRelease_Outside",     // RELEASE_OUTSIDE
-               "onRoll_Over",           // ROLL_OVER
-               "onRoll_Out",            // ROLL_OUT
-               "onDrag_Over",           // DRAG_OVER
-               "onDrag_Out",            // DRAG_OUT
+               "onRollOver",            // ROLL_OVER
+               "onRollOut",             // ROLL_OUT
+               "onDragOver",            // DRAG_OVER
+               "onDragOut",             // DRAG_OUT
                "onKeyPress",            // KEY_PRESS
                "onInitialize",          // INITIALIZE
 

Index: testsuite/actionscript.all/MovieClip.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/MovieClip.as,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -b -r1.50 -r1.51
--- testsuite/actionscript.all/MovieClip.as     11 Apr 2007 08:39:30 -0000      
1.50
+++ testsuite/actionscript.all/MovieClip.as     11 Apr 2007 14:20:21 -0000      
1.51
@@ -22,7 +22,7 @@
 // compile this test case with Ming makeswf, and then
 // execute it like this gnash -1 -r 0 -v out.swf
 
-rcsid="$Id: MovieClip.as,v 1.50 2007/04/11 08:39:30 strk Exp $";
+rcsid="$Id: MovieClip.as,v 1.51 2007/04/11 14:20:21 strk Exp $";
 
 #include "check.as"
 
@@ -165,6 +165,26 @@
 check_equals(mc.onRollOver, undefined);
 check_equals(mc.onSetFocus, undefined);
 check_equals(mc.onUnload, undefined);
+#if OUTPUT_VERSION >=6
+check(! mc.hasOwnProperty('onData'));
+check(! mc.hasOwnProperty('onDragOut'));
+check(! mc.hasOwnProperty('onDragOver'));
+check(! mc.hasOwnProperty('onEnterFrame')); 
+check(! mc.hasOwnProperty('onKeyDown'));
+check(! mc.hasOwnProperty('onKeyUp'));
+check(! mc.hasOwnProperty('onKillFocus'));
+check(! mc.hasOwnProperty('onLoad'));
+check(! mc.hasOwnProperty('onMouseDown'));
+check(! mc.hasOwnProperty('onMouseMove'));
+check(! mc.hasOwnProperty('onMouseUp'));
+check(! mc.hasOwnProperty('onPress'));
+check(! mc.hasOwnProperty('onRelease'));
+check(! mc.hasOwnProperty('onReleaseOutside'));
+check(! mc.hasOwnProperty('onRollOut'));
+check(! mc.hasOwnProperty('onRollOver'));
+check(! mc.hasOwnProperty('onSetFocus'));
+check(! mc.hasOwnProperty('onUnload'));
+#endif
 
 // Check property existance
 
@@ -328,7 +348,7 @@
 check_equals(typeof(_root.copy1), 'movieclip');
 check_equals(typeof(_root.copy1.child1), 'undefined');
 check_equals(typeof(_root.copy1.onEnterFrame), 'undefined');
-xcheck_equals(typeof(_root.copy1.onRollOver), 'undefined');
+check_equals(typeof(_root.copy1.onRollOver), 'undefined');
 check_equals(_root.copy1.getDepth(), 63);
 check_equals(_root.copy1._x, 100);
 
@@ -338,7 +358,7 @@
 check_equals(typeof(_root.copy2), 'movieclip');
 check_equals(typeof(_root.copy2.child1), 'undefined');
 check_equals(typeof(_root.copy2.onEnterFrame), 'undefined');
-xcheck_equals(typeof(_root.copy2.onRollOver), 'undefined');
+check_equals(typeof(_root.copy2.onRollOver), 'undefined');
 check_equals(_root.copy2.getDepth(), 64);
 check_equals(_root.copy2._x, 100);
 #endif // OUTPUT_VERSION = 6

Index: testsuite/actionscript.all/dejagnu_so_init.as
===================================================================
RCS file: /sources/gnash/gnash/testsuite/actionscript.all/dejagnu_so_init.as,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- testsuite/actionscript.all/dejagnu_so_init.as       9 Feb 2007 14:47:15 
-0000       1.12
+++ testsuite/actionscript.all/dejagnu_so_init.as       11 Apr 2007 14:20:21 
-0000      1.13
@@ -41,6 +41,7 @@
                clearInterval(_dejagnu_checker_interval);
 #ifdef USE_FRAMELOOP
                onEnterFrame = undefined;
+               delete onEnterFrame;
 #endif
 
                // setup some dejagnu wrappers

Index: testsuite/misc-ming.all/action_execution_order_extend_test.c
===================================================================
RCS file: 
/sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_extend_test.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -b -r1.6 -r1.7
--- testsuite/misc-ming.all/action_execution_order_extend_test.c        21 Mar 
2007 09:33:19 -0000      1.6
+++ testsuite/misc-ming.all/action_execution_order_extend_test.c        11 Apr 
2007 14:20:21 -0000      1.7
@@ -95,7 +95,7 @@
   /* Woo, the PlaceObject tag hasn't defined an 'onLoad' function.
                 maybe just pushed something to the action list???
        */
-  xcheck_equals(mo, "typeOf(_root.mc_red.onLoad)", "'undefined'");
+  check_equals(mo, "typeOf(_root.mc_red.onLoad)", "'undefined'");
   add_actions(mo, " note('as in frame2 of root'); var x1 = \"as_in_root\"; ");
   add_actions(mo, " _root.mc_red.onLoad = function () \
                    { \
@@ -157,8 +157,8 @@
   SWFMovie_nextFrame(mo); /* 4th frame */
   
   /* mc_red onload is only called IFF onClipEvent(load) is also defined! */
-  check_equals(mo, "_root.y1", "'mc_red onLoad called'");
-  xcheck_equals(mo, "_root.y1bis", "'mc_red onClipLoad called'");
+  xcheck_equals(mo, "_root.y1", "'mc_red onLoad called'");
+  check_equals(mo, "_root.y1bis", "'mc_red onClipLoad called'");
   /* actions in main timeline is executed *after* mc_red.onEnterFrame */
   check_equals(mo, "_root.y2", "'as_in_root'");
   /* actions in main timeline is executed *before* mc_red.onUnload in

Index: testsuite/misc-ming.all/displaylist_depths_test.c
===================================================================
RCS file: 
/sources/gnash/gnash/testsuite/misc-ming.all/displaylist_depths_test.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- testsuite/misc-ming.all/displaylist_depths_test.c   11 Apr 2007 08:03:32 
-0000      1.4
+++ testsuite/misc-ming.all/displaylist_depths_test.c   11 Apr 2007 14:20:21 
-0000      1.5
@@ -102,6 +102,7 @@
        //SWFDisplayItem_moveTo(it, -(width/2), -(height/2)); 
        SWFDisplayItem_setName(it, name);
        SWFDisplayItem_addAction(it, newSWFAction("this._rotation+=2;"), 
SWFACTION_ENTERFRAME);
+       SWFDisplayItem_addAction(it, newSWFAction("this._y+=5;"), 
SWFACTION_ENTERFRAME);
 
        //SWFMovie_add(mo, (SWFBlock)mc);
 }

Index: server/cxform.cpp
===================================================================
RCS file: server/cxform.cpp
diff -N server/cxform.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/cxform.cpp   11 Apr 2007 14:20:20 -0000      1.1
@@ -0,0 +1,191 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 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
+
+// 
+// $Id: cxform.cpp,v 1.1 2007/04/11 14:20:20 strk Exp $ 
+//
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cxform.h"
+#include "types.h" // for rgba type :(
+#include "stream.h" // for reading from SWF
+#include "log.h"
+
+using namespace std;
+
+namespace gnash {
+
+cxform cxform::identity;
+
+cxform::cxform()
+// Initialize to identity transform.
+{
+       m_[0][0] = 1;
+       m_[1][0] = 1;
+       m_[2][0] = 1;
+       m_[3][0] = 1;
+       m_[0][1] = 0;
+       m_[1][1] = 0;
+       m_[2][1] = 0;
+       m_[3][1] = 0;
+}
+
+void   cxform::concatenate(const cxform& c)
+// Concatenate c's transform onto ours.  When
+// transforming colors, c's transform is applied
+// first, then ours.
+{
+       m_[0][1] += m_[0][0] * c.m_[0][1];
+       m_[1][1] += m_[1][0] * c.m_[1][1];
+       m_[2][1] += m_[2][0] * c.m_[2][1];
+       m_[3][1] += m_[3][0] * c.m_[3][1];
+
+       m_[0][0] *= c.m_[0][0];
+       m_[1][0] *= c.m_[1][0];
+       m_[2][0] *= c.m_[2][0];
+       m_[3][0] *= c.m_[3][0];
+}
+
+
+rgba   cxform::transform(const rgba& in) const
+// Apply our transform to the given color; return the result.
+{
+       rgba    result(in.m_r, in.m_g, in.m_b, in.m_a);
+       
+       transform(result.m_r, result.m_g, result.m_b, result.m_a);
+
+       return result;
+}
+
+void   cxform::transform(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const
+// Faster transform() method for loops (avoids creation of rgba object)
+{
+       r = (uint8_t) fclamp(r * m_[0][0] + m_[0][1], 0, 255);
+       g = (uint8_t) fclamp(g * m_[1][0] + m_[1][1], 0, 255);
+       b = (uint8_t) fclamp(b * m_[2][0] + m_[2][1], 0, 255);
+       a = (uint8_t) fclamp(a * m_[3][0] + m_[3][1], 0, 255);
+}
+
+void   cxform::read_rgb(stream* in)
+{
+       in->align();
+
+       int     has_add = in->read_uint(1);
+       int     has_mult = in->read_uint(1);
+       int     nbits = in->read_uint(4);
+
+       if (has_mult) {
+               m_[0][0] = in->read_sint(nbits) / 255.0f;
+               m_[1][0] = in->read_sint(nbits) / 255.0f;
+               m_[2][0] = in->read_sint(nbits) / 255.0f;
+               m_[3][0] = 1;
+       }
+       else {
+               for (int i = 0; i < 4; i++) { m_[i][0] = 1; }
+       }
+       if (has_add) {
+               m_[0][1] = (float) in->read_sint(nbits);
+               m_[1][1] = (float) in->read_sint(nbits);
+               m_[2][1] = (float) in->read_sint(nbits);
+               m_[3][1] = 1;
+       }
+       else {
+               for (int i = 0; i < 4; i++) { m_[i][1] = 0; }
+       }
+}
+
+void   cxform::read_rgba(stream* in)
+{
+       in->align();
+
+       int     has_add = in->read_uint(1);
+       int     has_mult = in->read_uint(1);
+       int     nbits = in->read_uint(4);
+
+       if (has_mult) {
+               m_[0][0] = in->read_sint(nbits) / 256.0f;
+               m_[1][0] = in->read_sint(nbits) / 256.0f;
+               m_[2][0] = in->read_sint(nbits) / 256.0f;
+               m_[3][0] = in->read_sint(nbits) / 256.0f;
+       }
+       else {
+               for (int i = 0; i < 4; i++) { m_[i][0] = 1; }
+       }
+       if (has_add) {
+               m_[0][1] = (float) in->read_sint(nbits);
+               m_[1][1] = (float) in->read_sint(nbits);
+               m_[2][1] = (float) in->read_sint(nbits);
+               m_[3][1] = (float) in->read_sint(nbits);
+       }
+       else {
+               for (int i = 0; i < 4; i++) { m_[i][1] = 0; }
+       }
+}
+
+/// Force component values to be in legal range.
+void cxform::clamp()
+{
+       m_[0][0] = fclamp(m_[0][0], 0, 1);
+       m_[1][0] = fclamp(m_[1][0], 0, 1);
+       m_[2][0] = fclamp(m_[2][0], 0, 1);
+       m_[3][0] = fclamp(m_[3][0], 0, 1);
+       
+       m_[0][1] = fclamp(m_[0][1], -255.0f, 255.0f);
+       m_[1][1] = fclamp(m_[1][1], -255.0f, 255.0f);
+       m_[2][1] = fclamp(m_[2][1], -255.0f, 255.0f);
+       m_[3][1] = fclamp(m_[3][1], -255.0f, 255.0f);
+}
+
+void   cxform::print() const
+// Debug log.
+{
+       log_parse("    *         +");
+       log_parse("| %4.4f %4.4f|", m_[0][0], m_[0][1]);
+       log_parse("| %4.4f %4.4f|", m_[1][0], m_[1][1]);
+       log_parse("| %4.4f %4.4f|", m_[2][0], m_[2][1]);
+       log_parse("| %4.4f %4.4f|", m_[3][0], m_[3][1]);
+}
+
+bool   cxform::is_identity() const
+// Returns true when the cxform equals identity (no transform)
+{         
+  for (int a=0; a<4; a++)
+   for (int b=0; b<2; b++)
+    if (m_[a][b] != identity.m_[a][b])
+     return false;
+  
+  return true;
+}
+
+bool   cxform::is_invisible() const
+// Returns true when the cxform leads to alpha == 0
+{
+       return (255.0 * m_[3][0] + m_[3][1]) <= 0.0;    
+}
+
+
+}      // end namespace gnash
+
+
+// Local Variables:
+// mode: C++
+// c-basic-offset: 8 
+// tab-width: 8
+// indent-tabs-mode: t
+// End:

Index: server/cxform.h
===================================================================
RCS file: server/cxform.h
diff -N server/cxform.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/cxform.h     11 Apr 2007 14:20:20 -0000      1.1
@@ -0,0 +1,91 @@
+// 
+//   Copyright (C) 2007 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
+
+#ifndef GNASHCXFORM_H
+#define GNASHCXFORM_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tu_config.h" // for DSOEXPORT
+
+#include <iosfwd>
+
+namespace gnash {
+       class rgba;
+       class stream;
+}
+
+namespace gnash {
+
+/// Color transform type, used by render handler
+class DSOEXPORT cxform
+{
+public:
+    /// [RGBA][multiply, add]
+    float      m_[4][2];
+    
+    /// Initialize to the identity color transform (no transform)
+    cxform();
+    
+    /// Concatenate c's transform onto ours. 
+    //
+    /// When transforming colors, c's transform is applied
+    /// first, then ours.
+    ///
+    void concatenate(const cxform& c);
+    
+    /// Apply our transform to the given color; return the result.
+    rgba transform(const rgba& in) const;
+    
+    /// Faster transform() method for loops (avoids creation of rgba object)
+    void transform(uint8_t& r, uint8_t& g, uint8_t& b, uint8_t& a) const;    
+    
+    /// Read RGB from the SWF input stream.
+    void read_rgb(stream* in);
+    
+    /// Read RGBA from the SWF input stream.
+    void read_rgba(stream* in);
+    
+    /// Force component values to be in range.
+    void clamp();
+    
+    /// Debug log.
+    void print() const;
+    
+    /// Returns true when the cxform equals identity (no transform)
+    bool is_identity() const;
+    
+    /// Returns true when the cxform leads to alpha == 0
+    bool is_invisible() const;
+    
+    /// The identity color transform (no transform)
+    static cxform      identity;
+};
+
+
+
+
+}      // namespace gnash
+
+#endif // GNASHCXFORM_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: server/swf/PlaceObject2Tag.cpp
===================================================================
RCS file: server/swf/PlaceObject2Tag.cpp
diff -N server/swf/PlaceObject2Tag.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/swf/PlaceObject2Tag.cpp      11 Apr 2007 14:20:21 -0000      1.1
@@ -0,0 +1,413 @@
+// 
+//   Copyright (C) 2007 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
+
+/* $Id: PlaceObject2Tag.cpp,v 1.1 2007/04/11 14:20:21 strk Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "PlaceObject2Tag.h"
+#include "character.h"
+#include "sprite_instance.h"
+#include "swf_event.h"
+#include "log.h"
+#include "stream.h"
+
+namespace gnash {
+namespace SWF {
+namespace tag_loaders {
+
+void
+PlaceObject2Tag::readPlaceObject(stream* in)
+{
+       // Original place_object tag; very simple.
+       m_character_id = in->read_u16();
+       m_depth = in->read_u16()+character::staticDepthOffset;
+       m_matrix.read(in);
+
+       IF_VERBOSE_PARSE
+       (
+               log_parse("  char_id = %d", m_character_id);
+               log_parse("  depth = %d (%d)", m_depth, 
m_depth-character::staticDepthOffset);
+               m_matrix.print();
+       );
+
+       if (in->get_position() < in->get_tag_end_position())
+       {
+               m_color_transform.read_rgb(in);
+
+               IF_VERBOSE_PARSE
+               (
+                       log_parse("  cxform:");
+                       m_color_transform.print();
+               );
+
+       }
+}
+
+// read placeObject2 actions
+void
+PlaceObject2Tag::readPlaceActions(stream* in, int movie_version)
+{
+
+       uint16_t reserved = in->read_u16();
+       assert(reserved == 0);  // must be 0
+
+       // The logical 'or' of all the following handlers.
+       // I don't think we care about this...
+       uint32_t all_flags = (movie_version >= 6) ?
+               in->read_u32() : in->read_u16();
+       UNUSED(all_flags);
+
+       IF_VERBOSE_PARSE (
+               log_parse("  actions: flags = 0x%X", all_flags);
+       );
+
+       // Read swf_events.
+       for (;;)
+       {
+               // Read event.
+               in->align();
+
+               uint32_t flags = (movie_version >= 6) ? in->read_u32() : 
in->read_u16();
+
+               if (flags == 0)
+               {
+                       // Done with events.
+                       break;
+               }
+
+               uint32_t event_length = in->read_u32();
+               if ( in->get_tag_end_position()-in->get_position() <  
event_length )
+               {
+                       IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror("swf_event::read(), "
+                               "even_length = %u, but only %lu bytes left "
+                               "to the end of current tag."
+                               " Breaking for safety.",
+                               event_length, 
in->get_tag_end_position()-in->get_position());
+                       );
+                       break;
+               }
+
+               uint8 ch = key::INVALID;
+
+               if (flags & (1 << 17))  // has keypress event
+               {
+                       ch = in->read_u8();
+                       event_length--;
+               }
+
+               // Read the actions for event(s)
+               std::auto_ptr<action_buffer> action(new action_buffer);
+               action->read(in);
+
+               size_t readlen = action->size();
+               if (readlen > event_length)
+               {
+                       IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror("swf_event::read(), "
+                               "event_length = %d, "
+                               "but read " SIZET_FMT
+                               ". Breaking for safety.",
+                               event_length, readlen);
+                       );
+                       // or should we just continue here ?
+                       break;
+               }
+               else if ( readlen < event_length )
+               {
+                       IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror("swf_event::read(), "
+                               "event_length = %d, "
+                               "but read " SIZET_FMT 
+                               ". Skipping excessive bytes.",
+                               event_length, readlen);
+                       );
+                       in->skip_bytes(event_length - readlen);
+               }
+
+               // 13 bits reserved, 19 bits used
+               static const event_id s_code_bits[19] =
+               {
+                       event_id::LOAD,
+                       event_id::ENTER_FRAME,
+                       event_id::UNLOAD,
+                       event_id::MOUSE_MOVE,
+                       event_id::MOUSE_DOWN,
+                       event_id::MOUSE_UP,
+                       event_id::KEY_DOWN,
+                       event_id::KEY_UP,
+
+                       event_id::DATA,
+                       event_id::INITIALIZE,
+                       event_id::PRESS,
+                       event_id::RELEASE,
+                       event_id::RELEASE_OUTSIDE,
+                       event_id::ROLL_OVER,
+                       event_id::ROLL_OUT,
+                       event_id::DRAG_OVER,
+
+                       event_id::DRAG_OUT,
+                       event_id(event_id::KEY_PRESS, key::CONTROL),
+                       event_id::CONSTRUCT
+               };
+
+               // Let's see if the event flag we received is for an event that 
we know of
+               if ((pow(2.0, int( sizeof(s_code_bits) / sizeof(s_code_bits[0]) 
)) - 1) < flags)
+               {
+                       IF_VERBOSE_MALFORMED_SWF(
+                       log_swferror("swf_event::read() -- unknown / unhandled 
event type received, flags = 0x%x", flags);
+                       );
+               }
+
+               for (int i = 0, mask = 1; i < 
int(sizeof(s_code_bits)/sizeof(s_code_bits[0])); i++, mask <<= 1)
+               {
+                       if (flags & mask)
+                       {
+                               std::auto_ptr<swf_event> ev ( new 
swf_event(s_code_bits[i], action) );
+                               //log_action("---- actions for event %s", 
ev->event().get_function_name().c_str());
+
+                               // hack
+                               if (i == 17)    // has keypress event ?
+                               {
+                                       ev->event().setKeyCode(ch);
+                               }
+
+                               m_event_handlers.push_back(ev.release());
+                       }
+               }
+       }
+}
+
+// read SWF::PLACEOBJECT2
+void
+PlaceObject2Tag::readPlaceObject2(stream* in, int movie_version)
+{
+       in->align();
+
+       bool    has_actions = in->read_uint(1) ? true : false;
+       bool    has_clip_bracket = in->read_uint(1) ? true : false;
+       bool    has_name = in->read_uint(1) ? true : false;
+       bool    has_ratio = in->read_uint(1) ? true : false;
+       bool    has_cxform = in->read_uint(1) ? true : false;
+       bool    has_matrix = in->read_uint(1) ? true : false;
+       bool    has_char = in->read_uint(1) ? true : false;
+       bool    flag_move = in->read_uint(1) ? true : false;
+
+       m_depth = in->read_u16()+character::staticDepthOffset;
+
+       if (has_char) m_character_id = in->read_u16();
+
+       if (has_matrix)
+       {
+               m_has_matrix = true;
+               m_matrix.read(in);
+       }
+
+       if (has_cxform)
+       {
+               m_has_cxform = true;
+               m_color_transform.read_rgba(in);
+       }
+                       
+       if (has_ratio) m_ratio = (float)in->read_u16() / (float)65535;
+
+       if (has_name) m_name = in->read_string();
+
+       if (has_clip_bracket) m_clip_depth = 
in->read_u16()+character::staticDepthOffset; 
+
+       if (has_actions)
+       {
+               readPlaceActions(in, movie_version);
+       }
+
+
+       if (has_char == true && flag_move == true)
+       {
+               // Remove whatever's at m_depth, and put m_character there.
+               m_place_type = REPLACE;
+       }
+       else if (has_char == false && flag_move == true)
+       {
+               // Moves the object at m_depth to the new location.
+               m_place_type = MOVE;
+       }
+       else if (has_char == true && flag_move == false)
+       {
+               // Put m_character at m_depth.
+               m_place_type = PLACE;
+       }
+
+       IF_VERBOSE_PARSE (
+               log_parse("  PLACEOBJECT2: depth = %d (%d)", m_depth, 
m_depth-character::staticDepthOffset);
+               if ( has_char ) log_parse("  char id = %d", m_character_id);
+               if ( has_matrix ) 
+               {
+                       log_parse("  mat:");
+                       m_matrix.print();
+               }
+               if ( has_cxform )
+               {
+                       log_parse("  cxform:");
+                       m_color_transform.print();
+               }
+               if ( has_ratio ) log_parse("  ratio: %f", m_ratio);
+               if ( has_name ) log_parse("  name = %s", m_name ? m_name : 
"<null>");
+               if ( has_clip_bracket ) log_parse("  clip_depth = %d (%d)", 
m_clip_depth, m_clip_depth-character::staticDepthOffset);
+               log_parse(" m_place_type: %d", m_place_type);
+       );
+                       
+
+                       
+       //log_msg("place object at depth %i", m_depth);
+}
+
+void
+PlaceObject2Tag::read(stream* in, tag_type tag, int movie_version)
+{
+
+       m_tag_type = tag;
+
+       if (tag == SWF::PLACEOBJECT)
+       {
+               readPlaceObject(in);
+       }
+       else
+       {
+               readPlaceObject2(in, movie_version);
+       }
+}
+
+/// Place/move/whatever our object in the given movie.
+void
+PlaceObject2Tag::execute(sprite_instance* m)
+{
+    switch (m_place_type) {
+
+      case PLACE:
+          m->add_display_object(
+             m_character_id,
+             m_name,
+             m_event_handlers,
+             m_depth,
+             m->is_reverse_execution(),        // place_object doesn't do 
replacement when not in reverse execution
+             m_color_transform,
+             m_matrix,
+             m_ratio,
+             m_clip_depth);
+         break;
+         
+      case MOVE:
+         m->move_display_object(
+             m_depth,
+             m_has_cxform,
+             m_color_transform,
+             m_has_matrix,
+             m_matrix,
+             m_ratio,
+             m_clip_depth);
+         break;
+         
+      case REPLACE:
+         m->replace_display_object(
+             m_character_id,
+             m_name,
+             m_depth,
+             m_has_cxform,
+             m_color_transform,
+             m_has_matrix,
+             m_matrix,
+             m_ratio,
+             m_clip_depth);
+         break;
+    }
+}
+
+PlaceObject2Tag::~PlaceObject2Tag()
+{
+       delete [] m_name;
+       m_name = NULL;
+       for(size_t i=0; i<m_event_handlers.size(); ++i)
+       {
+               delete m_event_handlers[i];
+       }
+}
+
+void
+PlaceObject2Tag::execute_state_reverse(sprite_instance* m, int frame)
+{
+    switch (m_place_type) {
+      case PLACE:
+         // reverse of add is remove
+         m->remove_display_object(m_depth, m_tag_type == 4 ? m_character_id : 
-1);
+         break;
+         
+      case MOVE:
+         // reverse of move is move
+         m->move_display_object(
+             m_depth,
+             m_has_cxform,
+             m_color_transform,
+             m_has_matrix,
+             m_matrix,
+             m_ratio,
+             m_clip_depth);
+         break;
+         
+      case REPLACE:
+      {
+         // reverse of replace is to re-add the previous object.
+         execute_tag*  last_add = m->find_previous_replace_or_add_tag(frame, 
m_depth, -1);
+         if (last_add) {
+             last_add->execute_state(m);
+         } else {
+             log_error("reverse REPLACE can't find previous replace or add 
tag(%d, %d)",
+                       frame, m_depth);
+             
+         }
+         break;
+      }
+    }
+}
+
+uint32
+PlaceObject2Tag::get_depth_id_of_replace_or_add_tag() const
+{
+       uint32 depthid = 0;
+       if (m_place_type == PLACE || m_place_type == REPLACE)
+       {
+               int id = -1;
+               if (m_tag_type == SWF::PLACEOBJECT)
+               {
+                   // Old-style PlaceObject; the corresponding Remove
+                   // is specific to the character_id.
+                   id = m_character_id;
+               }
+               depthid = ((m_depth & 0x0FFFF) << 16) | (id & 0x0FFFF);
+       }
+       return depthid;
+}
+
+} // namespace gnash::SWF::tag_loaders
+} // namespace gnash::SWF
+} // namespace gnash
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:

Index: server/swf/PlaceObject2Tag.h
===================================================================
RCS file: server/swf/PlaceObject2Tag.h
diff -N server/swf/PlaceObject2Tag.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/swf/PlaceObject2Tag.h        11 Apr 2007 14:20:21 -0000      1.1
@@ -0,0 +1,139 @@
+// 
+//   Copyright (C) 2007 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
+
+// 
+//
+//
+
+/* $Id: PlaceObject2Tag.h,v 1.1 2007/04/11 14:20:21 strk Exp $ */
+
+#ifndef GNASH_SWF_PLACEOBJECT2TAG_H
+#define GNASH_SWF_PLACEOBJECT2TAG_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "execute_tag.h" // for inheritance
+#include "swf.h" // for tag_type definition
+#include "matrix.h" // for composition
+#include "cxform.h" // for composition 
+#include "tu_types.h" // for uint16_t, uint32 etc. definition 
+
+//#include <boost/ptr_container/ptr_vector.hpp>
+#include <vector>
+
+// Forward declarations
+namespace gnash {
+       class stream;
+       class sprite_instance;
+       class swf_event;
+       class movie_definition;
+}
+
+namespace gnash {
+namespace SWF {
+namespace tag_loaders {
+
+/// SWF Tag PlaceObject (4) or PlaceObject2 (9) 
+//
+///
+///
+class PlaceObject2Tag : public execute_tag
+{
+public:
+
+       typedef std::vector<swf_event*> EventHandlers;
+
+       PlaceObject2Tag(const movie_definition& def)
+               :
+               m_tag_type(0),
+               m_name(NULL),
+               m_ratio(0),
+               m_has_matrix(false),
+               m_has_cxform(false),
+               m_depth(0),
+               m_character_id(0),
+               m_clip_depth(0),
+               m_place_type(PLACE),
+               _movie_def(def)
+       {
+       }
+
+       ~PlaceObject2Tag();
+
+       /// Read SWF::PLACEOBJECT or SWF::PLACEOBJECT2
+       void read(stream* in, tag_type tag, int movie_version);
+
+       /// Place/move/whatever our object in the given movie.
+       void execute(sprite_instance* m);
+
+       /// Proxy for execute(sprite_instance*)
+       void execute_state(sprite_instance* m)
+       {
+           execute(m);
+       }
+    
+private:
+
+       int     m_tag_type;
+       char*   m_name;
+       float   m_ratio;
+       cxform  m_color_transform;
+       matrix  m_matrix;
+       bool    m_has_matrix;
+       bool    m_has_cxform;
+       int             m_depth;
+       uint16_t        m_character_id;
+       int     m_clip_depth;
+
+       enum place_type
+       {
+               PLACE,
+               MOVE,
+               REPLACE
+       } m_place_type;
+
+       const movie_definition& _movie_def;
+
+       EventHandlers m_event_handlers;
+
+       // read SWF::PLACEOBJECT 
+       void readPlaceObject(stream* in);
+
+       // read placeObject2 actions
+       void readPlaceActions(stream* in, int movie_version);
+
+       // read SWF::PLACEOBJECT2
+       void readPlaceObject2(stream* in, int movie_version);
+
+       void execute_state_reverse(sprite_instance* m, int frame);
+    
+       uint32  get_depth_id_of_replace_or_add_tag() const;
+};
+
+} // namespace gnash::SWF::tag_loaders
+} // namespace gnash::SWF
+} // namespace gnash
+
+
+#endif // GNASH_SWF_PLACEOBJECT2TAG_H
+
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: t
+// End:




reply via email to

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