gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11004: Migrated XMLNode to the new


From: Ben Limmer
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11004: Migrated XMLNode to the new filestructure and namespace
Date: Fri, 05 Jun 2009 10:32:05 -0600
User-agent: Bazaar (1.13.1)

------------------------------------------------------------
revno: 11004
committer: Ben Limmer <address@hidden>
branch nick: trunk
timestamp: Fri 2009-06-05 10:32:05 -0600
message:
  Migrated XMLNode to the new filestructure and namespace
removed:
  libcore/asobj/XMLNode_as.cpp
  libcore/asobj/XMLNode_as.h
modified:
  libcore/ClassHierarchy.cpp
  libcore/asobj/Makefile.am
  libcore/asobj/XML_as.cpp
  libcore/asobj/XML_as.h
  libcore/asobj/flash/xml/XMLNode_as.cpp
  libcore/asobj/flash/xml/XMLNode_as.h
  libcore/asobj/flash/xml/xml.am
  testsuite/as3/classes.all/xml/XMLNode_as.hx
    ------------------------------------------------------------
    revno: 10993.1.1
    committer: Ben Limmer <address@hidden>
    branch nick: branch_3
    timestamp: Thu 2009-06-04 15:48:41 -0600
    message:
      Migrated XMLNode to the new filestructure. Passes all ming tests.
    removed:
      libcore/asobj/XMLNode_as.cpp
      libcore/asobj/XMLNode_as.h
    modified:
      libcore/ClassHierarchy.cpp
      libcore/asobj/Makefile.am
      libcore/asobj/XML_as.cpp
      libcore/asobj/XML_as.h
      libcore/asobj/flash/xml/XMLNode_as.cpp
      libcore/asobj/flash/xml/XMLNode_as.h
      libcore/asobj/flash/xml/xml.am
      testsuite/as3/classes.all/xml/XMLNode_as.hx
=== modified file 'libcore/ClassHierarchy.cpp'
--- a/libcore/ClassHierarchy.cpp        2009-05-27 17:45:42 +0000
+++ b/libcore/ClassHierarchy.cpp        2009-06-04 21:48:41 +0000
@@ -64,7 +64,7 @@
 #include "builtin_function.h"
 #include "XMLSocket_as.h"
 #include "XML_as.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
 #include "asClass.h"
 #include "flash/text/TextFieldAutoSize_as.h"
 

=== modified file 'libcore/asobj/Makefile.am'
--- a/libcore/asobj/Makefile.am 2009-05-28 06:20:02 +0000
+++ b/libcore/asobj/Makefile.am 2009-06-04 21:48:41 +0000
@@ -84,7 +84,6 @@
        MovieClipLoader.cpp\
        String_as.cpp \
        XML_as.cpp \
-       XMLNode_as.cpp \
        XMLSocket_as.cpp \
        LoadableObject.cpp \
        Object.cpp
@@ -121,7 +120,6 @@
        String_as.h \
        XML_as.h \
        XMLSocket_as.h \
-       XMLNode_as.h \
        LoadableObject.h \
        Namespace_as.h \
        Object.h

