/**
 * This file is part of the DOM implementation for KDE.
 *
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Peter Kelly (pmk@post.com)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 * Copyright (C) 2004 Apple Computer, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

//#define EVENT_DEBUG
#include "dom/dom_exception.h"
#include "dom/dom_node.h"
#include "xml/dom_textimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/dom_elementimpl.h"

#include "khtml_part.h"
#include "khtmlview.h"

#include "html/htmlparser.h"

#include "rendering/render_canvas.h"
#include "css/css_valueimpl.h"
#include "css/cssproperties.h"
#include "css/cssvalues.h"
#include "css/css_stylesheetimpl.h"
#include "css/cssstyleselector.h"
#include "xml/dom_xmlimpl.h"

#include <qtextstream.h>
#include <kdebug.h>

using namespace DOM;
using namespace khtml;

AttributeImpl* AttributeImpl::clone(bool) const
{
    return new AttributeImpl(m_name, m_value);
}

void AttributeImpl::allocateImpl(ElementImpl* e) {
    m_impl = new AttrImpl(e, e->docPtr(), this);
}

AttrImpl::AttrImpl(ElementImpl* element, DocumentPtr* docPtr, AttributeImpl* a)
    : ContainerNodeImpl(docPtr),
      m_element(element),
      m_attribute(a)
{
    assert(!m_attribute->m_impl);
    m_attribute->m_impl = this;
    m_attribute->ref();
    m_specified = true;
}

AttrImpl::~AttrImpl()
{
    assert(m_attribute->m_impl == this);
    m_attribute->m_impl = 0;
    m_attribute->deref();
}

DOMString AttrImpl::nodeName() const
{
    if (m_element && m_element->getDocument()->isHTMLDocument())
        return name().upper(); // Have to uppercase attributes when returned in HTML (and not XML).
    return name();
}

unsigned short AttrImpl::nodeType() const
{
    return Node::ATTRIBUTE_NODE;
}

const AtomicString& AttrImpl::prefix() const
{
    return m_attribute->prefix();
}

void AttrImpl::setPrefix(const AtomicString &_prefix, int &exceptioncode )
{
    checkSetPrefix(_prefix, exceptioncode);
    if (exceptioncode)
        return;

    m_attribute->setPrefix(_prefix);
}

DOMString AttrImpl::nodeValue() const
{
    return value();
}

void AttrImpl::setValue( const DOMString &v, int &exceptioncode )
{
    exceptioncode = 0;

    // ### according to the DOM docs, we should create an unparsed Text child
    // node here
    // do not interprete entities in the string, its literal!

    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return;
    }

    // ### what to do on 0 ?
    if (v.isNull()) {
        exceptioncode = DOMException::DOMSTRING_SIZE_ERR;
        return;
    }

    m_attribute->setValue(v.implementation());
    if (m_element)
        m_element->attributeChanged(m_attribute);
}

void AttrImpl::setNodeValue( const DOMString &v, int &exceptioncode )
{
    exceptioncode = 0;
    // NO_MODIFICATION_ALLOWED_ERR: taken care of by setValue()
    setValue(v, exceptioncode);
}

NodeImpl *AttrImpl::cloneNode ( bool /*deep*/)
{
    return new AttrImpl(0, docPtr(), m_attribute->clone());
}

// DOM Section 1.1.1
bool AttrImpl::childAllowed( NodeImpl *newChild )
{
    if(!newChild)
        return false;

    return childTypeAllowed(newChild->nodeType());
}

bool AttrImpl::childTypeAllowed( unsigned short type )
{
    switch (type) {
        case Node::TEXT_NODE:
        case Node::ENTITY_REFERENCE_NODE:
            return true;
            break;
        default:
            return false;
    }
}

DOMString AttrImpl::toString() const
{
    DOMString result;

    result += nodeName();

    // FIXME: substitute entities for any instances of " or ' --
    // maybe easier to just use text value and ignore existing
    // entity refs?

    if (firstChild() != NULL) {
	result += "=\"";

	for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
	    result += child->toString();
	}
	
	result += "\"";
    }

    return result;
}

DOMString AttrImpl::name() const
{
    return m_attribute->name().toString();
}

DOMString AttrImpl::value() const
{
    return m_attribute->value();
}

// -------------------------------------------------------------------------

ElementImpl::ElementImpl(const QualifiedName& qName, DocumentPtr *doc)
    : ContainerNodeImpl(doc), m_tagName(qName)
{
    namedAttrMap = 0;
}

ElementImpl::~ElementImpl()
{
    if (namedAttrMap) {
        namedAttrMap->detachFromElement();
        namedAttrMap->deref();
    }
}

NodeImpl *ElementImpl::cloneNode(bool deep)
{
    int exceptionCode = 0;
    ElementImpl *clone = getDocument()->createElementNS(namespaceURI(), nodeName(), exceptionCode);
    assert(!exceptionCode);
    
    // clone attributes
    if (namedAttrMap)
        *clone->attributes() = *namedAttrMap;

    if (deep)
        cloneChildNodes(clone);

    return clone;
}

void ElementImpl::removeAttribute(const QualifiedName& name, int &exceptioncode)
{
    if (namedAttrMap) {
        namedAttrMap->removeNamedItem(name, exceptioncode);
        if (exceptioncode == DOMException::NOT_FOUND_ERR) {
            exceptioncode = 0;
        }
    }
}

void ElementImpl::setAttribute(const QualifiedName& name, const DOMString &value)
{
    int exceptioncode = 0;
    setAttribute(name, value.implementation(), exceptioncode);
}

// Virtual function, defined in base class.
NamedAttrMapImpl *ElementImpl::attributes() const
{
    return attributes(false);
}

NamedAttrMapImpl* ElementImpl::attributes(bool readonly) const
{
    updateStyleAttributeIfNeeded();
    if (!readonly && !namedAttrMap)
        createAttributeMap();
    return namedAttrMap;
}

