From 34889b2ab50860cbee2a32e88fc36b32ad0eb8ad Mon Sep 17 00:00:00 2001
From: tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>
Date: Tue, 18 Jan 2011 23:06:51 +0000
Subject: Reverted accidental complete delete of this file

git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1215518 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
---
 khtml/html/html_elementimpl.cpp | 685 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 685 insertions(+)

diff --git a/khtml/html/html_elementimpl.cpp b/khtml/html/html_elementimpl.cpp
index e69de29bb..a5931cd41 100644
--- a/khtml/html/html_elementimpl.cpp
+++ b/khtml/html/html_elementimpl.cpp
@@ -0,0 +1,685 @@
+// -*- c-basic-offset: 4; -*-
+/**
+ * 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) 2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+// -------------------------------------------------------------------------
+//#define DEBUG
+//#define DEBUG_LAYOUT
+//#define PAR_DEBUG
+//#define EVENT_DEBUG
+//#define UNSUPPORTED_ATTR
+
+#include "html/dtd.h"
+#include "html/html_elementimpl.h"
+#include "html/html_documentimpl.h"
+#include "html/htmltokenizer.h"
+
+#include "misc/htmlhashes.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+
+#include "rendering/render_object.h"
+#include "rendering/render_replaced.h"
+#include "css/css_valueimpl.h"
+#include "css/css_stylesheetimpl.h"
+#include "css/cssproperties.h"
+#include "css/cssvalues.h"
+#include "xml/dom_textimpl.h"
+#include "xml/dom2_eventsimpl.h"
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include "html_elementimpl.h"
+
+using namespace DOM;
+using namespace khtml;
+
+HTMLElementImpl::HTMLElementImpl(DocumentImpl *doc)
+    : ElementImpl( doc )
+{
+    m_htmlCompat = doc && doc->htmlMode() != DocumentImpl::XHtml;
+}
+
+HTMLElementImpl::~HTMLElementImpl()
+{
+}
+
+bool HTMLElementImpl::isInline() const
+{
+    if (renderer())
+        return ElementImpl::isInline();
+
+    switch(id()) {
+        case ID_A:
+        case ID_FONT:
+        case ID_TT:
+        case ID_U:
+        case ID_B:
+        case ID_I:
+        case ID_S:
+        case ID_STRIKE:
+        case ID_BIG:
+        case ID_SMALL:
+
+            // %phrase
+        case ID_EM:
+        case ID_STRONG:
+        case ID_DFN:
+        case ID_CODE:
+        case ID_SAMP:
+        case ID_KBD:
+        case ID_VAR:
+        case ID_CITE:
+        case ID_ABBR:
+        case ID_ACRONYM:
+
+            // %special
+        case ID_SUB:
+        case ID_SUP:
+        case ID_SPAN:
+        case ID_NOBR:
+        case ID_WBR:
+            return true;
+
+        default:
+            return ElementImpl::isInline();
+    }
+}
+
+DOMString HTMLElementImpl::namespaceURI() const
+{
+    return (!m_htmlCompat) ?
+        DOMString(XHTML_NAMESPACE) : DOMString();
+}
+
+
+DOMString HTMLElementImpl::localName() const
+{
+    // We only have a localName if we were created by createElementNS(), in which
+    // case we are an XHTML element. This also means we have a lowercase name.
+    if (!m_htmlCompat) // XHTML == not HTMLCompat
+    {
+        NodeImpl::Id _id = id();
+        DOMString tn;
+        if ( _id >= ID_LAST_TAG )
+            tn = getDocument()->getName(ElementId, _id);
+        else // HTML tag
+            tn = getTagName( _id );
+	return tn; // lowercase already
+    }
+    // createElement() always returns elements with a null localName.
+    else
+	return DOMString();
+}
+
+DOMString HTMLElementImpl::tagName() const
+{
+    DOMString tn;
+    NodeImpl::Id _id = id();
+    if ( _id >= ID_LAST_TAG )
+        tn = getDocument()->getName(ElementId, _id);
+    else // HTML tag
+        tn = getTagName( _id );
+
+    if ( m_htmlCompat )
+        tn = tn.upper();
+
+    if (m_prefix)
+        return DOMString(m_prefix) + ":" + tn;
+
+    return tn;
+}
+
+void HTMLElementImpl::parseAttribute(AttributeImpl *attr)
+{
+    DOMString indexstring;
+    switch( attr->id() )
+    {
+    case ATTR_ALIGN:
+        if (attr->val()) {
+            if ( strcasecmp(attr->value(), "middle" ) == 0 )
+                addCSSProperty( CSS_PROP_TEXT_ALIGN, CSS_VAL_CENTER );
+            else
+                addCSSProperty(CSS_PROP_TEXT_ALIGN, attr->value().lower());
+        }
+        else
+            removeCSSProperty(CSS_PROP_TEXT_ALIGN);
+        break;
+// the core attributes...
+    case ATTR_ID:
+        // unique id
+        setHasID();
+        getDocument()->incDOMTreeVersion();
+        break;
+    case ATTR_CLASS:
+        if (attr->val()) {
+          DOMString v = attr->value();
+          const TQChar* s = v.tqunicode();
+          int l = v.length();
+          while( l && !s->isSpace() )
+            l--,s++;
+          setHasClassList(l);
+          setHasClass(true);
+        } else {
+          setHasClassList(false);
+          setHasClass(false);
+        }
+        break;
+    case ATTR_NAME:
+        getDocument()->incDOMTreeVersion();
+        break;
+    case ATTR_STYLE:
+        if (m_styleDecls)
+	    m_styleDecls->removeCSSHints();
+	else
+	    createDecl();
+        m_styleDecls->setProperty(attr->value());
+        setChanged();
+        break;
+    case ATTR_TABINDEX:
+        indexstring=getAttribute(ATTR_TABINDEX);
+        if (indexstring.length())
+            setTabIndex(indexstring.toInt());
+        break;
+// i18n attributes
+    case ATTR_LANG:
+        break;
+    case ATTR_DIR:
+        addCSSProperty(CSS_PROP_DIRECTION, attr->value().lower());
+        addCSSProperty(CSS_PROP_UNICODE_BIDI, CSS_VAL_EMBED);
+        break;
+// standard events
+    case ATTR_ONCLICK:
+	setHTMLEventListener(EventImpl::KHTML_ECMA_CLICK_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onclick", this));
+        break;
+    case ATTR_ONDBLCLICK:
+	setHTMLEventListener(EventImpl::KHTML_ECMA_DBLCLICK_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "ondblclick", this));
+        break;
+    case ATTR_ONMOUSEDOWN:
+        setHTMLEventListener(EventImpl::MOUSEDOWN_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onmousedown", this));
+        break;
+    case ATTR_ONMOUSEMOVE:
+        setHTMLEventListener(EventImpl::MOUSEMOVE_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onmousemove", this));
+        break;
+    case ATTR_ONMOUSEOUT:
+        setHTMLEventListener(EventImpl::MOUSEOUT_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onmouseout", this));
+        break;
+    case ATTR_ONMOUSEOVER:
+        setHTMLEventListener(EventImpl::MOUSEOVER_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onmouseover", this));
+        break;
+    case ATTR_ONMOUSEUP:
+        setHTMLEventListener(EventImpl::MOUSEUP_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onmouseup", this));
+        break;
+    case ATTR_ONKEYDOWN:
+        setHTMLEventListener(EventImpl::KEYDOWN_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onkeydown", this));
+	break;
+    case ATTR_ONKEYPRESS:
+        setHTMLEventListener(EventImpl::KEYPRESS_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onkeypress", this));
+	break;
+    case ATTR_ONKEYUP:
+        setHTMLEventListener(EventImpl::KEYUP_EVENT,
+	    getDocument()->createHTMLEventListener(attr->value().string(), "onkeyup", this));
+        break;
+    case ATTR_ONFOCUS:
+        setHTMLEventListener(EventImpl::FOCUS_EVENT,
+            getDocument()->createHTMLEventListener(attr->value().string(), "onfocus", this));
+        break;
+    case ATTR_ONBLUR:
+        setHTMLEventListener(EventImpl::BLUR_EVENT,
+            getDocument()->createHTMLEventListener(attr->value().string(), "onblur", this));
+        break;
+    case ATTR_ONSCROLL:
+        setHTMLEventListener(EventImpl::SCROLL_EVENT,
+            getDocument()->createHTMLEventListener(attr->value().string(), "onscroll", this));
+        break;
+// other misc attributes
+    default:
+#ifdef UNSUPPORTED_ATTR
+	kdDebug(6030) << "UATTR: <" << this->nodeName().string() << "> ["
+		      << attr->name().string() << "]=[" << attr->value().string() << "]" << endl;
+#endif
+        break;
+    }
+}
+
+void HTMLElementImpl::recalcStyle( StyleChange ch )
+{
+    ElementImpl::recalcStyle( ch );
+
+    if (m_render /*&& changed*/)
+        m_render->updateFromElement();
+}
+
+void HTMLElementImpl::addCSSProperty(int id, const DOMString &value)
+{
+    if(!m_styleDecls) createDecl();
+    m_styleDecls->setProperty(id, value, false, true);
+    setChanged();
+}
+
+void HTMLElementImpl::addCSSProperty(int id, int value)
+{
+    if(!m_styleDecls) createDecl();
+    m_styleDecls->setProperty(id, value, false, true);
+    setChanged();
+}
+
+void HTMLElementImpl::addCSSLength(int id, const DOMString &value, bool numOnly, bool multiLength)
+{
+    if(!m_styleDecls) createDecl();
+
+    // strip attribute garbage to avoid CSS parsing errors
+    // ### create specialized hook that avoids parsing every
+    // value twice!
+    if ( value.implementation() ) {
+        // match \s*[+-]?\d*(\.\d*)?[%\*]?
+        unsigned i = 0, j = 0;
+        TQChar* s = value.implementation()->s;
+        unsigned l = value.implementation()->l;
+
+        while (i < l && s[i].isSpace())
+            ++i;
+        if (i < l && (s[i] == '+' || s[i] == '-'))
+            ++i;
+        while (i < l && s[i].isDigit())
+            ++i,++j;
+
+        // no digits!
+        if (j == 0) return;
+
+        int v = kClamp( TQConstString(s, i).string().toInt(), -8192, 8191 ) ;
+        const char* suffix = "px";
+        if (!numOnly || multiLength) {
+            // look if we find a % or *
+            while (i < l) {
+                if (multiLength && s[i] == '*') {
+                    suffix = "";
+                    break;
+                }
+                if (s[i] == '%') {
+                    suffix = "%";
+                    break;
+                }
+                ++i;
+            }
+        }
+	if (numOnly) suffix = "";
+
+        TQString ns = TQString::number(v) + suffix;
+        m_styleDecls->setLengthProperty( id, DOMString( ns ), false, true, multiLength );
+        setChanged();
+        return;
+    }
+
+    m_styleDecls->setLengthProperty(id, value, false, true, multiLength);
+    setChanged();
+}
+
+static inline bool isHexDigit( const TQChar &c ) {
+    return ( c >= '0' && c <= '9' ) ||
+	   ( c >= 'a' && c <= 'f' ) ||
+	   ( c >= 'A' && c <= 'F' );
+}
+
+static inline int toHex( const TQChar &c ) {
+    return ( (c >= '0' && c <= '9')
+	     ? (c.tqunicode() - '0')
+	     : ( ( c >= 'a' && c <= 'f' )
+		 ? (c.tqunicode() - 'a' + 10)
+		 : ( ( c >= 'A' && c <= 'F' )
+		     ? (c.tqunicode() - 'A' + 10)
+		     : -1 ) ) );
+}
+
+/* color parsing that tries to match as close as possible IE 6. */
+void HTMLElementImpl::addHTMLColor( int id, const DOMString &c )
+{
+    if(!m_styleDecls) createDecl();
+
+    // this is the only case no color gets applied in IE.
+    if ( !c.length() ) {
+	removeCSSProperty(id);
+	return;
+    }
+
+    if ( m_styleDecls->setProperty(id, c, false, true) )
+	return;
+
+    TQString 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 ( m_styleDecls->setProperty(id, DOMString(color), false, true) )
+		return;
+	}
+    }
+    m_styleDecls->setProperty(id, CSS_VAL_BLACK, false, true);
+}
+
+void HTMLElementImpl::removeCSSProperty(int id)
+{
+    if(!m_styleDecls)
+        return;
+    m_styleDecls->setParent(getDocument()->elementSheet());
+    m_styleDecls->removeProperty(id, true /*nonCSSHint */);
+    setChanged();
+}
+
+DOMString HTMLElementImpl::innerHTML() const
+{
+    TQString result; //Use TQString to accumulate since DOMString is poor for appends
+    for (NodeImpl *child = firstChild(); child != NULL; child = child->nextSibling()) {
+        DOMString kid = child->toString();
+        result += TQConstString(kid.tqunicode(), kid.length()).string();
+    }
+    return result;
+}
+
+DOMString HTMLElementImpl::innerText() const
+{
+    TQString text = "";
+    if(!firstChild())
+        return text;
+
+    const NodeImpl *n = this;
+    // find the next text/image after the anchor, to get a position
+    while(n) {
+        if(n->firstChild())
+            n = n->firstChild();
+        else if(n->nextSibling())
+            n = n->nextSibling();
+        else {
+            NodeImpl *next = 0;
+            while(!next) {
+                n = n->parentNode();
+                if(!n || n == (NodeImpl *)this ) goto end;
+                next = n->nextSibling();
+            }
+            n = next;
+        }
+        if(n->isTextNode() ) {
+            DOMStringImpl* data = static_cast<const TextImpl *>(n)->string();
+            text += TQConstString(data->s, data->l).string();
+        }
+    }
+ end:
+    return text;
+}
+
+DocumentFragment HTMLElementImpl::createContextualFragment( const DOMString &html )
+{
+    // the following is in accordance with the definition as used by IE
+    if( endTag[id()] == FORBIDDEN )
+        return DocumentFragment();
+    // IE disallows innerHTML on inline elements.
+    // I don't see why we should have this restriction, as our
+    // dhtml engine can cope with it. Lars
+    //if ( isInline() ) return false;
+    switch( id() ) {
+        case ID_COL:
+        case ID_COLGROUP:
+        case ID_FRAMESET:
+        case ID_HEAD:
+        case ID_TABLE:
+        case ID_TBODY:
+        case ID_TFOOT:
+        case ID_THEAD:
+        case ID_TITLE:
+            return DocumentFragment();
+        default:
+            break;
+    }
+    if ( !getDocument()->isHTMLDocument() )
+        return DocumentFragment();
+
+    DocumentFragmentImpl* fragment = new DocumentFragmentImpl( docPtr() );
+    DocumentFragment f( fragment );
+    {
+        HTMLTokenizer tok( docPtr(), fragment );
+        tok.begin();
+        tok.write( html.string(), true );
+        tok.end();
+    }
+
+    // Exceptions are ignored because none ought to happen here.
+    int ignoredExceptionCode;
+
+    // we need to pop <html> and <body> elements and remove <head> to
+    // accomadate folks passing complete HTML documents to make the
+    // child of an element.
+    for ( NodeImpl* node = fragment->firstChild(); node; ) {
+        if (node->id() == ID_HTML || node->id() == ID_BODY) {
+            NodeImpl* firstChild = node->firstChild();
+            NodeImpl* child = firstChild;
+            while ( child ) {
+                NodeImpl *nextChild = child->nextSibling();
+                fragment->insertBefore(child, node, ignoredExceptionCode);
+                child = nextChild;
+            }
+            if ( !firstChild ) {
+                NodeImpl *nextNode = node->nextSibling();
+                fragment->removeChild(node, ignoredExceptionCode);
+                node = nextNode;
+            } else {
+                fragment->removeChild(node, ignoredExceptionCode);
+                node = firstChild;
+            }
+        } else if (node->id() == ID_HEAD) {
+            NodeImpl *nextNode = node->nextSibling();
+            fragment->removeChild(node, ignoredExceptionCode);
+            node = nextNode;
+        } else {
+            node = node->nextSibling();
+        }
+    }
+
+    return f;
+}
+
+void HTMLElementImpl::setInnerHTML( const DOMString &html, int &exceptioncode )
+{
+    // Works line innerText in Gecko
+    // ### test if needed for ID_SCRIPT as well.
+    if ( id() == ID_STYLE ) {
+        setInnerText(html, exceptioncode);
+        return;
+    }
+
+    DocumentFragment fragment = createContextualFragment( html );
+    if ( fragment.isNull() ) {
+        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+
+    // Make sure adding the new child is ok, before removing all children (#96187)
+    checkAddChild( fragment.handle(), exceptioncode );
+    if ( exceptioncode )
+        return;
+
+    removeChildren();
+    appendChild( fragment.handle(), exceptioncode );
+}
+
+void HTMLElementImpl::setInnerText( const DOMString &text, int& exceptioncode )
+{
+    // following the IE specs.
+    if( endTag[id()] == FORBIDDEN ) {
+        exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+        return;
+    }
+    // IE disallows innerHTML on inline elements. I don't see why we should have this restriction, as our
+    // dhtml engine can cope with it. Lars
+    //if ( isInline() ) return false;
+    switch( id() ) {
+        case ID_COL:
+        case ID_COLGROUP:
+        case ID_FRAMESET:
+        case ID_HEAD:
+        case ID_HTML:
+        case ID_TABLE:
+        case ID_TBODY:
+        case ID_TFOOT:
+        case ID_THEAD:
+        case ID_TR:
+            exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
+            return;
+        default:
+            break;
+    }
+
+    removeChildren();
+
+    TextImpl *t = new TextImpl( docPtr(), text.implementation() );
+    appendChild( t, exceptioncode );
+}
+
+void HTMLElementImpl::addHTMLAlignment( DOMString tqalignment )
+{
+    //qDebug("tqalignment is %s", tqalignment.string().latin1() );
+    // vertical tqalignment with respect to the current baseline of the text
+    // right or left means floating images
+    int propfloat = -1;
+    int propvalign = -1;
+    if ( strcasecmp( tqalignment, "absmiddle" ) == 0 ) {
+        propvalign = CSS_VAL_MIDDLE;
+    } else if ( strcasecmp( tqalignment, "absbottom" ) == 0 ) {
+        propvalign = CSS_VAL_BOTTOM;
+    } else if ( strcasecmp( tqalignment, "left" ) == 0 ) {
+	propfloat = CSS_VAL_LEFT;
+	propvalign = CSS_VAL_TOP;
+    } else if ( strcasecmp( tqalignment, "right" ) == 0 ) {
+	propfloat = CSS_VAL_RIGHT;
+	propvalign = CSS_VAL_TOP;
+    } else if ( strcasecmp( tqalignment, "top" ) == 0 ) {
+	propvalign = CSS_VAL_TOP;
+    } else if ( strcasecmp( tqalignment, "middle" ) == 0 ) {
+	propvalign = CSS_VAL__KHTML_BASELINE_MIDDLE;
+    } else if ( strcasecmp( tqalignment, "center" ) == 0 ) {
+	propvalign = CSS_VAL_MIDDLE;
+    } else if ( strcasecmp( tqalignment, "bottom" ) == 0 ) {
+	propvalign = CSS_VAL_BASELINE;
+    } else if ( strcasecmp ( tqalignment, "texttop") == 0 ) {
+	propvalign = CSS_VAL_TEXT_TOP;
+    }
+
+    if ( propfloat != -1 )
+	addCSSProperty( CSS_PROP_FLOAT, propfloat );
+    if ( propvalign != -1 )
+	addCSSProperty( CSS_PROP_VERTICAL_ALIGN, propvalign );
+}
+
+DOMString HTMLElementImpl::toString() const
+{
+    if (!hasChildNodes()) {
+	DOMString result = openTagStartToString();
+	result += ">";
+
+	if (endTag[id()] == REQUIRED) {
+	    result += "</";
+	    result += tagName();
+	    result += ">";
+	}
+
+	return result;
+    }
+
+    return ElementImpl::toString();
+}
+
+// -------------------------------------------------------------------------
+HTMLGenericElementImpl::HTMLGenericElementImpl(DocumentImpl *doc, ushort i)
+    : HTMLElementImpl(doc)
+{
+    _id = i;
+}
+
+HTMLGenericElementImpl::~HTMLGenericElementImpl()
+{
+}
-- 
cgit v1.2.3