=== removed file 'libcore/asobj/XMLNode_as.cpp'
--- a/libcore/asobj/XMLNode_as.cpp      2009-04-20 13:59:41 +0000
+++ b/libcore/asobj/XMLNode_as.cpp      1970-01-01 00:00:00 +0000
@@ -1,1001 +0,0 @@
-// XMLNode_as.cpp:  ActionScript "XMLNode_as" class, for Gnash.
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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
-
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "log.h"
-#include "fn_call.h"
-#include "builtin_function.h"
-#include "Array_as.h" // for childNodes
-#include "XMLNode_as.h"
-#include "XML_as.h" // escape / unescape
-#include "log.h"
-#include "Object.h" // for getObjectInterface
-#include "VM.h" // for getting the string_table.
-#include "string_table.h" 
-#include "PropertyList.h"
-
-#include <boost/bind.hpp>
-#include <string>
-#include <sstream>
-#include <vector>
-#include <algorithm>
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-namespace gnash {
-
-namespace {
-    void enumerateAttributes(const XMLNode_as& node,
-            PropertyList::SortedPropertyList&attributes);
-    bool prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
-            const std::string& prefix);
-    bool namespaceMatches(
-            const PropertyList::SortedPropertyList::value_type& val,
-            const std::string& ns);
-
-    as_value xmlnode_new(const fn_call& fn);
-    as_value xmlnode_nodeName(const fn_call& fn);
-    as_value xmlnode_nodeValue(const fn_call& fn);
-    as_value xmlnode_nodeType(const fn_call& fn);
-    as_value xmlnode_attributes(const fn_call& fn);
-    as_value xmlnode_appendChild(const fn_call& fn);
-    as_value xmlnode_cloneNode(const fn_call& fn);
-    as_value xmlnode_hasChildNodes(const fn_call& fn);
-    as_value xmlnode_insertBefore(const fn_call& fn);
-    as_value xmlnode_removeNode(const fn_call& fn);
-    as_value xmlnode_toString(const fn_call& fn);
-    as_value xmlnode_firstChild(const fn_call& fn);
-    as_value xmlnode_lastChild(const fn_call& fn);
-    as_value xmlnode_nextSibling(const fn_call& fn);
-    as_value xmlnode_previousSibling(const fn_call& fn);
-    as_value xmlnode_childNodes(const fn_call& fn);
-    as_value xmlnode_parentNode(const fn_call& fn);
-    as_value xmlnode_getPrefixForNamespace(const fn_call& fn);
-    as_value xmlnode_getNamespaceForPrefix(const fn_call& fn);
-    as_value xmlnode_namespaceURI(const fn_call& fn);
-    as_value xmlnode_localName(const fn_call& fn);
-    as_value xmlnode_prefix(const fn_call& fn);
-
-    void attachXMLNodeInterface(as_object& o);
-}
-
-
-XMLNode_as::XMLNode_as()
-    :
-    as_object(getXMLNodeInterface()),
-    _parent(0),
-    _attributes(new as_object),
-    _type(Element)
-{
-    //log_debug("%s: %p", __PRETTY_FUNCTION__, this);
-#ifdef DEBUG_MEMORY_ALLOCATION
-    log_debug(_("\tCreating XMLNode data at %p"), this);
-#endif
-}
-
-XMLNode_as::XMLNode_as(const XMLNode_as& tpl, bool deep)
-    :
-    as_object(getXMLNodeInterface()),
-    _parent(0), // _parent is never implicitly copied
-    _attributes(0),
-    _name(tpl._name),
-    _value(tpl._value),
-    _type(tpl._type)
-{
-    // only clone children if in deep mode
-    if (deep) {
-        const Children& from=tpl._children;
-        for (Children::const_iterator it=from.begin(), itEnd=from.end();
-                        it != itEnd; ++it) {
-
-            _children.push_back(new XMLNode_as(*(*it), deep));
-        }
-    }
-}
-
-XMLNode_as::~XMLNode_as()
-{
-#ifdef DEBUG_MEMORY_ALLOCATION
-    log_debug(_("\tDeleting XMLNode data %s with as_value %s at %p"),
-            this->_name, this->as_value, this);
-#endif
-}
-
-bool
-XMLNode_as::hasChildNodes()
-{
-    if (_children.size()) return true;
-    return false;
-}
-
-boost::intrusive_ptr<XMLNode_as>
-XMLNode_as::firstChild()
-{
-    if ( _children.empty() ) return NULL;
-    return _children.front();
-}
-
-boost::intrusive_ptr<XMLNode_as>
-XMLNode_as::lastChild()
-{
-       if (_children.empty()) {
-                       log_debug(_("XMLNode_as %p has no children"), 
(void*)this);
-                       return 0;
-       }
-       return _children.back();
-}
-
-
-void
-XMLNode_as::appendChild(boost::intrusive_ptr<XMLNode_as> node)
-{
-    assert (node);
-
-    boost::intrusive_ptr<XMLNode_as> oldparent = node->getParent();
-    node->setParent(this);
-    _children.push_back(node);
-    if ( oldparent ) {
-        oldparent->_children.remove(node);
-    }
-
-}
-
-boost::intrusive_ptr<XMLNode_as> 
-XMLNode_as::cloneNode(bool deep)
-{
-    boost::intrusive_ptr<XMLNode_as> newnode = new XMLNode_as(*this, deep);
-    return newnode;
-}
-
-void
-XMLNode_as::insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
-        boost::intrusive_ptr<XMLNode_as> pos)
-{
-    // find iterator for positional parameter
-    Children::iterator it = std::find(_children.begin(), _children.end(), pos);
-    if (it == _children.end()) {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("XMLNode.insertBefore(): positional parameter "
-                "is not a child of this node"));
-        );
-        return;
-    }
-
-    _children.insert(it, newnode);
-    boost::intrusive_ptr<XMLNode_as> oldparent = newnode->getParent();
-    newnode->setParent(this);
-    if (oldparent) {
-        oldparent->_children.remove(newnode);
-    }
-}
-
-/// \brief removes the specified XML object from its parent. Also
-/// deletes all descendants of the node.
-void
-XMLNode_as::removeNode()
-{
-    boost::intrusive_ptr<XMLNode_as> oldparent = getParent();
-    if (oldparent) {
-        oldparent->_children.remove(this);
-    }
-    _parent = 0;
-}
-
-XMLNode_as *
-XMLNode_as::previousSibling()
-{
-    if (!_parent) return 0;
-       if (_parent->_children.size() <= 1) return 0;
-
-    XMLNode_as *previous_node = 0;
-    for (Children::iterator itx = _parent->_children.begin();
-            itx != _parent->_children.end(); itx++) {
-
-        if (itx->get() == this) return previous_node;
-               
-        previous_node = itx->get();
-    }
-
-    return 0;
-}
-
-XMLNode_as *
-XMLNode_as::nextSibling()
-{
-
-    if (!_parent) return 0;
-
-    if (_parent->_children.size() <= 1) return 0;
-
-    XMLNode_as *previous_node = 0;
-    for (Children::reverse_iterator itx = _parent->_children.rbegin();
-            itx != _parent->_children.rend(); ++itx) {
-
-        if (itx->get() == this) return previous_node;
-               previous_node = itx->get();
-    }
-
-    return 0;
-}
-
-void
-XMLNode_as::toString(std::ostream& xmlout, bool encode) const
-{
-    stringify(*this, xmlout, encode);
-}
-
-void
-XMLNode_as::setAttribute(const std::string& name, const std::string& value)
-{
-    if (_attributes) {
-        string_table& st = _vm.getStringTable();
-        _attributes->set_member(st.find(name), value);
-    }
-}
-
-bool
-XMLNode_as::getPrefixForNamespace(const std::string& ns, std::string& prefix)
-{
-    XMLNode_as* node = this;
-    PropertyList::SortedPropertyList::const_iterator it; 
-    PropertyList::SortedPropertyList attrs;
-    
-    while (node) {
-        enumerateAttributes(*node, attrs);
-        if (!attrs.empty())
-        {
-            it = std::find_if(attrs.begin(), attrs.end(), 
-                        boost::bind(namespaceMatches, _1, ns));
-            if (it != attrs.end()) break;
-        }
-        node = node->getParent();
-    }
-
-    // None found.
-    if (!node) return false;
-
-    // Return the matching prefix
-    const std::string& name = it->first;
-
-    if (name.length() == 5) {
-        return true;
-    }
-
-    assert (name.length() >= 6);
-    
-    if (name[5] != ':') return false;
-
-    // Can also be empty.
-    prefix = name.substr(6);
-    return true;
-    
-}
-
-void
-XMLNode_as::getNamespaceForPrefix(const std::string& prefix, std::string& ns)
-{
-    XMLNode_as* node = this;
-    PropertyList::SortedPropertyList::const_iterator it; 
-    PropertyList::SortedPropertyList attrs;
-    
-    while (node) {
-
-        enumerateAttributes(*node, attrs);
-
-        if (!attrs.empty()) {
-
-            it = std::find_if(attrs.begin(), attrs.end(), 
-                        boost::bind(prefixMatches, _1, prefix));
-            if (it != attrs.end()) break;
-        }
-        node = node->getParent();
-    }
-
-    // None found; return undefined
-    if (!node) return;
-
-    // Return the matching namespace
-    ns = it->second;
-
-}
-
-
-bool
-XMLNode_as::extractPrefix(std::string& prefix)
-{
-    prefix.clear();
-    if (_name.empty()) return false;
-
-    std::string::size_type pos = _name.find(':');
-    if (pos == std::string::npos || pos == _name.size() - 1) {
-        return false;
-    }
-
-    prefix = _name.substr(0, pos);
-    return true;
-}
-
-
-void
-XMLNode_as::stringify(const XMLNode_as& xml, std::ostream& xmlout, bool 
encode) 
-{
-
-    const std::string& nodeValue = xml.nodeValue();
-    const std::string& nodeName = xml.nodeName();
-    NodeType type = xml.nodeType();
-
-#ifdef GNASH_DEBUG
-    log_debug(_("Stringifying node %p with name %s, as_value %s, %u "
-                "attributes and %u children"), (void*)&xml, nodeName,
-            nodeValue, xml._attributes.size(), xml._children.size());
-#endif
-
-    // Create the beginning of the tag
-    if (!nodeName.empty()) {
-
-        xmlout << "<" << nodeName;
-    
-        // Process the attributes, if any
-        PropertyList::SortedPropertyList attrs;
-        enumerateAttributes(xml, attrs);
-        if (!attrs.empty()) {
-
-            for (PropertyList::SortedPropertyList::iterator i = 
-                    attrs.begin(), e = attrs.end(); i != e; ++i) { 
-                XML_as::escape(i->second);
-                xmlout << " " << i->first << "=\"" << i->second << "\"";
-            }
-        }
-
-       // If the node has no content, just close the tag now
-       if ( nodeValue.empty() && xml._children.empty() ) {
-               xmlout << " />";
-            return;
-       }
-        else {
-            // Will use a closing tag later
-            xmlout << ">";
-        }
-
-    }
-
-    // Node as_value first, then children
-    if (type == Text)
-    {
-        as_object* global = xml.getVM().getGlobal();
-        assert(global);
-
-        // Insert entities.
-        std::string escaped(nodeValue);
-        XML_as::escape(escaped);
-        const std::string& val = encode ? 
-            global->callMethod(NSV::PROP_ESCAPE, escaped).to_string() :
-            escaped;
-
-           xmlout << val;
-    }
-
-    // Childs, after node as_value.
-    for (Children::const_iterator itx = xml._children.begin(); 
-            itx != xml._children.end(); ++itx) {
-
-        (*itx)->toString(xmlout, encode);
-    }
-
-    if (!nodeName.empty()) {
-           xmlout << "</" << nodeName << ">";
-    }
-}
-
-
-#ifdef GNASH_USE_GC
-void
-XMLNode_as::markReachableResources() const
-{
-       // Mark children
-    std::for_each(_children.begin(), _children.end(),
-            boost::mem_fn(&as_object::setReachable));
-
-       // Mark parent
-       if (_parent) _parent->setReachable();
-
-       // Mark attributes object
-       if (_attributes) _attributes->setReachable();
-
-       markAsObjectReachable();
-}
-#endif // GNASH_USE_GC
-
-void
-XMLNode_as::registerNative(as_object& global)
-{
-    VM& vm = global.getVM();
-    vm.registerNative(xmlnode_cloneNode, 253, 1);
-    vm.registerNative(xmlnode_removeNode, 253, 2);
-    vm.registerNative(xmlnode_insertBefore, 253, 3);
-    vm.registerNative(xmlnode_appendChild, 253, 4);
-    vm.registerNative(xmlnode_hasChildNodes, 253, 5);
-    vm.registerNative(xmlnode_toString, 253, 6);
-}
-
-as_object*
-XMLNode_as::getXMLNodeInterface()
-{
-    static boost::intrusive_ptr<as_object> o;
-    if ( o == NULL ) {
-        o = new as_object(getObjectInterface());
-        attachXMLNodeInterface(*o);
-    }
-    return o.get();
-}
-
-
-void
-XMLNode_as::init(as_object& global)
-{
-    // This is the global XMLNode_as "class"
-    static boost::intrusive_ptr<builtin_function> cl;
-
-    if ( cl == NULL )
-    {
-        cl=new builtin_function(&xmlnode_new, getXMLNodeInterface());
-    }
-
-    global.init_member("XMLNode", cl.get());
-
-}
-
-
-// XMLNode interface implementation
-
-namespace {
-
-void
-attachXMLNodeInterface(as_object& o)
-{
-    // These need to be full-featured AS functions (builtin_function)
-    
-    VM& vm = o.getVM();
-
-    const int noFlags = 0;
-    
-    // No prop flags:
-    o.init_member("cloneNode", vm.getNative(253, 1), noFlags);
-    o.init_member("removeNode", vm.getNative(253, 2), noFlags);
-    o.init_member("insertBefore", vm.getNative(253, 3), noFlags);
-    o.init_member("appendChild", vm.getNative(253, 4), noFlags);
-    o.init_member("hasChildNodes", vm.getNative(253, 5), noFlags);
-    o.init_member("toString", vm.getNative(253, 6), noFlags);
-    o.init_member("getPrefixForNamespace", new builtin_function(
-                xmlnode_getPrefixForNamespace), noFlags);
-    o.init_member("getNamespaceForPrefix", new builtin_function(
-                xmlnode_getNamespaceForPrefix), noFlags);
-
-
-    const int protectedFlags = as_prop_flags::isProtected;
-
-    // Just the protected flag:
-    o.init_property("nodeValue", &xmlnode_nodeValue, 
-            &xmlnode_nodeValue, protectedFlags);
-    o.init_property("nodeName", &xmlnode_nodeName, 
-            &xmlnode_nodeName, protectedFlags);
-
-    o.init_readonly_property("firstChild", &xmlnode_firstChild, 
protectedFlags);
-    o.init_readonly_property("lastChild", &xmlnode_lastChild, protectedFlags);
-    o.init_readonly_property("localName", &xmlnode_localName, protectedFlags);
-    o.init_readonly_property("namespaceURI", 
-            &xmlnode_namespaceURI, protectedFlags);
-    o.init_readonly_property("nextSibling", 
-            &xmlnode_nextSibling, protectedFlags);
-    o.init_readonly_property("prefix", &xmlnode_prefix, protectedFlags);
-    o.init_readonly_property("previousSibling", 
-            &xmlnode_previousSibling, protectedFlags);
-    o.init_readonly_property("nodeType", &xmlnode_nodeType, protectedFlags);
-    o.init_readonly_property("attributes", &xmlnode_attributes, 
protectedFlags);
-    o.init_readonly_property("childNodes", &xmlnode_childNodes, 
protectedFlags);
-    o.init_readonly_property("parentNode", &xmlnode_parentNode, 
protectedFlags);
-
-}
-
-
-as_value
-xmlnode_new(const fn_call& fn)
-{
-    
-    XMLNode_as *xml_obj = new XMLNode_as;
-    if ( fn.nargs > 0 )
-    {
-        xml_obj->nodeTypeSet(XMLNode_as::NodeType(fn.arg(0).to_int()));
-        if (fn.nargs > 1)
-        {
-            xml_obj->nodeValueSet(fn.arg(1).to_string());
-        }
-    }
-    
-    return as_value(xml_obj);
-}
-
-
-as_value
-xmlnode_appendChild(const fn_call& fn)
-{
-//    GNASH_REPORT_FUNCTION;
-
-       boost::intrusive_ptr<XMLNode_as> ptr = 
ensureType<XMLNode_as>(fn.this_ptr);
-
-       if ( ! fn.nargs )
-       {
-               IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror(_("XMLNode::appendChild() needs at least one 
argument"));
-               );
-               return as_value();
-       }
-
-       boost::intrusive_ptr<XMLNode_as> xml_obj = 
-        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());        
-       if ( ! xml_obj )
-       {
-               IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror(_("First argument to XMLNode::appendChild() is not "
-                "an XMLNode"));
-               );
-               return as_value();
-       }
-
-       ptr->appendChild(xml_obj);
-       return as_value(); // undefined
-
-}
-
-
-as_value
-xmlnode_cloneNode(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
-    bool deep = false;
-    if (fn.nargs > 0) deep = fn.arg(0).to_bool();
-
-    boost::intrusive_ptr<XMLNode_as> newnode = ptr->cloneNode(deep);
-    return as_value(newnode.get());
-}
-
-
-as_value
-xmlnode_insertBefore(const fn_call& fn)
-{
-       boost::intrusive_ptr<XMLNode_as> ptr = 
ensureType<XMLNode_as>(fn.this_ptr);
-
-       if ( fn.nargs < 2 )
-       {
-               IF_VERBOSE_ASCODING_ERRORS(
-               std::stringstream ss; fn.dump_args(ss);
-               log_aserror(_("XMLNode.insertBefore(%s) needs at least two "
-                "arguments"), ss.str());
-               );
-               return as_value();
-       }
-
-       boost::intrusive_ptr<XMLNode_as> newnode = 
-        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
-
-       if (!newnode) {
-               IF_VERBOSE_ASCODING_ERRORS(
-               std::stringstream ss; fn.dump_args(ss);
-               log_aserror(_("First argument to XMLNode.insertBefore(%s) is 
not "
-                "an XMLNode"), ss.str());
-               );
-               return as_value();
-       }
-
-       boost::intrusive_ptr<XMLNode_as> pos = 
-        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(1).to_object());
-
-       if (!pos) {
-               IF_VERBOSE_ASCODING_ERRORS(
-        std::stringstream ss; fn.dump_args(ss);
-               log_aserror(_("Second argument to XMLNode.insertBefore(%s) is 
not "
-                "an XMLNode"), ss.str());
-               );
-               return as_value();
-       }
-
-    ptr->insertBefore(newnode, pos);
-    return as_value();
-    
-}
-
-
-as_value
-xmlnode_getNamespaceForPrefix(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    if (!fn.nargs) {
-        return as_value();
-    }
-
-    std::string ns;
-
-    ptr->getNamespaceForPrefix(fn.arg(0).to_string(), ns);
-    if (ns.empty()) return as_value();
-    return as_value(ns);
-}
-
-
-as_value
-xmlnode_getPrefixForNamespace(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    if (!fn.nargs) {
-        return as_value();
-    }
-
-    std::string prefix;
-
-    // Return undefined if none found; otherwise the prefix string found.
-    // This can be empty if it is a standard namespace.
-    if (!ptr->getPrefixForNamespace(fn.arg(0).to_string(), prefix)) {
-        return as_value();
-    }
-    return as_value(prefix);
-}
-
-/// If the node has a prefix, return the matching namespace. Otherwise, 
-/// returns a namespaceURI set with the xmlns attribute, searching upwards
-/// through parent nodes if necessary.
-//
-/// This standard namespace can only  be set during XML parsing and cannot
-/// be changed or set using attributes.
-//
-/// Conversely, the similar getNamespaceForPrefix("") can be set and changed
-/// through attributes.
-as_value
-xmlnode_namespaceURI(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
-    // Read-only property
-    
-    const std::string& name = ptr->nodeName();
-
-    if (name.empty()) {
-        as_value null;
-        null.set_null();
-        return null;
-    }
-
-    std::string prefix;
-    if (ptr->extractPrefix(prefix)) {
-        std::string ns;
-        ptr->getNamespaceForPrefix(prefix, ns);
-        return as_value(ns);
-    }
-
-    // Search recursively for a namespace. Return an empty string
-    // if none found.
-    XMLNode_as* node = ptr.get();
-    while (node && node->getNamespaceURI().empty()) {
-        node = node->getParent();
-    }
-    if (!node) return as_value("");
-
-    return as_value(node->getNamespaceURI());
-}
-
-
-// Return the prefix part of the node name. If there is no colon, or one
-// colon at the end of the string, this is empty. Otherwise it is the part
-// up to the first colon.
-as_value
-xmlnode_prefix(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
-    // Read-only property
-    
-    if (ptr->nodeName().empty()) {
-        as_value null;
-        null.set_null();
-        return null;
-    }
-    
-    std::string prefix;
-    if (!ptr->extractPrefix(prefix)) return as_value("");
-    return as_value(prefix);
-}
-
-
-// The local part of a node name. If there is no colon or a single colon
-// at the end of the string, this is the whole string. Otherwise all of the
-// string after the first colon.
-as_value
-xmlnode_localName(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
-    // Read-only property
-    
-    if (ptr->nodeName().empty()) {
-        as_value null;
-        null.set_null();
-        return null;
-    }
-
-    const std::string& nodeName = ptr->nodeName();
-    if (nodeName.empty()) return as_value("");
-
-    std::string::size_type pos = nodeName.find(':');
-    if (pos == std::string::npos || pos == nodeName.size() - 1) {
-        return as_value(nodeName);
-    }
-
-    return as_value(nodeName.substr(pos + 1));
-}
-
-
-as_value
-xmlnode_removeNode(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    
-    ptr->removeNode();
-    return as_value();
-}
-
-
-// TODO: shouldn't overriding get_text_value() be fine ?
-as_value
-xmlnode_toString(const fn_call& fn)
-{
-    //GNASH_REPORT_FUNCTION;
-    
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    
-    std::stringstream ss;
-    ptr->toString(ss);
-
-    return as_value(ss.str());
-}
-
-
-as_value
-xmlnode_hasChildNodes(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    return as_value(ptr->hasChildNodes());
-}
-
-
-as_value
-xmlnode_nodeValue(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    as_value rv;
-    rv.set_null();
-    
-    if ( fn.nargs == 0 )
-    {
-        const std::string& val = ptr->nodeValue();
-        if ( ! val.empty() ) rv = val;
-    }
-    else
-    {
-        ptr->nodeValueSet(fn.arg(0).to_string());
-    }
-    return rv;
-}
-
-
-as_value
-xmlnode_nodeName(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    as_value rv;
-    rv.set_null();
-
-    if (!fn.nargs) {
-        const std::string& val = ptr->nodeName();
-        if ( ! val.empty() ) rv = val;
-    }
-    else
-    {
-        ptr->nodeNameSet(fn.arg(0).to_string());
-    }
-    return rv;
-}
-
-
-as_value
-xmlnode_nodeType(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    return as_value(ptr->nodeType());
-}
-
-
-as_value
-xmlnode_attributes(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-
-    as_object* attrs = ptr->getAttributes();
-    if (attrs) return as_value(attrs);
-    return as_value(); 
-}
-
-
-/// Read-only property; evaluates the specified XML object and
-/// references the first child in the parent node's child
-/// list. This property is null if the node does not have
-/// children. This property is undefined if the node is a text
-/// node. This is a read-only property and cannot be used to
-/// manipulate child nodes; use the appendChild(), insertBefore(),
-/// and removeNode() methods to manipulate child nodes. 
-///
-as_value
-xmlnode_firstChild(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    as_value rv;
-    rv.set_null();
-
-    boost::intrusive_ptr<XMLNode_as> node = ptr->firstChild();
-    if (node) {
-       rv = node.get();
-    }
-
-    return rv;
-}
-
-
-/// Read-only property; an XMLNode as_value that references the last
-/// child in the node's child list. The XML.lastChild property
-/// is null if the node does not have children. This property cannot
-/// be used to manipulate child nodes; use the appendChild(),
-/// insertBefore(), and removeNode() methods to manipulate child
-/// nodes.
-as_value
-xmlnode_lastChild(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    as_value rv;
-    rv.set_null();
-
-    boost::intrusive_ptr<XMLNode_as> node = ptr->lastChild();
-    if (node) rv = node.get();
-
-    return rv;
-}
-
-
-as_value
-xmlnode_nextSibling(const fn_call& fn)
-{
-    as_value rv;
-    rv.set_null();
-
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    XMLNode_as *node = ptr->nextSibling();
-    if (node) {
-       rv = node;
-    }
-    return rv;
-}
-
-
-as_value
-xmlnode_previousSibling(const fn_call& fn)
-{
-    as_value rv;
-    rv.set_null();
-
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    XMLNode_as *node = ptr->previousSibling();
-    if (node) {
-       rv = node;
-    }
-    return rv;
-}
-
-
-as_value
-xmlnode_parentNode(const fn_call& fn)
-{
-    as_value rv;
-    rv.set_null();
-
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    XMLNode_as *node = ptr->getParent();
-    if (node) {
-       rv = node;
-    }
-    return rv;
-}
-
-
-as_value
-xmlnode_childNodes(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    boost::intrusive_ptr<Array_as> ary = new Array_as();
-
-    typedef XMLNode_as::Children Children;
-
-    Children& child = ptr->childNodes();
-    for ( Children::const_iterator it=child.begin(), itEnd=child.end();
-                    it != itEnd; ++it )
-    {
-        boost::intrusive_ptr<XMLNode_as> node = *it;
-        ary->push(as_value(node.get()));
-    }
-
-    return as_value(ary.get());
-}
-
-
-void
-enumerateAttributes(const XMLNode_as& node,
-            PropertyList::SortedPropertyList& attrs)
-{
-    attrs.clear();
-    const as_object* obj = node.getAttributes();
-    if (obj) {
-        obj->enumerateProperties(attrs);
-    }
-
-}
-
-/// Return true if this attribute is a namespace specifier and the
-/// namespace matches.
-bool
-namespaceMatches(const PropertyList::SortedPropertyList::value_type& val,
-        const std::string& ns)
-{
-    StringNoCaseEqual noCaseCompare;
-    return (noCaseCompare(val.first.substr(0, 5), "xmlns") && 
-                noCaseCompare(val.second, ns));
-}
-
-
-bool
-prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
-        const std::string& prefix)
-{
-    const std::string& name = val.first;
-    StringNoCaseEqual noCaseCompare;
-
-    // An empty prefix searches for a standard namespace specifier.
-    // Attributes are stored with no trailing or leading whitespace,
-    // so a simple comparison should do. TODO: what about "xmlns:"?
-    if (prefix.empty()) {
-        return noCaseCompare(name, "xmlns") || noCaseCompare(name, "xmlns:");
-    }
-
-    if (!noCaseCompare(name.substr(0, 6), "xmlns:")) return false;
-
-    return noCaseCompare(prefix, name.substr(6));
-}
-
-} // anonymous namespace
-
-} // end of gnash namespace
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:

=== removed file 'libcore/asobj/XMLNode_as.h'
--- a/libcore/asobj/XMLNode_as.h        2009-03-31 09:26:54 +0000
+++ b/libcore/asobj/XMLNode_as.h        1970-01-01 00:00:00 +0000
@@ -1,254 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007, 2008, 2009 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 3 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 GNASH_ASOBJ_XML_NODE_H
-#define GNASH_ASOBJ_XML_NODE_H
-
-//#define DEBUG_MEMORY_ALLOCATION 1
-
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "action.h"
-#include "impl.h"
-#include "log.h"
-
-#include <list>
-#include <vector>
-#include <string>
-#include <sstream>
-
-namespace gnash {  
- 
-/// XMLNode  ActionScript class
-//
-/// This is also the base class for the XML actionscript class (see
-/// XML_as.cpp, XML_as.h). Because XML_as also inherits from LoadableObject,
-/// this is a virtual base class.
-//
-/// Trivial copying and assignment are forbidden
-class XMLNode_as : public virtual as_object, boost::noncopyable
-{
-public:
-
-    enum NodeType {
-        Element = 1,
-        Attribute = 2,
-        Text = 3,
-        Cdata = 4,
-        EntityRef = 5,
-        Entity = 6,
-        ProcInstr = 7,
-        Comment = 8,
-        Document = 9,
-        DocType = 10,
-        DocFragment = 11,
-        Notation = 12
-    };
-
-    XMLNode_as();
-
-    virtual ~XMLNode_as();
-
-    // Initialize the global XMLNode class
-    static void init(as_object& global);
-
-    // Used by XML_as
-    static as_object* getXMLNodeInterface();
-
-    /// Register ASnative methods
-    static void registerNative(as_object& global);
-
-    size_t length() const { return _children.size(); }
-
-    const std::string& nodeName() const { return _name; }
-
-    const std::string& nodeValue() const { return _value; }
-
-    /// Get the type of an XML Node.
-    NodeType nodeType() const { return _type; }
-
-    /// Set the type of an XML Node.
-    void nodeTypeSet(NodeType type) {
-           _type = type;
-    }
-
-    /// Set name of this node, but only if it doesn't have a name yet
-    //
-    /// TODO: check if this is the correct behaviour
-    ///
-    void nodeNameSet(const std::string& name) { _name = name; }
-
-    bool extractPrefix(std::string& prefix);
-
-    /// Set value of this node, overriding any previous value
-    void nodeValueSet(const std::string& value) { _value = value; }
-
-    /// Performs a recursive search of node attributes to find a match
-    void getNamespaceForPrefix(const std::string& prefix, std::string& ns);
-
-    /// Performs a recursive search of node attributes to find a match
-    //
-    /// @return false if no match found.
-    bool getPrefixForNamespace(const std::string& ns, std::string& prefix);
-
-    void setNamespaceURI(const std::string value) {
-        _namespaceURI = value;
-    }
-
-    const std::string& getNamespaceURI() const {
-        return _namespaceURI;
-    }
-
-    ///  Returns true if the specified node has child nodes; otherwise,
-    ///  returns false.
-    bool hasChildNodes();
-
-    boost::intrusive_ptr<XMLNode_as> firstChild();
-    boost::intrusive_ptr<XMLNode_as> lastChild();
-    
-    // Use a list for quick erasing
-    typedef std::list<boost::intrusive_ptr<XMLNode_as> > Children;
-
-    Children& childNodes() { return _children; }
-
-    XMLNode_as* previousSibling();
-    XMLNode_as* nextSibling();
-
-    /// Copy a node
-    //
-    /// Method; constructs and returns a new XML node of the same type,
-    /// name, value, and attributes as the specified XML object. If deep
-    /// is set to true, all child nodes are recursively cloned, resulting
-    /// in an exact copy of the original object's document tree. 
-    boost::intrusive_ptr<XMLNode_as> cloneNode(bool deep);
-
-    /// Append a child node the the XML object
-    //
-    /// Appends the specified node to the XML object's child
-    /// list. This method operates directly on the node referenced by the
-    /// childNode parameter; it does not append a copy of the node. If the
-    /// node to be appended already exists in another tree structure,
-    /// appending the node to the new location will remove it from its
-    /// current location. If the childNode parameter refers to a node that
-    /// already exists in another XML tree structure, the appended child
-    /// node is placed in the new tree structure after it is removed from
-    /// its existing parent node. 
-    ///
-    /// @param childNode    The XMLNode_as object to append as a child.
-    void appendChild(boost::intrusive_ptr<XMLNode_as> childNode);
-
-    /// Set the parent XMLNode_as of this node.
-    //
-    /// @param node     The new parent of this node. May be 0.
-    void setParent(XMLNode_as* node) { _parent = node; }
-
-    /// Get the parent XMLNode_as of this node. Can be 0.
-    XMLNode_as *getParent() const {
-        return _parent.get();
-    }
-
-    /// Insert a node before a node
-    //
-    /// Method; inserts a new child node into the XML object's child
-    /// list, before the beforeNode node. If the beforeNode parameter is
-    /// undefined or null, the node is added using the appendChild()
-    /// method. If beforeNode is not a child of my_xml, the insertion
-    /// fails.
-    ///
-    /// @param newnoe
-    ///     The node to insert, moving from its current tree
-    ///
-    /// @param beforeWhich
-    ///     The node before which to insert the new one.
-    ///     Must be a child of this XMLNode or the operation will fail.
-    ///
-    void insertBefore(boost::intrusive_ptr<XMLNode_as> newnode, 
-            boost::intrusive_ptr<XMLNode_as> pos);
-
-    /// Removes the specified XML object from its parent.
-    //
-    /// Also deletes all descendants of the node.
-    void removeNode();
-
-    /// Convert the XMLNode to a string
-    //
-    /// @param o        The ostream to write the string to.
-    /// @param encode   Whether to URL encode the node values. This
-    ///                 is false by default, as it is only necessary
-    ///                 for XML.sendAndLoad.
-    virtual void toString(std::ostream& str, bool encode = false) const;
-
-    /// Return the attributes object associated with this node.
-    as_object* getAttributes() { return _attributes; }
-
-    /// Return a read-only version of this node's attributes object.
-    const as_object* getAttributes() const { return _attributes; }
-
-    /// Set a named attribute to a value.
-    //
-    /// @param name     The name of the attribute to set. If already present,
-    ///                 the value is changed. If not present, the attribute is
-    ///                 added.
-    /// @param value    The value to set the named attribute to.
-    void setAttribute(const std::string& name, const std::string& value);
-
-protected:
-
-#ifdef GNASH_USE_GC
-       /// Mark XMLNode-specific reachable resources and invoke
-       /// the parent's class version (markAsObjectReachable)
-       //
-       /// XMLNode-specific reachable resources are:
-       ///     - The child elements (_children)
-       ///     - The parent elements (_parent)
-       ///
-       virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
-    Children _children;
-
-private:
-
-    /// A non-trivial copy-constructor for cloning nodes.
-    XMLNode_as(const XMLNode_as &node, bool deep);
-
-    boost::intrusive_ptr<XMLNode_as> _parent;
-
-    as_object* _attributes;
-
-    std::string _name;
-
-    std::string _value;
-
-    NodeType _type;
-
-    std::string _namespaceURI;
-
-    static void stringify(const XMLNode_as& xml, std::ostream& xmlout,
-            bool encode);
-
-};
-
-} // gnash namespace
-
-
-#endif 
-
-
-// Local Variables:
-// mode: C++
-// indent-tabs-mode: t
-// End:

=== modified file 'libcore/asobj/XML_as.cpp'
--- a/libcore/asobj/XML_as.cpp  2009-05-14 16:02:12 +0000
+++ b/libcore/asobj/XML_as.cpp  2009-06-04 21:48:41 +0000
@@ -28,7 +28,7 @@
 #include "fn_call.h"
 
 #include "LoadableObject.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
 #include "XML_as.h"
 #include "builtin_function.h"
 #include "VM.h"

=== modified file 'libcore/asobj/XML_as.h'
--- a/libcore/asobj/XML_as.h    2009-01-22 20:10:39 +0000
+++ b/libcore/asobj/XML_as.h    2009-06-04 21:48:41 +0000
@@ -19,7 +19,7 @@
 #define GNASH_ASOBJ_XML_H
 
 #include "LoadableObject.h"
-#include "XMLNode_as.h"
+#include "xml/XMLNode_as.h"
 #include "log.h"
 #include "dsodefs.h"
 #include "StringPredicates.h"

=== modified file 'libcore/asobj/flash/xml/XMLNode_as.cpp'
--- a/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-05-28 17:11:03 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-06-04 21:48:41 +0000
@@ -22,154 +22,976 @@
 #endif
 
 #include "xml/XMLNode_as.h"
+//FIXME: direct this to the proper flash namespace
+#include "XML_as.h"
+#include "Array_as.h"
+#include "Object.h"
+#include "VM.h"
 #include "log.h"
 #include "fn_call.h"
 #include "smart_ptr.h" // for boost intrusive_ptr
 #include "builtin_function.h" // need builtin_function
 #include "GnashException.h" // for ActionException