unsigned short ElementImpl::nodeType() const
{
    return Node::ELEMENT_NODE;
}

const AtomicStringList* ElementImpl::getClassList() const
{
    return 0;
}

const AtomicString& ElementImpl::getIDAttribute() const
{
    return namedAttrMap ? namedAttrMap->id() : nullAtom;
}

const AtomicString& ElementImpl::getAttribute(const QualifiedName& name) const
{
    if (name == HTMLAttributes::style())
        updateStyleAttributeIfNeeded();

    if (namedAttrMap) {
        AttributeImpl* a = namedAttrMap->getAttributeItem(name);
        if (a) return a->value();
    }
    return nullAtom;
}

void ElementImpl::scrollIntoView(bool alignToTop) 
{
    KHTMLView *v = getDocument()->view();
    QRect bounds = this->getRect();
    int x, y, xe, ye;
    x = bounds.left();
    y = bounds.top();
    xe = bounds.right();
    ye = bounds.bottom();
    
    if (alignToTop) 
        v->setContentsPos(x, y);
    else
        v->ensureVisible(x, y, xe-x, ye-y);
}

const AtomicString& ElementImpl::getAttributeNS(const DOMString &namespaceURI,
                                                const DOMString &localName) const
{
    DOMString ln(localName);
    if (getDocument()->isHTMLDocument())
        ln = localName.lower();
    QualifiedName name(nullAtom, ln.implementation(), namespaceURI.implementation());
    return getAttribute(name);
}

void ElementImpl::setAttribute(const QualifiedName& name, DOMStringImpl* value, int &exceptioncode )
{
    if (inDocument())
        getDocument()->incDOMTreeVersion();

    // allocate attributemap if necessary
    AttributeImpl* old = attributes(false)->getAttributeItem(name);

    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    if (namedAttrMap->isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return;
    }

    if (name == HTMLAttributes::idAttr())
	updateId(old ? old->value() : nullAtom, value);
    
    if (old && !value)
        namedAttrMap->removeAttribute(name);
    else if (!old && value)
        namedAttrMap->addAttribute(createAttribute(name, value));
    else if (old && value) {
        old->setValue(value);
        attributeChanged(old);
    }
}

AttributeImpl* ElementImpl::createAttribute(const QualifiedName& name, DOMStringImpl* value)
{
    return new AttributeImpl(name, value);
}

void ElementImpl::setAttributeMap( NamedAttrMapImpl* list )
{
    if (inDocument())
        getDocument()->incDOMTreeVersion();

    // If setting the whole map changes the id attribute, we need to
    // call updateId.

    AttributeImpl *oldId = namedAttrMap ? namedAttrMap->getAttributeItem(HTMLAttributes::idAttr()) : 0;
    AttributeImpl *newId = list ? list->getAttributeItem(HTMLAttributes::idAttr()) : 0;

    if (oldId || newId) {
	updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    }

    if(namedAttrMap)
        namedAttrMap->deref();

    namedAttrMap = list;

    if(namedAttrMap) {
        namedAttrMap->ref();
        namedAttrMap->element = this;
        unsigned int len = namedAttrMap->length();
        for(unsigned int i = 0; i < len; i++)
            attributeChanged(namedAttrMap->attrs[i]);
    }
}

bool ElementImpl::hasAttributes() const
{
    updateStyleAttributeIfNeeded();
    return namedAttrMap && namedAttrMap->length() > 0;
}

DOMString ElementImpl::nodeName() const
{
    return m_tagName.toString();
}

void ElementImpl::setPrefix(const AtomicString &_prefix, int &exceptioncode)
{
    checkSetPrefix(_prefix, exceptioncode);
    if (exceptioncode)
        return;

    m_tagName.setPrefix(_prefix);
}

void ElementImpl::createAttributeMap() const
{
    namedAttrMap = new NamedAttrMapImpl(const_cast<ElementImpl*>(this));
    namedAttrMap->ref();
}

bool ElementImpl::isURLAttribute(AttributeImpl *attr) const
{
    return false;
}

RenderStyle *ElementImpl::styleForRenderer(RenderObject *parentRenderer)
{
    return getDocument()->styleSelector()->styleForElement(this);
}

RenderObject *ElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
{
    if (getDocument()->documentElement() == this && style->display() == NONE) {
        // Ignore display: none on root elements.  Force a display of block in that case.
        RenderBlock* result = new (arena) RenderBlock(this);
        if (result) result->setStyle(style);
        return result;
    }
    return RenderObject::createObject(this, style);
}


void ElementImpl::insertedIntoDocument()
{
    // need to do superclass processing first so inDocument() is true
    // by the time we reach updateId
    ContainerNodeImpl::insertedIntoDocument();

    if (hasID()) {
        NamedAttrMapImpl *attrs = attributes(true);
        if (attrs) {
            AttributeImpl *idAttr = attrs->getAttributeItem(HTMLAttributes::idAttr());
            if (idAttr && !idAttr->isNull()) {
                updateId(nullAtom, idAttr->value());
            }
        }
    }
}

void ElementImpl::removedFromDocument()
{
    if (hasID()) {
        NamedAttrMapImpl *attrs = attributes(true);
        if (attrs) {
            AttributeImpl *idAttr = attrs->getAttributeItem(HTMLAttributes::idAttr());
            if (idAttr && !idAttr->isNull()) {
                updateId(idAttr->value(), nullAtom);
            }
        }
    }

    ContainerNodeImpl::removedFromDocument();
}

void ElementImpl::attach()
{
#if SPEED_DEBUG < 1
    createRendererIfNeeded();
#endif
    ContainerNodeImpl::attach();
}