+#include "string_table.h"
+#include "PropertyList.h"
+
+#include <boost/bind.hpp>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
 
 namespace gnash {
 
-// Forward declarations
+// Function Prototypes
 namespace {
+    void enumerateAttributes(const XMLNode_as& node, 
PropertyList::SortedPropertyList&attributes);
+    bool prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+            const std::string& prefix);
+    bool namespaceMatches(
+            const PropertyList::SortedPropertyList::value_type& val,
+            const std::string& ns);    
+       //FIXME: these should be changed to the proper return type & arguments
+    as_value xmlnode_new(const fn_call& fn);
+    as_value xmlnode_nodeName(const fn_call& fn);
+    as_value xmlnode_nodeValue(const fn_call& fn);
+    as_value xmlnode_nodeType(const fn_call& fn);
+    as_value xmlnode_attributes(const fn_call& fn);
+    as_value xmlnode_appendChild(const fn_call& fn);
     as_value xmlnode_cloneNode(const fn_call& fn);
+    as_value xmlnode_lastChild(const fn_call& fn);
+    as_value xmlnode_firstChild(const fn_call& fn);
+    as_value xmlnode_nextSibling(const fn_call& fn);
+    as_value xmlnode_childNodes(const fn_call& fn);
+    as_value xmlnode_previousSibling(const fn_call& fn);
+    as_value xmlnode_parentNode(const fn_call& fn);
     as_value xmlnode_getNamespaceForPrefix(const fn_call& fn);
     as_value xmlnode_getPrefixForNamespace(const fn_call& fn);
+    as_value xmlnode_namespaceURI(const fn_call& fn);
     as_value xmlnode_hasChildNodes(const fn_call& fn);
     as_value xmlnode_insertBefore(const fn_call& fn);
     as_value xmlnode_removeNode(const fn_call& fn);
     as_value xmlnode_toString(const fn_call& fn);
+    as_value xmlnode_localName(const fn_call& fn);
+    as_value xmlnode_prefix(const fn_call& fn);
     as_value xmlnode_ctor(const fn_call& fn);
     void attachXMLNodeInterface(as_object& o);
     void attachXMLNodeStaticInterface(as_object& o);
     as_object* getXMLNodeInterface();
-
-}
-
-class XMLNode_as : public as_object
-{
-
-public:
-
-    XMLNode_as()
-        :
-        as_object(getXMLNodeInterface())
-    {}
-};
-
-// extern (used by Global.cpp)
-void xmlnode_class_init(as_object& global)
-{
-    static boost::intrusive_ptr<builtin_function> cl;
-
-    if (!cl) {
-        cl = new builtin_function(&xmlnode_ctor, getXMLNodeInterface());
-        attachXMLNodeStaticInterface(*cl);
-    }
-
-    // Register _global.XMLNode
-    global.init_member("XMLNode", cl.get());
-}
-
-namespace {
-
-void
-attachXMLNodeInterface(as_object& o)
-{
-    o.init_member("cloneNode", new builtin_function(xmlnode_cloneNode));
-    o.init_member("getNamespaceForPrefix", new 
builtin_function(xmlnode_getNamespaceForPrefix));
-    o.init_member("getPrefixForNamespace", new 
builtin_function(xmlnode_getPrefixForNamespace));
-    o.init_member("hasChildNodes", new 
builtin_function(xmlnode_hasChildNodes));
-    o.init_member("insertBefore", new builtin_function(xmlnode_insertBefore));
-    o.init_member("removeNode", new builtin_function(xmlnode_removeNode));
-    o.init_member("toString", new builtin_function(xmlnode_toString));
-}
-
-void
-attachXMLNodeStaticInterface(as_object& o)
-{
-
+}
+
+//should be declared in header file
+//class XMLNode_as : public as_object
+//{
+//public:
+//    XMLNode_as();
+//    ~XMLNode_as();
+//};
+
+//ADDED//
+XMLNode_as::XMLNode_as()
+       : as_object(getXMLNodeInterface()),
+         _parent(0),
+         _attributes(new as_object),
+         _type(Element)
+{
+    //log_debug("%s: %p", __PRETTY_FUNCTION__, this);
+#ifdef DEBUG_MEMORY_ALLOCATION
+    log_debug(_("\tCreating XMLNode data at %p"), this);
+#endif
+}
+
+XMLNode_as::XMLNode_as(const XMLNode_as& tpl, bool deep)
+    :
+    as_object(getXMLNodeInterface()),
+    _parent(0), // _parent is never implicitly copied
+    _attributes(0),
+    _name(tpl._name),
+    _value(tpl._value),
+    _type(tpl._type)
+{
+    // only clone children if in deep mode
+    if (deep) {
+        const Children& from=tpl._children;
+        for (Children::const_iterator it=from.begin(), itEnd=from.end();
+                        it != itEnd; ++it) {
+
+            _children.push_back(new XMLNode_as(*(*it), deep));
+        }
+    }
+}
+
+XMLNode_as::~XMLNode_as()
+{
+#ifdef DEBUG_MEMORY_ALLOCATION
+    log_debug(_("\tDeleting XMLNode data %s with as_value %s at %p"),
+            this->_name, this->as_value, this);
+#endif
+}
+       
+bool
+XMLNode_as::hasChildNodes()
+{
+    if (_children.size()) return true;
+    return false;
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::firstChild()
+{
+    if ( _children.empty() ) return NULL;
+    return _children.front();
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::cloneNode(bool deep)
+{
+    boost::intrusive_ptr<XMLNode_as> newnode = new XMLNode_as(*this, deep);
+    return newnode;
+}
+
+boost::intrusive_ptr<XMLNode_as>
+XMLNode_as::lastChild()
+{
+       if (_children.empty()) {
+                       log_debug(_("XMLNode_as %p has no children"), 
(void*)this);
+                       return 0;
+       }
+       return _children.back();
+}
+
+void
+XMLNode_as::appendChild(boost::intrusive_ptr<XMLNode_as> node)
+{
+    assert (node);
+
+    boost::intrusive_ptr<XMLNode_as> oldparent = node->getParent();
+    node->setParent(this);
+    _children.push_back(node);
+    if ( oldparent ) {
+        oldparent->_children.remove(node);
+    }
+
+}
+
+void
+XMLNode_as::insertBefore(boost::intrusive_ptr<XMLNode_as> newnode,
+        boost::intrusive_ptr<XMLNode_as> pos)
+{
+       // find iterator for positional parameter
+    Children::iterator it = std::find(_children.begin(), _children.end(), pos);
+    if (it == _children.end()) {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("XMLNode.insertBefore(): positional parameter "
+                "is not a child of this node"));
+        );
+        return;
+    }
+
+    _children.insert(it, newnode);
+    boost::intrusive_ptr<XMLNode_as> oldparent = newnode->getParent();
+    newnode->setParent(this);
+    if (oldparent) {
+        oldparent->_children.remove(newnode);
+    }
+}
+
+// \brief removes the specified XML object from its parent. Also
+// deletes all descendants of the node.
+void
+XMLNode_as::removeNode()
+{
+    boost::intrusive_ptr<XMLNode_as> oldparent = getParent();
+    if (oldparent) {
+        oldparent->_children.remove(this);
+    }
+    _parent = 0;
+}
+
+XMLNode_as *
+XMLNode_as::previousSibling()
+{
+    if (!_parent) return 0;
+       if (_parent->_children.size() <= 1) return 0;
+
+    XMLNode_as *previous_node = 0;
+    for (Children::iterator itx = _parent->_children.begin();
+            itx != _parent->_children.end(); itx++) {
+
+        if (itx->get() == this) return previous_node;
+               
+        previous_node = itx->get();
+    }
+
+    return 0;
+}
+
+XMLNode_as *
+XMLNode_as::nextSibling()
+{
+
+    if (!_parent) return 0;
+
+    if (_parent->_children.size() <= 1) return 0;
+
+    XMLNode_as *previous_node = 0;
+    for (Children::reverse_iterator itx = _parent->_children.rbegin();
+            itx != _parent->_children.rend(); ++itx) {
+
+        if (itx->get() == this) return previous_node;
+               previous_node = itx->get();
+    }
+
+    return 0;
+}
+
+void
+XMLNode_as::toString(std::ostream& xmlout, bool encode) const
+{
+    stringify(*this, xmlout, encode);
+}
+
+void
+XMLNode_as::setAttribute(const std::string& name, const std::string& value)
+{
+    if (_attributes) {
+        string_table& st = _vm.getStringTable();
+        _attributes->set_member(st.find(name), value);
+    }
+}
+
+bool
+XMLNode_as::getPrefixForNamespace(const std::string& ns, std::string& prefix)
+{
+    XMLNode_as* node = this;
+    PropertyList::SortedPropertyList::const_iterator it; 
+    PropertyList::SortedPropertyList attrs;
+    
+    while (node) {
+        enumerateAttributes(*node, attrs);
+        if (!attrs.empty())
+        {
+            it = std::find_if(attrs.begin(), attrs.end(), 
+                        boost::bind(namespaceMatches, _1, ns));
+            if (it != attrs.end()) break;
+        }
+        node = node->getParent();
+    }
+
+    // None found.
+    if (!node) return false;
+
+    // Return the matching prefix
+    const std::string& name = it->first;
+
+    if (name.length() == 5) {
+        return true;
+    }
+
+    assert (name.length() >= 6);
+    
+    if (name[5] != ':') return false;
+
+    // Can also be empty.
+    prefix = name.substr(6);
+    return true;    
+}
+
+void
+XMLNode_as::getNamespaceForPrefix(const std::string& prefix, std::string& ns)
+{
+    XMLNode_as* node = this;
+    PropertyList::SortedPropertyList::const_iterator it; 
+    PropertyList::SortedPropertyList attrs;
+    
+    while (node) {
+
+        enumerateAttributes(*node, attrs);
+
+        if (!attrs.empty()) {
+
+            it = std::find_if(attrs.begin(), attrs.end(), 
+                        boost::bind(prefixMatches, _1, prefix));
+            if (it != attrs.end()) break;
+        }
+        node = node->getParent();
+    }
+
+    // None found; return undefined
+    if (!node) return;
+
+    // Return the matching namespace
+    ns = it->second;
+
+}
+
+bool
+XMLNode_as::extractPrefix(std::string& prefix)
+{
+    prefix.clear();
+    if (_name.empty()) return false;
+
+    std::string::size_type pos = _name.find(':');
+    if (pos == std::string::npos || pos == _name.size() - 1) {
+        return false;
+    }
+
+    prefix = _name.substr(0, pos);
+    return true;
+}
+
+void
+XMLNode_as::stringify(const XMLNode_as& xml, std::ostream& xmlout, bool 
encode) 
+{
+
+    const std::string& nodeValue = xml.nodeValue();
+    const std::string& nodeName = xml.nodeName();
+    NodeType type = xml.nodeType();
+
+#ifdef GNASH_DEBUG
+    log_debug(_("Stringifying node %p with name %s, as_value %s, %u "
+                "attributes and %u children"), (void*)&xml, nodeName,
+            nodeValue, xml._attributes.size(), xml._children.size());
+#endif
+
+    // Create the beginning of the tag
+    if (!nodeName.empty()) {
+
+        xmlout << "<" << nodeName;
+    
+        // Process the attributes, if any
+        PropertyList::SortedPropertyList attrs;
+        enumerateAttributes(xml, attrs);
+        if (!attrs.empty()) {
+
+            for (PropertyList::SortedPropertyList::iterator i = 
+                    attrs.begin(), e = attrs.end(); i != e; ++i) { 
+                XML_as::escape(i->second);
+                xmlout << " " << i->first << "=\"" << i->second << "\"";
+            }
+        }
+
+       // If the node has no content, just close the tag now
+       if ( nodeValue.empty() && xml._children.empty() ) {
+               xmlout << " />";
+            return;
+       }
+        else {
+            // Will use a closing tag later
+            xmlout << ">";
+        }
+
+    }
+
+    // Node as_value first, then children
+    if (type == Text)
+    {
+        as_object* global = xml.getVM().getGlobal();
+        assert(global);
+
+        // Insert entities.
+        std::string escaped(nodeValue);
+        XML_as::escape(escaped);
+        const std::string& val = encode ? 
+            global->callMethod(NSV::PROP_ESCAPE, escaped).to_string() :
+            escaped;
+
+           xmlout << val;
+    }
+
+    // Childs, after node as_value.
+    for (Children::const_iterator itx = xml._children.begin(); 
+            itx != xml._children.end(); ++itx) {
+
+        (*itx)->toString(xmlout, encode);
+    }
+
+    if (!nodeName.empty()) {
+           xmlout << "</" << nodeName << ">";
+    }
+}
+
+#ifdef GNASH_USE_GC
+void
+XMLNode_as::markReachableResources() const
+{
+       // Mark children
+    std::for_each(_children.begin(), _children.end(),
+            boost::mem_fn(&as_object::setReachable));
+
+       // Mark parent
+       if (_parent) _parent->setReachable();
+
+       // Mark attributes object
+       if (_attributes) _attributes->setReachable();
+
+       markAsObjectReachable();
+}
+#endif // GNASH_USE_GC
+
+void
+XMLNode_as::registerNative(as_object& global)
+{
+    VM& vm = global.getVM();
+    vm.registerNative(xmlnode_cloneNode, 253, 1);
+    vm.registerNative(xmlnode_removeNode, 253, 2);
+    vm.registerNative(xmlnode_insertBefore, 253, 3);
+    vm.registerNative(xmlnode_appendChild, 253, 4);
+    vm.registerNative(xmlnode_hasChildNodes, 253, 5);
+    vm.registerNative(xmlnode_toString, 253, 6);
 }
 
 as_object*
-getXMLNodeInterface()
+XMLNode_as::getXMLNodeInterface()
 {
     static boost::intrusive_ptr<as_object> o;
-    if ( ! o ) {
-        o = new as_object();
+    if ( o == NULL ) {
+        o = new as_object(getObjectInterface());
         attachXMLNodeInterface(*o);
     }
     return o.get();
 }
 
+void
+XMLNode_as::init(as_object& global)
+{
+    // This is the global XMLNode_as "class"
+    static boost::intrusive_ptr<builtin_function> cl;
+
+    if ( cl == NULL )
+    {
+        cl=new builtin_function(&xmlnode_new, getXMLNodeInterface());
+    }
+
+    global.init_member("XMLNode", cl.get());
+
+}
+
+namespace {
+
+void
+attachXMLNodeInterface(as_object& o)
+{
+    // These need to be full-featured AS functions (builtin_function)
+    
+    VM& vm = o.getVM();
+
+    const int noFlags = 0;
+    
+    // No prop flags:
+    o.init_member("cloneNode", vm.getNative(253, 1), noFlags);
+    o.init_member("removeNode", vm.getNative(253, 2), noFlags);
+    o.init_member("insertBefore", vm.getNative(253, 3), noFlags);
+    o.init_member("appendChild", vm.getNative(253, 4), noFlags);
+    o.init_member("hasChildNodes", vm.getNative(253, 5), noFlags);
+    o.init_member("toString", vm.getNative(253, 6), noFlags);
+    o.init_member("getPrefixForNamespace", new builtin_function(
+                xmlnode_getPrefixForNamespace), noFlags);
+    o.init_member("getNamespaceForPrefix", new builtin_function(
+                xmlnode_getNamespaceForPrefix), noFlags);
+
+
+    const int protectedFlags = as_prop_flags::isProtected;
+
+    // Just the protected flag:
+    o.init_property("nodeValue", &xmlnode_nodeValue, 
+            &xmlnode_nodeValue, protectedFlags);
+    o.init_property("nodeName", &xmlnode_nodeName, 
+            &xmlnode_nodeName, protectedFlags);
+
+    o.init_readonly_property("firstChild", &xmlnode_firstChild, 
protectedFlags);
+    o.init_readonly_property("lastChild", &xmlnode_lastChild, protectedFlags);
+    o.init_readonly_property("localName", &xmlnode_localName, protectedFlags);
+    o.init_readonly_property("namespaceURI", 
+            &xmlnode_namespaceURI, protectedFlags);
+    o.init_readonly_property("nextSibling", 
+            &xmlnode_nextSibling, protectedFlags);
+    o.init_readonly_property("prefix", &xmlnode_prefix, protectedFlags);
+    o.init_readonly_property("previousSibling", 
+            &xmlnode_previousSibling, protectedFlags);
+    o.init_readonly_property("nodeType", &xmlnode_nodeType, protectedFlags);
+    o.init_readonly_property("attributes", &xmlnode_attributes, 
protectedFlags);
+    o.init_readonly_property("childNodes", &xmlnode_childNodes, 
protectedFlags);
+    o.init_readonly_property("parentNode", &xmlnode_parentNode, 
protectedFlags);
+
+}
+
+
+as_value
+xmlnode_new(const fn_call& fn)
+{
+    
+    XMLNode_as *xml_obj = new XMLNode_as;
+    if ( fn.nargs > 0 )
+    {
+        xml_obj->nodeTypeSet(XMLNode_as::NodeType(fn.arg(0).to_int()));
+        if (fn.nargs > 1)
+        {
+            xml_obj->nodeValueSet(fn.arg(1).to_string());
+        }
+    }
+    
+    return as_value(xml_obj);
+}
+
+
+as_value
+xmlnode_appendChild(const fn_call& fn)
+{
+//    GNASH_REPORT_FUNCTION;
+
+       boost::intrusive_ptr<XMLNode_as> ptr = 
ensureType<XMLNode_as>(fn.this_ptr);
+
+       if ( ! fn.nargs )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+               log_aserror(_("XMLNode::appendChild() needs at least one 
argument"));
+               );
+               return as_value();
+       }
+
+       boost::intrusive_ptr<XMLNode_as> xml_obj = 
+        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());        
+       if ( ! xml_obj )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+               log_aserror(_("First argument to XMLNode::appendChild() is not "
+                "an XMLNode"));
+               );
+               return as_value();
+       }
+
+       ptr->appendChild(xml_obj);
+       return as_value(); // undefined
+
+}
+
 as_value
 xmlnode_cloneNode(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+    bool deep = false;
+    if (fn.nargs > 0) deep = fn.arg(0).to_bool();
+
+    boost::intrusive_ptr<XMLNode_as> newnode = ptr->cloneNode(deep);
+    return as_value(newnode.get());
+}
+
+
+as_value
+xmlnode_insertBefore(const fn_call& fn)
+{
+       boost::intrusive_ptr<XMLNode_as> ptr = 
ensureType<XMLNode_as>(fn.this_ptr);
+
+       if ( fn.nargs < 2 )
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+               std::stringstream ss; fn.dump_args(ss);
+               log_aserror(_("XMLNode.insertBefore(%s) needs at least two "
+                "arguments"), ss.str());
+               );
+               return as_value();
+       }
+
+       boost::intrusive_ptr<XMLNode_as> newnode = 
+        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object());
+
+       if (!newnode) {
+               IF_VERBOSE_ASCODING_ERRORS(
+               std::stringstream ss; fn.dump_args(ss);
+               log_aserror(_("First argument to XMLNode.insertBefore(%s) is 
not "
+                "an XMLNode"), ss.str());
+               );
+               return as_value();
+       }
+
+       boost::intrusive_ptr<XMLNode_as> pos = 
+        boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(1).to_object());
+
+       if (!pos) {
+               IF_VERBOSE_ASCODING_ERRORS(
+        std::stringstream ss; fn.dump_args(ss);
+               log_aserror(_("Second argument to XMLNode.insertBefore(%s) is 
not "
+                "an XMLNode"), ss.str());
+               );
+               return as_value();
+       }
+
+    ptr->insertBefore(newnode, pos);
     return as_value();
+    
 }
 
+
 as_value
 xmlnode_getNamespaceForPrefix(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    if (!fn.nargs) {
+        return as_value();
+    }
+
+    std::string ns;
+
+    ptr->getNamespaceForPrefix(fn.arg(0).to_string(), ns);
+    if (ns.empty()) return as_value();
+    return as_value(ns);
 }
 
+
 as_value
 xmlnode_getPrefixForNamespace(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-
-as_value
-xmlnode_hasChildNodes(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
-
-as_value
-xmlnode_insertBefore(const fn_call& fn)
-{
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
-}
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    if (!fn.nargs) {
+        return as_value();
+    }
+
+    std::string prefix;
+
+    // Return undefined if none found; otherwise the prefix string found.
+    // This can be empty if it is a standard namespace.
+    if (!ptr->getPrefixForNamespace(fn.arg(0).to_string(), prefix)) {
+        return as_value();
+    }
+    return as_value(prefix);
+}
+
+/// If the node has a prefix, return the matching namespace. Otherwise, 
+/// returns a namespaceURI set with the xmlns attribute, searching upwards
+/// through parent nodes if necessary.
+//
+/// This standard namespace can only  be set during XML parsing and cannot
+/// be changed or set using attributes.
+//
+/// Conversely, the similar getNamespaceForPrefix("") can be set and changed
+/// through attributes.
+as_value
+xmlnode_namespaceURI(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+    // Read-only property
+    
+    const std::string& name = ptr->nodeName();
+
+    if (name.empty()) {
+        as_value null;
+        null.set_null();
+        return null;
+    }
+
+    std::string prefix;
+    if (ptr->extractPrefix(prefix)) {
+        std::string ns;
+        ptr->getNamespaceForPrefix(prefix, ns);
+        return as_value(ns);
+    }
+
+    // Search recursively for a namespace. Return an empty string
+    // if none found.
+    XMLNode_as* node = ptr.get();
+    while (node && node->getNamespaceURI().empty()) {
+        node = node->getParent();
+    }
+    if (!node) return as_value("");
+
+    return as_value(node->getNamespaceURI());
+}
+
+
+// Return the prefix part of the node name. If there is no colon, or one
+// colon at the end of the string, this is empty. Otherwise it is the part
+// up to the first colon.
+as_value
+xmlnode_prefix(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+    // Read-only property
+    
+    if (ptr->nodeName().empty()) {
+        as_value null;
+        null.set_null();
+        return null;
+    }
+    
+    std::string prefix;
+    if (!ptr->extractPrefix(prefix)) return as_value("");
+    return as_value(prefix);
+}
+
+
+// The local part of a node name. If there is no colon or a single colon
+// at the end of the string, this is the whole string. Otherwise all of the
+// string after the first colon.
+as_value
+xmlnode_localName(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+    // Read-only property
+    
+    if (ptr->nodeName().empty()) {
+        as_value null;
+        null.set_null();
+        return null;
+    }
+
+    const std::string& nodeName = ptr->nodeName();
+    if (nodeName.empty()) return as_value("");
+
+    std::string::size_type pos = nodeName.find(':');
+    if (pos == std::string::npos || pos == nodeName.size() - 1) {
+        return as_value(nodeName);
+    }
+
+    return as_value(nodeName.substr(pos + 1));
+}
+
 
 as_value
 xmlnode_removeNode(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    
+    ptr->removeNode();
     return as_value();
 }
 
+
+// TODO: shouldn't overriding get_text_value() be fine ?
 as_value
 xmlnode_toString(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLNode_as> ptr =
-        ensureType<XMLNode_as>(fn.this_ptr);
-    UNUSED(ptr);
-    log_unimpl (__FUNCTION__);
-    return as_value();
+    //GNASH_REPORT_FUNCTION;
+    
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    
+    std::stringstream ss;
+    ptr->toString(ss);
+
+    return as_value(ss.str());
+}
+
+
+as_value
+xmlnode_hasChildNodes(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    return as_value(ptr->hasChildNodes());
+}
+
+
+as_value
+xmlnode_nodeValue(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    as_value rv;
+    rv.set_null();
+    
+    if ( fn.nargs == 0 )
+    {
+        const std::string& val = ptr->nodeValue();
+        if ( ! val.empty() ) rv = val;
+    }
+    else
+    {
+        ptr->nodeValueSet(fn.arg(0).to_string());
+    }
+    return rv;
+}
+
+
+as_value
+xmlnode_nodeName(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    as_value rv;
+    rv.set_null();
+
+    if (!fn.nargs) {
+        const std::string& val = ptr->nodeName();
+        if ( ! val.empty() ) rv = val;
+    }
+    else
+    {
+        ptr->nodeNameSet(fn.arg(0).to_string());
+    }
+    return rv;
+}
+
+
+as_value
+xmlnode_nodeType(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    return as_value(ptr->nodeType());
+}
+
+
+as_value
+xmlnode_attributes(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+
+    as_object* attrs = ptr->getAttributes();
+    if (attrs) return as_value(attrs);
+    return as_value(); 
+}
+
+
+/// Read-only property; evaluates the specified XML object and
+/// references the first child in the parent node's child
+/// list. This property is null if the node does not have
+/// children. This property is undefined if the node is a text
+/// node. This is a read-only property and cannot be used to
+/// manipulate child nodes; use the appendChild(), insertBefore(),
+/// and removeNode() methods to manipulate child nodes. 
+///
+as_value
+xmlnode_firstChild(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    as_value rv;
+    rv.set_null();
+
+    boost::intrusive_ptr<XMLNode_as> node = ptr->firstChild();
+    if (node) {
+       rv = node.get();
+    }
+
+    return rv;
+}
+
+
+/// Read-only property; an XMLNode as_value that references the last
+/// child in the node's child list. The XML.lastChild property
+/// is null if the node does not have children. This property cannot
+/// be used to manipulate child nodes; use the appendChild(),
+/// insertBefore(), and removeNode() methods to manipulate child
+/// nodes.
+as_value
+xmlnode_lastChild(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    as_value rv;
+    rv.set_null();
+
+    boost::intrusive_ptr<XMLNode_as> node = ptr->lastChild();
+    if (node) rv = node.get();
+
+    return rv;
+}
+
+
+as_value
+xmlnode_nextSibling(const fn_call& fn)
+{
+    as_value rv;
+    rv.set_null();
+
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    XMLNode_as *node = ptr->nextSibling();
+    if (node) {
+       rv = node;
+    }
+    return rv;
+}
+
+
+as_value
+xmlnode_previousSibling(const fn_call& fn)
+{
+    as_value rv;
+    rv.set_null();
+
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    XMLNode_as *node = ptr->previousSibling();
+    if (node) {
+       rv = node;
+    }
+    return rv;
+}
+
+
+as_value
+xmlnode_parentNode(const fn_call& fn)
+{
+    as_value rv;
+    rv.set_null();
+
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    XMLNode_as *node = ptr->getParent();
+    if (node) {
+       rv = node;
+    }
+    return rv;
+}
+
+
+as_value
+xmlnode_childNodes(const fn_call& fn)
+{
+    boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
+    boost::intrusive_ptr<Array_as> ary = new Array_as();
+
+    typedef XMLNode_as::Children Children;
+
+    Children& child = ptr->childNodes();
+    for ( Children::const_iterator it=child.begin(), itEnd=child.end();
+                    it != itEnd; ++it )
+    {
+        boost::intrusive_ptr<XMLNode_as> node = *it;
+        ary->push(as_value(node.get()));
+    }
+
+    return as_value(ary.get());
+}
+
+
+void
+enumerateAttributes(const XMLNode_as& node,
+            PropertyList::SortedPropertyList& attrs)
+{
+    attrs.clear();
+    const as_object* obj = node.getAttributes();
+    if (obj) {
+        obj->enumerateProperties(attrs);
+    }
+
+}
+
+/// Return true if this attribute is a namespace specifier and the
+/// namespace matches.
+bool
+namespaceMatches(const PropertyList::SortedPropertyList::value_type& val,
+        const std::string& ns)
+{
+    StringNoCaseEqual noCaseCompare;
+    return (noCaseCompare(val.first.substr(0, 5), "xmlns") && 
+                noCaseCompare(val.second, ns));
+}
+
+
+bool
+prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+        const std::string& prefix)
+{
+    const std::string& name = val.first;
+    StringNoCaseEqual noCaseCompare;
+
+    // An empty prefix searches for a standard namespace specifier.
+    // Attributes are stored with no trailing or leading whitespace,
+    // so a simple comparison should do. TODO: what about "xmlns:"?
+    if (prefix.empty()) {
+        return noCaseCompare(name, "xmlns") || noCaseCompare(name, "xmlns:");
+    }
+
+    if (!noCaseCompare(name.substr(0, 6), "xmlns:")) return false;
+
+    return noCaseCompare(prefix, name.substr(6));
 }
 
 as_value