void ElementImpl::recalcStyle( StyleChange change )
{
    // ### should go away and be done in renderobject
    RenderStyle* _style = m_render ? m_render->style() : 0;
    bool hasParentRenderer = parent() ? parent()->renderer() : false;
    
#if 0
    const char* debug;
    switch(change) {
    case NoChange: debug = "NoChange";
        break;
    case NoInherit: debug= "NoInherit";
        break;
    case Inherit: debug = "Inherit";
        break;
    case Force: debug = "Force";
        break;
    }
    qDebug("recalcStyle(%d: %s)[%p: %s]", change, debug, this, tagName().string().latin1());
#endif
    if ( hasParentRenderer && (change >= Inherit || changed()) ) {
        RenderStyle *newStyle = getDocument()->styleSelector()->styleForElement(this);
        newStyle->ref();
        StyleChange ch = diff( _style, newStyle );
        if (ch == Detach) {
            if (attached()) detach();
            // ### Suboptimal. Style gets calculated again.
            attach();
            // attach recalulates the style for all children. No need to do it twice.
            setChanged( false );
            setHasChangedChild( false );
            newStyle->deref(getDocument()->renderArena());
            return;
        }
        else if (ch != NoChange) {
            if( m_render && newStyle ) {
                //qDebug("--> setting style on render element bgcolor=%s", newStyle->backgroundColor().name().latin1());
                m_render->setStyle(newStyle);
            }
        }
        else if (changed() && m_render && newStyle && (getDocument()->usesSiblingRules() || getDocument()->usesDescendantRules())) {
            // Although no change occurred, we use the new style so that the cousin style sharing code won't get
            // fooled into believing this style is the same.  This is only necessary if the document actually uses
            // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
            // descendants.
            m_render->setStyleInternal(newStyle);
        }

        newStyle->deref(getDocument()->renderArena());

        if ( change != Force) {
            if (getDocument()->usesDescendantRules())
                change = Force;
            else
                change = ch;
        }
    }

    NodeImpl *n;
    for (n = _first; n; n = n->nextSibling()) {
	//qDebug("    (%p) calling recalcStyle on child %s/%p, change=%d", this, n, n->isElementNode() ? ((ElementImpl *)n)->tagName().string().latin1() : n->isTextNode() ? "text" : "unknown", change );
        if ( change >= Inherit || n->isTextNode() ||
             n->hasChangedChild() || n->changed() )
            n->recalcStyle( change );
    }

    setChanged( false );
    setHasChangedChild( false );
}

bool ElementImpl::childTypeAllowed( unsigned short type )
{
    switch (type) {
        case Node::ELEMENT_NODE:
        case Node::TEXT_NODE:
        case Node::COMMENT_NODE:
        case Node::PROCESSING_INSTRUCTION_NODE:
        case Node::CDATA_SECTION_NODE:
        case Node::ENTITY_REFERENCE_NODE:
            return true;
            break;
        default:
            return false;
    }
}

void ElementImpl::dispatchAttrRemovalEvent(AttributeImpl *attr)
{
    if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
	return;
    //int exceptioncode = 0;
//     dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
// 		  attr->value(), getDocument()->attrName(attr->id()),MutationEvent::REMOVAL),exceptioncode);
}

void ElementImpl::dispatchAttrAdditionEvent(AttributeImpl *attr)
{
    if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
	return;
   // int exceptioncode = 0;
//     dispatchEvent(new MutationEventImpl(EventImpl::DOMATTRMODIFIED_EVENT,true,false,attr,attr->value(),
//                                         attr->value(),getDocument()->attrName(attr->id()),MutationEvent::ADDITION),exceptioncode);
}

DOMString ElementImpl::openTagStartToString() const
{
    DOMString result = DOMString("<") + nodeName();

    NamedAttrMapImpl *attrMap = attributes(true);

    if (attrMap) {
	unsigned long numAttrs = attrMap->length();
	for (unsigned long i = 0; i < numAttrs; i++) {
	    result += " ";

	    AttributeImpl *attribute = attrMap->attributeItem(i);
	    result += attribute->name().toString();
            if (!attribute->value().isNull()) {
                result += "=\"";
                // FIXME: substitute entities for any instances of " or '
                result += attribute->value();
                result += "\"";
            }
	}
    }

    return result;
}

DOMString ElementImpl::toString() const
{
    DOMString result = openTagStartToString();

    if (hasChildNodes()) {
	result += ">";

	for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
	    result += child->toString();
	}

	result += "</";
	result += nodeName();
	result += ">";
    } else {
	result += " />";
    }

    return result;
}

void ElementImpl::updateId(const AtomicString& oldId, const AtomicString& newId)
{
    if (!inDocument())
	return;

    if (oldId == newId)
	return;

    DocumentImpl* doc = getDocument();
    if (!oldId.isEmpty())
	doc->removeElementById(oldId, this);
    if (!newId.isEmpty())
	doc->addElementById(newId, this);
}

#ifndef NDEBUG
void ElementImpl::dump(QTextStream *stream, QString ind) const
{
    updateStyleAttributeIfNeeded();
    if (namedAttrMap) {
        for (uint i = 0; i < namedAttrMap->length(); i++) {
            AttributeImpl *attr = namedAttrMap->attributeItem(i);
            *stream << " " << attr->name().localName().string().ascii()
                    << "=\"" << attr->value().string().ascii() << "\"";
        }
    }

    ContainerNodeImpl::dump(stream,ind);
}
#endif

#ifndef NDEBUG
void ElementImpl::formatForDebugger(char *buffer, unsigned length) const
{
    DOMString result;
    DOMString s;
    
    s = nodeName();
    if (s.length() > 0) {
        result += s;
    }
          
    s = getAttribute(HTMLAttributes::idAttr());
    if (s.length() > 0) {
        if (result.length() > 0)
            result += "; ";
        result += "id=";
        result += s;
    }
          
    s = getAttribute(HTMLAttributes::classAttr());
    if (s.length() > 0) {
        if (result.length() > 0)
            result += "; ";
        result += "class=";
        result += s;
    }
          
    strncpy(buffer, result.string().latin1(), length - 1);
}
#endif

SharedPtr<AttrImpl> ElementImpl::setAttributeNode(AttrImpl *attr, int &exception)
{
    return static_pointer_cast<AttrImpl>(attributes(false)->setNamedItem(attr, exception));
}

SharedPtr<AttrImpl> ElementImpl::removeAttributeNode(AttrImpl *attr, int &exception)
{
    if (!attr || attr->ownerElement() != this) {
        exception = DOMException::NOT_FOUND_ERR;
        return SharedPtr<AttrImpl>();
    }
    if (getDocument() != attr->getDocument()) {
        exception = DOMException::WRONG_DOCUMENT_ERR;
        return SharedPtr<AttrImpl>();
    }

    NamedAttrMapImpl *attrs = attributes(true);
    if (!attrs)
        return SharedPtr<AttrImpl>();

    return static_pointer_cast<AttrImpl>(attrs->removeNamedItem(attr->m_attribute->name(), exception));
}

void ElementImpl::setAttributeNS(const DOMString &namespaceURI, const DOMString &qualifiedName, const DOMString &value, int &exception)
{
    DOMString localName = qualifiedName;
    DOMString prefix;
    int colonpos;
    if ((colonpos = qualifiedName.find(':')) >= 0) {
        prefix = qualifiedName.copy();
        localName = qualifiedName.copy();
        prefix.truncate(colonpos);
        localName.remove(0, colonpos+1);
    }

    if (!DocumentImpl::isValidName(localName)) {
        exception = DOMException::INVALID_CHARACTER_ERR;
        return;
    }

    if (getDocument()->isHTMLDocument())
        localName = localName.lower();
        
    setAttribute(QualifiedName(prefix.implementation(), localName.implementation(),
                               namespaceURI.implementation()), value.implementation(), exception);
}

void ElementImpl::removeAttributeNS(const DOMString &namespaceURI, const DOMString &localName, int &exception)
{
    DOMString ln(localName);
    if (getDocument() && getDocument()->isHTMLDocument())
        ln = localName.lower();
    removeAttribute(QualifiedName(nullAtom, ln.implementation(), namespaceURI.implementation()), exception);
}

AttrImpl *ElementImpl::getAttributeNodeNS(const DOMString &namespaceURI, const DOMString &localName)
{
    NamedAttrMapImpl *attrs = attributes(true);
    if (!attrs)
        return 0;
    DOMString ln(localName);
    if (getDocument() && getDocument()->isHTMLDocument())
        ln = localName.lower();
    return attrs->getNamedItem(QualifiedName(nullAtom, localName.implementation(), namespaceURI.implementation()));
}

bool ElementImpl::hasAttributeNS(const DOMString &namespaceURI, const DOMString &localName) const
{
    NamedAttrMapImpl *attrs = attributes(true);
    if (!attrs)
        return false;
    DOMString ln(localName);
    if (getDocument() && getDocument()->isHTMLDocument())
        ln = localName.lower();
    return attrs->getAttributeItem(QualifiedName(nullAtom, localName.implementation(), 
                                                 namespaceURI.implementation()));
}

CSSStyleDeclarationImpl *ElementImpl::style()
{
    return 0;
}

// -------------------------------------------------------------------------

/*
XMLElementImpl::XMLElementImpl(DocumentPtr *doc, DOMStringImpl *_qualifiedName, DOMStringImpl *_namespaceURI)
    : ElementImpl(doc)
{
    int colonpos = -1;
    for (uint i = 0; i < _qualifiedName->l; ++i)
        if (_qualifiedName->s[i] == ':') {
            colonpos = i;
            break;
        }

    if (colonpos >= 0) {
        // we have a prefix
        DOMStringImpl* localName = _qualifiedName->copy();
        localName->ref();
        localName->remove(0,colonpos+1);
        m_id = doc->document()->tagId(_namespaceURI, localName, false);
        localName->deref();
        
        // FIXME: This is a temporary situation for stage one of the QualifiedName patch.  This is also a really stupid way to
        // have to handle the prefix.  Way too much copying.  We should make sure the XML tokenizer has done the split
        // already into prefix and localName.
        DOMStringImpl* prefix = _qualifiedName->copy();
        prefix->ref();
        prefix->truncate(colonpos);
        m_tagName = QualifiedName(prefix, nullAtom, nullAtom);
        prefix->deref();
    }
    else
        // no prefix
        m_id = doc->document()->tagId(_namespaceURI, _qualifiedName, false);
}

*/

// -------------------------------------------------------------------------

NamedAttrMapImpl::NamedAttrMapImpl(ElementImpl *e)
    : element(e)
    , attrs(0)
    , len(0)
{
}

NamedAttrMapImpl::~NamedAttrMapImpl()
{
    NamedAttrMapImpl::clearAttributes(); // virtual method, so qualify just to be explicit
}

bool NamedAttrMapImpl::isMappedAttributeMap() const
{
    return false;
}

AttrImpl *NamedAttrMapImpl::getNamedItem(const QualifiedName& name) const
{
    AttributeImpl* a = getAttributeItem(name);
    if (!a) return 0;

    if (!a->attrImpl())
        a->allocateImpl(element);

    return a->attrImpl();
}