@@ -179,10 +1001,10 @@
 
     return as_value(obj.get()); // will keep alive
 }
-
+       
+////END ADD
 } // anonymous namespace 
 } // gnash namespace
-
 // local Variables:
 // mode: C++
 // indent-tabs-mode: t

=== modified file 'libcore/asobj/flash/xml/XMLNode_as.h'
--- a/libcore/asobj/flash/xml/XMLNode_as.h      2009-05-28 17:29:17 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.h      2009-06-04 21:48:41 +0000
@@ -24,14 +24,220 @@
 #include "gnashconfig.h"
 #endif
 
+#include "smart_ptr.h" // GNASH_USE_GC
+#include "action.h"
+#include "impl.h"
+#include "log.h"
+
+#include <list>
+#include <vector>
+#include <string>
+#include <sstream>
 
 namespace gnash {
-
-// Forward declarations
-class as_object;
-
-/// Initialize the global XMLNode class
-void xmlnode_class_init(as_object& global);
+class XMLNode_as : public virtual as_object, boost::noncopyable
+{
+public:
+
+    enum NodeType {
+        Element = 1,
+        Attribute = 2,
+        Text = 3,
+        Cdata = 4,
+        EntityRef = 5,
+        Entity = 6,
+        ProcInstr = 7,
+        Comment = 8,
+        Document = 9,
+        DocType = 10,
+        DocFragment = 11,
+        Notation = 12
+    };
+
+    XMLNode_as();
+
+    virtual ~XMLNode_as();
+
+    // Initialize the global XMLNode class
+    static void init(as_object& global);
+
+    // Used by XML_as
+    static as_object* getXMLNodeInterface();
+
+    /// Register ASnative methods
+    static void registerNative(as_object& global);
+
+    size_t length() const { return _children.size(); }
+
+    const std::string& nodeName() const { return _name; }
+
+    const std::string& nodeValue() const { return _value; }
+
+    /// Get the type of an XML Node.
+    NodeType nodeType() const { return _type; }
+
+    /// Set the type of an XML Node.
+    void nodeTypeSet(NodeType type) {
+           _type = type;
+    }
+
+    /// Set name of this node, but only if it doesn't have a name yet
+    //
+    /// TODO: check if this is the correct behaviour
+    ///
+    void nodeNameSet(const std::string& name) { _name = name; }
+
+    bool extractPrefix(std::string& prefix);
+
+    /// Set value of this node, overriding any previous value
+    void nodeValueSet(const std::string& value) { _value = value; }
+
+    /// Performs a recursive search of node attributes to find a match
+    void getNamespaceForPrefix(const std::string& prefix, std::string& ns);
+
+    /// Performs a recursive search of node attributes to find a match
+    //
+    /// @return false if no match found.
+    bool getPrefixForNamespace(const std::string& ns, std::string& prefix);
+
+    void setNamespaceURI(const std::string value) {
+        _namespaceURI = value;
+    }
+
+    const std::string& getNamespaceURI() const {
+        return _namespaceURI;
+    }
+
+    ///  Returns true if the specified node has child nodes; otherwise,
+    ///  returns false.
+    bool hasChildNodes();
+
+    boost::intrusive_ptr<XMLNode_as> firstChild();
+    boost::intrusive_ptr<XMLNode_as> lastChild();
+    
+    // Use a list for quick erasing
+    typedef std::list<boost::intrusive_ptr<XMLNode_as> > Children;
+
+    Children& childNodes() { return _children; }
+
+    XMLNode_as* previousSibling();
+    XMLNode_as* nextSibling();
+
+    /// Copy a node
+    //  UNIMPLEMENTED
+    /// Method; constructs and returns a new XML node of the same type,
+    /// name, value, and attributes as the specified XML object. If deep
+    /// is set to true, all child nodes are recursively cloned, resulting
+    /// in an exact copy of the original object's document tree. 
+    boost::intrusive_ptr<XMLNode_as> cloneNode(bool deep);
+
+    /// Append a child node the the XML object
+    //
+    /// Appends the specified node to the XML object's child
+    /// list. This method operates directly on the node referenced by the
+    /// childNode parameter; it does not append a copy of the node. If the
+    /// node to be appended already exists in another tree structure,
+    /// appending the node to the new location will remove it from its
+    /// current location. If the childNode parameter refers to a node that
+    /// already exists in another XML tree structure, the appended child
+    /// node is placed in the new tree structure after it is removed from
+    /// its existing parent node. 
+    ///
+    /// @param childNode    The XMLNode_as object to append as a child.
+
+       void appendChild(boost::intrusive_ptr<XMLNode_as> childNode);
+
+    /// Set the parent XMLNode_as of this node.
+    //
+    /// @param node     The new parent of this node. May be 0.
+    void setParent(XMLNode_as* node) { _parent = node; }
+
+    /// Get the parent XMLNode_as of this node. Can be 0.
+    XMLNode_as *getParent() const {
+        return _parent.get();
+    }
+
+    /// Insert a node before a node
+    //
+    /// Method; inserts a new child node into the XML object's child
+    /// list, before the beforeNode node. If the beforeNode parameter is
+    /// undefined or null, the node is added using the appendChild()
+    /// method. If beforeNode is not a child of my_xml, the insertion
+    /// fails.
+    ///
+    /// @param newnoe
+    ///     The node to insert, moving from its current tree
+    ///
+    /// @param beforeWhich
+    ///     The node before which to insert the new one.
+    ///     Must be a child of this XMLNode or the operation will fail.
+    ///
+    void insertBefore(boost::intrusive_ptr<XMLNode_as> newnode, 
+            boost::intrusive_ptr<XMLNode_as> pos);
+
+    /// Removes the specified XML object from its parent.
+    //
+    /// Also deletes all descendants of the node.
+    void removeNode();
+
+    /// Convert the XMLNode to a string
+    //
+    /// @param o        The ostream to write the string to.
+    /// @param encode   Whether to URL encode the node values. This
+    ///                 is false by default, as it is only necessary
+    ///                 for XML.sendAndLoad.
+    virtual void toString(std::ostream& str, bool encode = false) const;
+
+    /// Return the attributes object associated with this node.
+    as_object* getAttributes() { return _attributes; }
+
+    /// Return a read-only version of this node's attributes object.
+    const as_object* getAttributes() const { return _attributes; }
+
+    /// Set a named attribute to a value.
+    //
+    /// @param name     The name of the attribute to set. If already present,
+    ///                 the value is changed. If not present, the attribute is
+    ///                 added.
+    /// @param value    The value to set the named attribute to.
+    void setAttribute(const std::string& name, const std::string& value);
+
+protected:
+
+#ifdef GNASH_USE_GC
+       /// Mark XMLNode-specific reachable resources and invoke
+       /// the parent's class version (markAsObjectReachable)
+       //
+       /// XMLNode-specific reachable resources are:
+       ///     - The child elements (_children)
+       ///     - The parent elements (_parent)
+       ///
+       virtual void markReachableResources() const;
+#endif // GNASH_USE_GC
+
+    Children _children;
+
+private:
+
+    /// A non-trivial copy-constructor for cloning nodes.
+    XMLNode_as(const XMLNode_as &node, bool deep);
+
+    boost::intrusive_ptr<XMLNode_as> _parent;
+
+    as_object* _attributes;
+
+    std::string _name;
+
+    std::string _value;
+
+    NodeType _type;
+
+    std::string _namespaceURI;
+
+    static void stringify(const XMLNode_as& xml, std::ostream& xmlout,
+            bool encode);
+
+};
 
 } // gnash namespace
 