SharedPtr<NodeImpl> NamedAttrMapImpl::setNamedItem ( NodeImpl* arg, int &exceptioncode )
{
    if (!element) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return SharedPtr<NodeImpl>();
    }

    // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly.
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return SharedPtr<NodeImpl>();
    }

    // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map.
    if (arg->getDocument() != element->getDocument()) {
        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
        return SharedPtr<NodeImpl>();
    }

    // Not mentioned in spec: throw a HIERARCHY_REQUEST_ERROR if the user passes in a non-attribute node
    if (!arg->isAttributeNode()) {
        exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
        return SharedPtr<NodeImpl>();
    }
    AttrImpl *attr = static_cast<AttrImpl*>(arg);

    AttributeImpl* a = attr->attrImpl();
    AttributeImpl* old = getAttributeItem(a->name());
    if (old == a)
        return SharedPtr<NodeImpl>(arg); // we know about it already

    // INUSE_ATTRIBUTE_ERR: Raised if arg is an Attr that is already an attribute of another Element object.
    // The DOM user must explicitly clone Attr nodes to re-use them in other elements.
    if (attr->ownerElement()) {
        exceptioncode = DOMException::INUSE_ATTRIBUTE_ERR;
        return SharedPtr<NodeImpl>();
    }

    if (a->name() == HTMLAttributes::idAttr())
	element->updateId(old ? old->value() : nullAtom, a->value());

    // ### slightly inefficient - resizes attribute array twice.
    SharedPtr<NodeImpl> r;
    if (old) {
        if (!old->attrImpl())
            old->allocateImpl(element);
        r.reset(old->m_impl);
        removeAttribute(a->name());
    }

    addAttribute(a);
    return r;
}

// The DOM2 spec doesn't say that removeAttribute[NS] throws NOT_FOUND_ERR
// if the attribute is not found, but at this level we have to throw NOT_FOUND_ERR
// because of removeNamedItem, removeNamedItemNS, and removeAttributeNode.
SharedPtr<NodeImpl> NamedAttrMapImpl::removeNamedItem(const QualifiedName& name, int &exceptioncode)
{
    // ### should this really be raised when the attribute to remove isn't there at all?
    // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly
    if (isReadOnly()) {
        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
        return SharedPtr<NodeImpl>();
    }

    AttributeImpl* a = getAttributeItem(name);
    if (!a) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return SharedPtr<NodeImpl>();
    }

    if (!a->attrImpl())  a->allocateImpl(element);
    SharedPtr<NodeImpl> r(a->attrImpl());

    if (name == HTMLAttributes::idAttr())
	element->updateId(a->value(), nullAtom);

    removeAttribute(name);
    return r;
}

AttrImpl *NamedAttrMapImpl::item ( unsigned long index ) const
{
    if (index >= len)
        return 0;

    if (!attrs[index]->attrImpl())
        attrs[index]->allocateImpl(element);

    return attrs[index]->attrImpl();
}

AttributeImpl* NamedAttrMapImpl::getAttributeItem(const QualifiedName& name) const
{
    for (unsigned long i = 0; i < len; ++i) {
        if (attrs[i]->name().matches(name))
            return attrs[i];
    }
    return 0;
}

void NamedAttrMapImpl::clearAttributes()
{
    if (attrs) {
        uint i;
        for (i = 0; i < len; i++) {
            if (attrs[i]->m_impl)
                attrs[i]->m_impl->m_element = 0;
            attrs[i]->deref();
        }
        main_thread_free(attrs);
        attrs = 0;
    }
    len = 0;
}

void NamedAttrMapImpl::detachFromElement()
{
    // we allow a NamedAttrMapImpl w/o an element in case someone still has a reference
    // to if after the element gets deleted - but the map is now invalid
    element = 0;
    clearAttributes();
}

NamedAttrMapImpl& NamedAttrMapImpl::operator=(const NamedAttrMapImpl& other)
{
    // clone all attributes in the other map, but attach to our element
    if (!element) return *this;

    // If assigning the map changes the id attribute, we need to call
    // updateId.

    AttributeImpl *oldId = getAttributeItem(HTMLAttributes::idAttr());
    AttributeImpl *newId = other.getAttributeItem(HTMLAttributes::idAttr());

    if (oldId || newId) {
	element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom);
    }

    clearAttributes();
    len = other.len;
    attrs = static_cast<AttributeImpl **>(main_thread_malloc(len * sizeof(AttributeImpl *)));

    // first initialize attrs vector, then call attributeChanged on it
    // this allows attributeChanged to use getAttribute
    for (uint i = 0; i < len; i++) {
        attrs[i] = other.attrs[i]->clone();
        attrs[i]->ref();
    }

    // FIXME: This is wasteful.  The class list could be preserved on a copy, and we
    // wouldn't have to waste time reparsing the attribute.
    // The derived class, HTMLNamedAttrMapImpl, which manages a parsed class list for the CLASS attribute,
    // will update its member variable when parse attribute is called.
    for(uint i = 0; i < len; i++)
        element->attributeChanged(attrs[i], true);

    return *this;
}

void NamedAttrMapImpl::addAttribute(AttributeImpl *attr)
{
    // Add the attribute to the list
    AttributeImpl **newAttrs = static_cast<AttributeImpl **>(main_thread_malloc((len + 1) * sizeof(AttributeImpl *)));
    if (attrs) {
      for (uint i = 0; i < len; i++)
        newAttrs[i] = attrs[i];
      main_thread_free(attrs);
    }
    attrs = newAttrs;
    attrs[len++] = attr;
    attr->ref();

    AttrImpl * const attrImpl = attr->m_impl;
    if (attrImpl)
        attrImpl->m_element = element;

    // Notify the element that the attribute has been added, and dispatch appropriate mutation events
    // Note that element may be null here if we are called from insertAttr() during parsing
    if (element) {
        element->attributeChanged(attr);
        element->dispatchAttrAdditionEvent(attr);
        element->dispatchSubtreeModifiedEvent(false);
    }
}