@@ -43,3 +249,4 @@
 // indent-tabs-mode: t
 // End:
 
+

=== modified file 'libcore/asobj/flash/xml/xml.am'
--- a/libcore/asobj/flash/xml/xml.am    2009-06-01 19:12:38 +0000
+++ b/libcore/asobj/flash/xml/xml.am    2009-06-05 16:32:05 +0000
@@ -31,7 +31,7 @@
 endif
 
 if BUILD_XMLNODE_AS3
-# XML_SOURCES += flash/xml/XMLNode_as.cpp
+XML_SOURCES += flash/xml/XMLNode_as.cpp
 XML_HEADERS += flash/xml/XMLNode_as.h
 endif
 
@@ -50,12 +50,17 @@
        echo "#define GNASH_ASOBJ_FLASH_XML_H 1" >> $${header}; \
        echo "#include \"sharedlib.h\"" >> $${header}; \
        echo "static gnash::SharedLib::initentry *as3xmlclasses[] = {" >> 
$${header}; \
-       sources="`echo $(XML_SOURCES) | cut -d ' ' -f 2-`"; \
-       for i in $${sources}; do \
-         item=`basename $$i | sed -e 's:\_as.cpp::'`; \
+       oldway=`grep -l "_class_init" $(srcdir)/flash/xml/*_as.h`; \
+       newway=`grep -l "void init" $(srcdir)/flash/xml/*_as.h`; \
+       for i in $${oldway}; do \
+         item=`basename $$i | sed -e 's:\_as.h::'`; \
          lowname="`echo $${item} | tr '[A-Z]' '[a-z]'`"; \
          echo "        gnash::$${lowname}_class_init,"  >> $${header}; \
        done; \
+       for i in $${newway}; do \
+         item=`basename $$i | sed -e 's:\_as.h::'`; \
+         echo "        gnash::$${item}_as::init,"  >> $${header}; \
+       done; \
        echo '  0' >> $${header}; \
        echo '};' >> $${header}; \
        echo "#endif // end of GNASH_ASOBJ_FLASH_XML_H" >> $${header};

=== modified file 'testsuite/as3/classes.all/xml/XMLNode_as.hx'
--- a/testsuite/as3/classes.all/xml/XMLNode_as.hx       2009-06-03 19:42:00 
+0000
+++ b/testsuite/as3/classes.all/xml/XMLNode_as.hx       2009-06-04 21:48:41 
+0000
@@ -28,6 +28,7 @@
 import flash.xml.XMLNodeType;
 import flash.display.MovieClip;
 #else
+import flash.XMLNode;
 import flash.MovieClip;
 #end
 import flash.Lib;
@@ -40,7 +41,7 @@
 // Class must be named with the _as suffix, as that's the same name as the 
file.
 class XMLNode_as {
     static function main() {
-       #if flash9
+       #if flash
         var x1:XMLNode = new XMLNode(XMLNodeType.ELEMENT_NODE, null);  
        
         // Make sure we actually get a valid class        


reply via email to

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