void NamedAttrMapImpl::removeAttribute(const QualifiedName& name)
{
    unsigned long index = len+1;
    for (unsigned long i = 0; i < len; ++i)
        if (attrs[i]->name().matches(name)) {
            index = i;
            break;
        }

    if (index >= len) return;

    // Remove the attribute from the list
    AttributeImpl* attr = attrs[index];
    if (attrs[index]->m_impl)
        attrs[index]->m_impl->m_element = 0;
    if (len == 1) {
        main_thread_free(attrs);
        attrs = 0;
        len = 0;
    }
    else {
        AttributeImpl **newAttrs = static_cast<AttributeImpl **>(main_thread_malloc((len - 1) * sizeof(AttributeImpl *)));
        uint i;
        for (i = 0; i < uint(index); i++)
            newAttrs[i] = attrs[i];
        len--;
        for (; i < len; i++)
            newAttrs[i] = attrs[i+1];
        main_thread_free(attrs);
        attrs = newAttrs;
    }

    // Notify the element that the attribute has been removed
    // dispatch appropriate mutation events
    if (element && !attr->m_value.isNull()) {
        AtomicString value = attr->m_value;
        attr->m_value = nullAtom;
        element->attributeChanged(attr);
        attr->m_value = value;
    }
    if (element) {
        element->dispatchAttrRemovalEvent(attr);
        element->dispatchSubtreeModifiedEvent(false);
    }
    attr->deref();
}

// ------------------------------- Styled Element and Mapped Attribute Implementation

CSSMappedAttributeDeclarationImpl::~CSSMappedAttributeDeclarationImpl() {
    if (m_entryType != ePersistent)
        StyledElementImpl::removeMappedAttributeDecl(m_entryType, m_attrName, m_attrValue);
}

QPtrDict<QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> > >* StyledElementImpl::m_mappedAttributeDecls = 0;

CSSMappedAttributeDeclarationImpl* StyledElementImpl::getMappedAttributeDecl(MappedAttributeEntry entryType, AttributeImpl* attr)
{
    if (!m_mappedAttributeDecls)
        return 0;
    
    QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> >* attrNameDict = m_mappedAttributeDecls->find((void*)entryType);
    if (attrNameDict) {
        QPtrDict<CSSMappedAttributeDeclarationImpl>* attrValueDict = 
            attrNameDict->find((void*)attr->name().localName().implementation());
        if (attrValueDict)
            return attrValueDict->find(attr->value().implementation());
    }
    return 0;
}

void StyledElementImpl::setMappedAttributeDecl(MappedAttributeEntry entryType, AttributeImpl* attr, CSSMappedAttributeDeclarationImpl* decl)
{
    if (!m_mappedAttributeDecls)
        m_mappedAttributeDecls = new QPtrDict<QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> > >;
    
    QPtrDict<CSSMappedAttributeDeclarationImpl>* attrValueDict = 0;
    QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> >* attrNameDict = m_mappedAttributeDecls->find((void*)entryType);
    if (!attrNameDict) {
        attrNameDict = new QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> >;
        attrNameDict->setAutoDelete(true);
        m_mappedAttributeDecls->insert((void*)entryType, attrNameDict);
    }
    else
        attrValueDict = attrNameDict->find((void*)attr->name().localName().implementation());
    if (!attrValueDict) {
        attrValueDict = new QPtrDict<CSSMappedAttributeDeclarationImpl>;
        if (entryType == ePersistent)
            attrValueDict->setAutoDelete(true);
        attrNameDict->insert((void*)attr->name().localName().implementation(), attrValueDict);
    }
    attrValueDict->replace(attr->value().implementation(), decl);
}

void StyledElementImpl::removeMappedAttributeDecl(MappedAttributeEntry entryType,
                                                  const QualifiedName& attrName, const AtomicString& attrValue)
{
    if (!m_mappedAttributeDecls)
        return;
    
    QPtrDict<QPtrDict<CSSMappedAttributeDeclarationImpl> >* attrNameDict = m_mappedAttributeDecls->find((void*)entryType);
    if (!attrNameDict)
        return;
    QPtrDict<CSSMappedAttributeDeclarationImpl>* attrValueDict = attrNameDict->find((void*)attrName.localName().implementation());
    if (!attrValueDict)
        return;
    attrValueDict->remove(attrValue.implementation());
}

void StyledElementImpl::invalidateStyleAttribute()
{
    m_isStyleAttributeValid = false;
}

void StyledElementImpl::updateStyleAttributeIfNeeded() const
{
    if (!m_isStyleAttributeValid) {
        m_isStyleAttributeValid = true;
        m_synchronizingStyleAttribute = true;
        if (m_inlineStyleDecl)
            const_cast<StyledElementImpl*>(this)->setAttribute(HTMLAttributes::style(), m_inlineStyleDecl->cssText());
        m_synchronizingStyleAttribute = false;
    }
}

MappedAttributeImpl::~MappedAttributeImpl()
{
    if (m_styleDecl)
        m_styleDecl->deref();
}

AttributeImpl* MappedAttributeImpl::clone(bool preserveDecl) const
{
    return new MappedAttributeImpl(m_name, m_value, preserveDecl ? m_styleDecl : 0);
}

NamedMappedAttrMapImpl::NamedMappedAttrMapImpl(ElementImpl *e)
:NamedAttrMapImpl(e), m_mappedAttributeCount(0)
{}

void NamedMappedAttrMapImpl::clearAttributes()
{
    m_classList.clear();
    m_mappedAttributeCount = 0;
    NamedAttrMapImpl::clearAttributes();
}

bool NamedMappedAttrMapImpl::isMappedAttributeMap() const
{
    return true;
}

int NamedMappedAttrMapImpl::declCount() const
{
    int result = 0;
    for (uint i = 0; i < length(); i++) {
        MappedAttributeImpl* attr = attributeItem(i);
        if (attr->decl())
            result++;
    }
    return result;
}

bool NamedMappedAttrMapImpl::mapsEquivalent(const NamedMappedAttrMapImpl* otherMap) const
{
    // The # of decls must match.
    if (declCount() != otherMap->declCount())
        return false;
    
    // The values for each decl must match.
    for (uint i = 0; i < length(); i++) {
        MappedAttributeImpl* attr = attributeItem(i);
        if (attr->decl()) {
            AttributeImpl* otherAttr = otherMap->getAttributeItem(attr->name());
            if (!otherAttr || (attr->value() != otherAttr->value()))
                return false;
        }
    }
    return true;
}

void NamedMappedAttrMapImpl::parseClassAttribute(const DOMString& classStr)
{
    m_classList.clear();
    if (!element->hasClass())
        return;
    
    DOMString classAttr = element->getDocument()->inCompatMode() ? 
        (classStr.implementation()->isLower() ? classStr : DOMString(classStr.implementation()->lower())) :
        classStr;
    
    if (classAttr.find(' ') == -1 && classAttr.find('\n') == -1)
        m_classList.setString(AtomicString(classAttr));
    else {
        QString val = classAttr.string();
        val.replace('\n', ' ');
        QStringList list = QStringList::split(' ', val);
        
        AtomicStringList* curr = 0;
        for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
            const QString& singleClass = *it;
            if (!singleClass.isEmpty()) {
                if (curr) {
                    curr->setNext(new AtomicStringList(AtomicString(singleClass)));
                    curr = curr->next();
                }
                else {
                    m_classList.setString(AtomicString(singleClass));
                    curr = &m_classList;
                }
            }
        }
    }
}

StyledElementImpl::StyledElementImpl(const QualifiedName& name, DocumentPtr *doc)
    : ElementImpl(name, doc)
{
    m_inlineStyleDecl = 0;
    m_isStyleAttributeValid = true;
    m_synchronizingStyleAttribute = false;
}

StyledElementImpl::~StyledElementImpl()
{
    destroyInlineStyleDecl();
}

AttributeImpl* StyledElementImpl::createAttribute(const QualifiedName& name, DOMStringImpl* value)
{
    return new MappedAttributeImpl(name, value);
}

void StyledElementImpl::createInlineStyleDecl()
{
    m_inlineStyleDecl = new CSSMutableStyleDeclarationImpl;
    m_inlineStyleDecl->ref();
    m_inlineStyleDecl->setParent(getDocument()->elementSheet());
    m_inlineStyleDecl->setNode(this);
    m_inlineStyleDecl->setStrictParsing(!getDocument()->inCompatMode());
}

void StyledElementImpl::destroyInlineStyleDecl()
{
    if (m_inlineStyleDecl) {
        m_inlineStyleDecl->setNode(0);
        m_inlineStyleDecl->setParent(0);
        m_inlineStyleDecl->deref();
        m_inlineStyleDecl = 0;
    }
}

void StyledElementImpl::attributeChanged(AttributeImpl* attr, bool preserveDecls)
{
    MappedAttributeImpl* mappedAttr = static_cast<MappedAttributeImpl*>(attr);
    if (mappedAttr->decl() && !preserveDecls) {
        mappedAttr->setDecl(0);
        setChanged();
        if (namedAttrMap)
            static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->declRemoved();
    }

    bool checkDecl = true;
    MappedAttributeEntry entry;
    bool needToParse = mapToEntry(attr->name(), entry);
    if (preserveDecls) {
        if (mappedAttr->decl()) {
            setChanged();
            if (namedAttrMap)
                static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->declAdded();
            checkDecl = false;
        }
    }
    else if (!attr->isNull() && entry != eNone) {
        CSSMappedAttributeDeclarationImpl* decl = getMappedAttributeDecl(entry, attr);
        if (decl) {
            mappedAttr->setDecl(decl);
            setChanged();
            if (namedAttrMap)
                static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->declAdded();
            checkDecl = false;
        } else
            needToParse = true;
    }

    if (needToParse)
        parseMappedAttribute(mappedAttr);
    
    if (checkDecl && mappedAttr->decl()) {
        // Add the decl to the table in the appropriate spot.
        setMappedAttributeDecl(entry, attr, mappedAttr->decl());
        mappedAttr->decl()->setMappedState(entry, attr->name(), attr->value());
        mappedAttr->decl()->setParent(0);
        mappedAttr->decl()->setNode(0);
        if (namedAttrMap)
            static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->declAdded();
    }
}

bool StyledElementImpl::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
{
    result = eNone;
    if (attrName == HTMLAttributes::style())
        return !m_synchronizingStyleAttribute;
    return true;
}

void StyledElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
{
    if (attr->name() == HTMLAttributes::idAttr()) {
        // unique id
        setHasID(!attr->isNull());
        if (namedAttrMap) {
            if (attr->isNull())
                namedAttrMap->setID(nullAtom);
            else if (getDocument() && getDocument()->inCompatMode() && !attr->value().implementation()->isLower())
                namedAttrMap->setID(AtomicString(attr->value().domString().lower()));
            else
                namedAttrMap->setID(attr->value());
        }
        setChanged();
    } else if (attr->name() == HTMLAttributes::classAttr()) {
        // class
        setHasClass(!attr->isNull());
        if (namedAttrMap) static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->parseClassAttribute(attr->value());
        setChanged();
    } else if (attr->name() == HTMLAttributes::style()) {
        setHasStyle(!attr->isNull());
        if (attr->isNull())
            destroyInlineStyleDecl();
        else
            getInlineStyleDecl()->parseDeclaration(attr->value());
        m_isStyleAttributeValid = true;
        setChanged();
    }
}

void StyledElementImpl::createAttributeMap() const
{
    namedAttrMap = new NamedMappedAttrMapImpl(const_cast<StyledElementImpl*>(this));
    namedAttrMap->ref();
}

CSSMutableStyleDeclarationImpl* StyledElementImpl::getInlineStyleDecl()
{
    if (!m_inlineStyleDecl)
        createInlineStyleDecl();
    return m_inlineStyleDecl;
}

CSSStyleDeclarationImpl* StyledElementImpl::style()
{
    return getInlineStyleDecl();
}

CSSMutableStyleDeclarationImpl* StyledElementImpl::additionalAttributeStyleDecl()
{
    return 0;
}

const AtomicStringList* StyledElementImpl::getClassList() const
{
    return namedAttrMap ? static_cast<NamedMappedAttrMapImpl*>(namedAttrMap)->getClassList() : 0;
}

static inline bool isHexDigit( const QChar &c ) {
    return ( c >= '0' && c <= '9' ) ||
	   ( c >= 'a' && c <= 'f' ) ||
	   ( c >= 'A' && c <= 'F' );
}

static inline int toHex( const QChar &c ) {
    return ( (c >= '0' && c <= '9')
             ? (c.unicode() - '0')
             : ( ( c >= 'a' && c <= 'f' )
                 ? (c.unicode() - 'a' + 10)
                 : ( ( c >= 'A' && c <= 'F' )
                     ? (c.unicode() - 'A' + 10)
                     : -1 ) ) );
}

void StyledElementImpl::addCSSProperty(MappedAttributeImpl* attr, int id, const DOMString &value)
{
    if (!attr->decl()) createMappedDecl(attr);
    attr->decl()->setProperty(id, value, false);
}

void StyledElementImpl::addCSSProperty(MappedAttributeImpl* attr, int id, int value)
{
    if (!attr->decl()) createMappedDecl(attr);
    attr->decl()->setProperty(id, value, false);
}

void StyledElementImpl::addCSSStringProperty(MappedAttributeImpl* attr, int id, const DOMString &value, CSSPrimitiveValue::UnitTypes type)
{
    if (!attr->decl()) createMappedDecl(attr);
    attr->decl()->setStringProperty(id, value, type, false);
}

void StyledElementImpl::addCSSImageProperty(MappedAttributeImpl* attr, int id, const DOMString &URL)
{
    if (!attr->decl()) createMappedDecl(attr);
    attr->decl()->setImageProperty(id, URL, false);
}

void StyledElementImpl::addCSSLength(MappedAttributeImpl* attr, int id, const DOMString &value)
{
    // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
    // length unit and make the appropriate parsed value.
    if (!attr->decl()) createMappedDecl(attr);

    // strip attribute garbage..
    DOMStringImpl* v = value.implementation();
    if ( v ) {
        unsigned int l = 0;
        
        while ( l < v->l && v->s[l].unicode() <= ' ') l++;
        
        for ( ;l < v->l; l++ ) {
            char cc = v->s[l].latin1();
            if ( cc > '9' || ( cc < '0' && cc != '*' && cc != '%' && cc != '.') )
                break;
        }
        if ( l != v->l ) {
            attr->decl()->setLengthProperty(id, DOMString( v->s, l ), false);
            return;
        }
    }
    
    attr->decl()->setLengthProperty(id, value, false);
}

/* color parsing that tries to match as close as possible IE 6. */
void StyledElementImpl::addCSSColor(MappedAttributeImpl* attr, int id, const DOMString &c)
{
    // this is the only case no color gets applied in IE.
    if ( !c.length() )
        return;

    if (!attr->decl()) createMappedDecl(attr);
    
    if (attr->decl()->setProperty(id, c, false) )
        return;
    
    QString color = c.string();
    // not something that fits the specs.
    
    // we're emulating IEs color parser here. It maps transparent to black, otherwise it tries to build a rgb value
    // out of everyhting you put in. The algorithm is experimentally determined, but seems to work for all test cases I have.
    
    // the length of the color value is rounded up to the next
    // multiple of 3. each part of the rgb triple then gets one third
    // of the length.
    //
    // Each triplet is parsed byte by byte, mapping
    // each number to a hex value (0-9a-fA-F to their values
    // everything else to 0).
    //
    // The highest non zero digit in all triplets is remembered, and
    // used as a normalization point to normalize to values between 0
    // and 255.
    
    if ( color.lower() != "transparent" ) {
        if ( color[0] == '#' )
            color.remove( 0,  1 );
        int basicLength = (color.length() + 2) / 3;
        if ( basicLength > 1 ) {
            // IE ignores colors with three digits or less
            // 	    qDebug("trying to fix up color '%s'. basicLength=%d, length=%d",
            // 		   color.latin1(), basicLength, color.length() );
            int colors[3] = { 0, 0, 0 };
            int component = 0;
            int pos = 0;
            int maxDigit = basicLength-1;
            while ( component < 3 ) {
                // search forward for digits in the string
                int numDigits = 0;
                while ( pos < (int)color.length() && numDigits < basicLength ) {
                    int hex = toHex( color[pos] );
                    colors[component] = (colors[component] << 4);
                    if ( hex > 0 ) {
                        colors[component] += hex;
                        maxDigit = kMin( maxDigit, numDigits );
                    }
                    numDigits++;
                    pos++;
                }
                while ( numDigits++ < basicLength )
                    colors[component] <<= 4;
                component++;
            }
            maxDigit = basicLength - maxDigit;
            // 	    qDebug("color is %x %x %x, maxDigit=%d",  colors[0], colors[1], colors[2], maxDigit );
            
            // normalize to 00-ff. The highest filled digit counts, minimum is 2 digits
            maxDigit -= 2;
            colors[0] >>= 4*maxDigit;
            colors[1] >>= 4*maxDigit;
            colors[2] >>= 4*maxDigit;
            // 	    qDebug("normalized color is %x %x %x",  colors[0], colors[1], colors[2] );
            // 	assert( colors[0] < 0x100 && colors[1] < 0x100 && colors[2] < 0x100 );
            
            color.sprintf("#%02x%02x%02x", colors[0], colors[1], colors[2] );
            // 	    qDebug( "trying to add fixed color string '%s'", color.latin1() );
            if ( attr->decl()->setProperty(id, DOMString(color), false) )
                return;
        }
    }
    attr->decl()->setProperty(id, CSS_VAL_BLACK, false);
}

void StyledElementImpl::createMappedDecl(MappedAttributeImpl* attr)
{
    CSSMappedAttributeDeclarationImpl* decl = new CSSMappedAttributeDeclarationImpl(0);
    attr->setDecl(decl);
    decl->setParent(getDocument()->elementSheet());
    decl->setNode(this);
    decl->setStrictParsing(false); // Mapped attributes are just always quirky.
}
