/* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
 *
 * Copyright (C) 1995-2012 Opera Software ASA.  All rights reserved.
 *
 * This file is part of the Opera web browser.
 * It may not be distributed under any circumstances.
 */
#ifndef HTM_ELM_H
#define HTM_ELM_H

// This include should go away.
#include "modules/logdoc/htm_ldoc.h"

#include "modules/logdoc/logdocenum.h"
#include "modules/url/url_id.h"

#include "modules/probetools/probepoints.h"

class HLDocProfile;
class HTML_Document;
class URL;
class CSS;
class StyleAttribute;
class StringTokenListAttribute;
class FramesDocument;
class FormObject;
class TempBuffer;
class AttrItem;
class TextData;
class DataSrc;
class DOM_Environment;
class DOM_ProxyEnvironment;
class OpNS4Plugin;
class ByteBuffer;
struct LayoutInfo;
class ElementRef;
class OpPlatformKeyEventData;
#ifdef SVG_SUPPORT
class SVGContext;
#endif // SVG_SUPPORT

class XMLDocumentInformation;

#ifdef XSLT_SUPPORT
class XSLT_StylesheetParser;
class XSLT_Stylesheet;
#endif // XSLT_SUPPORT

#include "modules/util/tree.h"
#include "modules/util/tempbuf.h"
#include "modules/logdoc/html.h"
#include "modules/logdoc/html_att.h"
#include "modules/logdoc/htm_lex.h"

class CssPropertyItem;

#include "modules/logdoc/src/attribute.h"
#include "modules/logdoc/src/doc_tree.h"
#include "modules/logdoc/namespace.h"
#include "modules/logdoc/class_attribute.h"
#include "modules/forms/formmanager.h"

#include "modules/display/cursor.h"
#include "modules/display/fontdb.h"
#include "modules/doc/css_mode.h"
#include "modules/hardcore/mem/mem_man.h"
#include "modules/style/css.h"
#include "modules/style/css_value_types.h"
#include "modules/style/css_all_properties.h"
#include "modules/prefs/prefsmanager/prefsmanager.h"
#include "modules/url/protocols/http_met.h"
#include "modules/dom/domeventtypes.h"
#include "modules/logdoc/markup.h"
class HTML5TokenWrapper;

class HEListElm;
class HEListElmRef;
class CSS_decl;
class CSS_Value;

class TraversalObject;
class LayoutProperties;

#ifdef CSS_VIEWPORT_SUPPORT
class CSS_ViewportMeta;
#endif // CSS_VIEWPORT_SUPPORT

#ifdef _WML_SUPPORT_
# include "modules/logdoc/wml.h"
class WML_Context;
#endif // _WML_SUPPORT_

#ifdef M2_SUPPORT
# include "modules/logdoc/omfenum.h"
#endif // M2_SUPPORT

class ES_Thread;
class DOM_Object;
class CSS_DOMStyleDeclaration;
struct ES_ProgramText;

#ifdef MEDIA_HTML_SUPPORT
class MediaElement;
class TrackElement;
#endif // MEDIA_HTML_SUPPORT

class Media;

class FormValue;

#ifdef JS_PLUGIN_SUPPORT
class JS_Plugin_Object;
#endif

/* Should not be used, but while it is, let's define it. */
#define NEW_SET_LENGTH_PROPERTY

#define NEW_HTML_Element()  OP_NEW(HTML_Element, ())
#define DELETE_HTML_Element(e) OP_DELETE(e)

#include "modules/forms/formvalue.h"

extern TempBuffer	g_dom_tempbuf;

#define DOM_TO_DOC_CODE_RELOCATION

#ifdef XML_EVENTS_SUPPORT
class XML_Events_Registration;
#endif

const int ATTR_NOT_FOUND = -1;

#define APPLY_DOC_STYLES_NO		0
#define APPLY_DOC_STYLES_SOME	1
#define APPLY_DOC_STYLES_YES	2

#define FLEXIBLE_FONTS_PREDEFINED_ONLY			0
#define FLEXIBLE_FONTS_PREVIOUS_TO_PREDEFINED	1
#define FLEXIBLE_FONTS_DOCUMENT_TO_PREDEFINED	2
#define FLEXIBLE_FONTS_DOCUMENT_ONLY			3

/**
 * Constants used to indicate how the element was inserted into the
 * logical tree.  Elements marked with some of them will not be
 * visible in the DOM and others will not be visible to the style
 * matcher.
 *
 * <pre>
 *
 * Legend: X = Visible to scripts (in the DOM) (Actual* traverse methods, as
 *             HTML_Element::ActualNext()).
 *
 *         Y = Visible to the style (CSS) matcher (ActualStyle* traverse
 *             methods; HTML_Element::ActualStyleNext())
 *
 *         Z = Visible to normal layout (Normal traverse methods:
 *             HTML_Element::Next()). Will typically be displayed if it's
 *             displayable but depending on other flags, might not be
 *             stylable.
 *
 *
 * HE_NOT_INSERTED              XYZ  Elements inserted during normal parsing.
 *
 * HE_INSERTED_BYPASSING_PARSER XYZ  Elements generated by DOM, WF2, XSLT and
 *                                   inserted directly with tree operations.
 *
 * HE_INSERTED_BY_PARSE_AHEAD   -YZ  Elements inserted speculatively by Delayed
 *                                   Script Execution while waiting for scripts
 *                                   to run. Should be displayed as normal but
 *                                   should preferably not trigger anything with
 *                                   side effects visible to scripts or the
 *                                   server. That should instead trigger
 *                                   when the element receives the normal
 *                                   HE_NOT_INSERTED type.
 *
 * HE_INSERTED_BY_TRACK         -YZ  Elements generated by HTML <video> to
 *                                   represent cues for a text track.
 *
 * HE_INSERTED_BY_LAYOUT        --Z  An element that is inserted to help the
 *                                   html layout engine. For example
 *                                   anonymous table elements or
 *                                   pseudo elements for generated
 *                                   content. This element is
 *                                   invisible through DOM and may be
 *                                   deleted during layout/reflow so
 *                                   dont keep references to it unless
 *                                   you know what you are doing.
 *
 * HE_INSERTED_BY_CSS_IMPORT    --Z  The CSS @import command is implemented by
 *                                   inserting invisible HE_LINK elements with
 *                                   this HE_InsertType.
 *
 * HE_INSERTED_BY_SVG           --Z  Similar to HE_INSERTED_BY_LAYOUT but for
 *                                   the svg layout engine.
 *
 * </pre>
 */
enum HE_InsertType
{
	HE_NOT_INSERTED, ///< Elements inserted during normal parsing.
	HE_INSERTED_BYPASSING_PARSER, ///< DOM, WF2, XSLT... see above.

	//////////////////////////////////////////////////////////////////////
	// All below are hidden by HTML_Element::*Actual functions, i.e. they
	// are not visible to script but they are visible to the style matcher
	// and of course visible in HTML layout.
	//////////////////////////////////////////////////////////////////////

	HE_INSERTED_BY_PARSE_AHEAD, ///< DSE, see full documentation above.
	HE_INSERTED_BY_TRACK,		///< HTML <video> track cues, see full doc above.

	//////////////////////////////////////////////////////////////////////
	// All below are hidden by HTML_Element::*ActualStyle functions,
	// i.e. they are not visible to scripts and they don't have any
	// CSS style applied to them but will normally be processed by the
	// html layout engine.
	//////////////////////////////////////////////////////////////////////

	HE_INSERTED_BY_LAYOUT, ///< HTML layout engine, see full doc above.
	HE_INSERTED_BY_CSS_IMPORT, ///< CSS @import, see full doc above.
	HE_INSERTED_BY_SVG, ///< SVG layout engine, see full doc above
	HE_INSERTED_BY_IME, ///< Temporary, uncommitted text inserted by IME.

	HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL = HE_INSERTED_BY_PARSE_AHEAD,
	HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL_STYLE = HE_INSERTED_BY_LAYOUT,
	HE_INSERTED_BY_DOM = HE_INSERTED_BYPASSING_PARSER ///< Kept for backwards compatibility.
};

#define LIST_TYPE_NULL			CSS_VALUE_none
#define LIST_TYPE_NUMBER		CSS_VALUE_decimal
#define LIST_TYPE_LOWER_ALPHA	CSS_VALUE_lower_alpha
#define LIST_TYPE_UPPER_ALPHA	CSS_VALUE_upper_alpha
#define LIST_TYPE_LOWER_ROMAN	CSS_VALUE_lower_roman
#define LIST_TYPE_UPPER_ROMAN	CSS_VALUE_upper_roman
#define LIST_TYPE_DISC			CSS_VALUE_disc
#define LIST_TYPE_SQUARE		CSS_VALUE_square
#define LIST_TYPE_BOX			CSS_VALUE_box
#define LIST_TYPE_CIRCLE		CSS_VALUE_circle

#define CLEAR_NONE		0
#define CLEAR_LEFT		1
#define CLEAR_RIGHT		2
#define CLEAR_ALL		3

#define	AREA_SHAPE_DEFAULT	0
#define	AREA_SHAPE_RECT		1
#define	AREA_SHAPE_CIRCLE	2
#define	AREA_SHAPE_POLYGON	3

#define FRAMESET_RELATIVE_SIZED		0
#define FRAMESET_PERCENTAGE_SIZED	1
#define FRAMESET_ABSOLUTE_SIZED		2

#define DEFAULT_FRAMEMARGINWIDTH	8
#define DEFAULT_FRAMEMARGINHEIGHT	8
#define DEFAULT_FRAMESETBORDER		4

#define ELM_NOT_DIRTY		0
#define ELM_DIRTY			1
#define ELM_EXTRA_DIRTY		2
#define ELM_BOTH_DIRTY		(ELM_DIRTY | ELM_EXTRA_DIRTY)
#define ELM_MINMAX_DELETED	4

class Box;
class CSS_property_list;
class VisualDevice;
#ifdef SVG_SUPPORT
class SVGContext;

/**
 * An interface used for notifying when an SVG element has finished (loaded,
 * parsed, etc).
 *
 * When an <img> contains an SVG image, for the content to be used an IFRAME is
 * create that contains the SVG XML document. An SVGIMGResourceListener is
 * added via the HTML_Element::SetSVGIMGResourceListener() function and the
 * function SignalFinished() gets called when the SVG image is ready to be used.
 */
class SVGIMGResourceListener : public ComplexAttr
{
public:
	/** Called when an SVG element is finished. */
	virtual void SignalFinished() = 0;
};
#endif // SVG_SUPPORT

/**
 * The class used to represent elements in the logical tree used to represent
 * a document. Each element in the markup will have its own HTML_Element
 */
class HTML_Element
  : public DocTree
{
	friend class HTML_AttrIterator;
	friend class HTML_ImmutableAttrIterator;

	OP_ALLOC_ACCOUNTED_POOLING
	OP_ALLOC_ACCOUNTED_POOLING_SMO_DOCUMENT

public:
	/** Helper class used to define the context of an element, that is, which
	    document or DOM environment it belongs to. */
	class DocumentContext
	{
	public:
		DocumentContext(FramesDocument *frames_doc);
		DocumentContext(LogicalDocument *logdoc);
		DocumentContext(DOM_Environment *environment);

		/* All of these can be NULL! */

		FramesDocument *frames_doc;
		LogicalDocument *logdoc;
		HLDocProfile *hld_profile;
		DOM_Environment *environment;
	};


private:

	Box*			layout_box;

#ifdef SVG_SUPPORT
	/** Auxiliary data for SVG elements. */
	SVGContext*	svg_context;
#endif // SVG_SUPPORT

	union
	{
		struct
		{
			/** Numeric code for the type of element */
			unsigned int
					type:9;
			/** Index into the namespace table */
			unsigned int
					ns_idx:8;
			/** Tells how it was inserted into the logical tree */
			unsigned int
					inserted:3;
			/** The length of the attribute array, but not necessarily the number of attributes */
			unsigned int
					attr_size:8;
			/** TRUE if a external reference to this element exists */
            unsigned int
                    is_referenced_by_doc:1;
			/** The element is explicitly ended with an endtag */
            unsigned int
                    end_tag_found:1;
			/** TRUE if this element has a class attribute */
			unsigned int
					has_class:1;

		} packed1; // 31 bits
		unsigned int
					packed1_init;
	};

	union
	{
		struct
		{
			/** Number of elements in the css_properties array */
			unsigned int
					css_props_size:7;
			unsigned int
					css_is_real_size_dependent:1;
			/**
			 * Holds the code for types of dirty. Used by layout to indicate
			 * that this element heeds to be laid out again
			*/
			unsigned int
					dirty:3;
			/** FALSE if the array of CssPropertyItem is dirty and must be reloaded. */
			unsigned int
					props_clean:1;
			/** TRUE if props of any of the children of this element are dirty. */
			unsigned int
					child_props_dirty:1;
			unsigned int
					needs_update:1;
			/** TRUE if this element has a cursor type specified explicitly */
            unsigned int
                    has_cursor_settings:1;
			/** Element is generated by the css content property */
			unsigned int
					generated_content:1;
			unsigned int
					pseudo:3;

			/**
			 * Set if layout box has a background image (move to Content_Box
			 * if not enough bits in packed2)
			 */
			unsigned int
					has_bg_image:1;

			unsigned int  is_in_selection:1;

			/**
			 * CSS bits:
			 * The current status of this element wrt. focus/hover
			 * etc. Used to find the right CSS2-rules.
			 */
			unsigned int  hovered:1;
			unsigned int  focused:1;
			unsigned int  activated:1;

			/** If true, the element either has a matching a css rule with :empty,
				or has a child which has a rule that matches one of the following:
				:last-of-type, :nth-last-of-type, :last-child, :nth-last-child, :only-child,
				:only-of-type.

				That means that this element or any of the child elements might change pseudo
				state when children are added. We need to apply property changes when the
				element is closed. */
			unsigned int update_pseudo_element:1;

			/** If true, the element has hover, active or focus.*/
			unsigned int check_dynamic:1;

			unsigned int has_first_letter:1;
			unsigned int has_first_line:1;
			unsigned int has_after:1;
			unsigned int has_before:1;

			unsigned int shared_css:1;
#ifdef WEB_TURBO_MODE
			unsigned int object_is_embed:1;
#endif // WEB_TURBO_MODE
		} packed2; // 32 bits. (counting shared_css and object_as_embed)
		unsigned int
					packed2_init;
	};

	DOM_Object *exo_object;

	/**
	 * A union of the attribute array and the text content. Text elements
	 * cannot have attributes and other elements cannot have text content
	 */
	union
	{
		AttrItem*	attrs;
		TextData*   text;
	} data;

	friend class ElementRef;

	/**
	 * Start of a list of references to this element. The referrers will be
	 * notified when the element is removed or deleted.
	 */
	ElementRef*		m_first_ref;

	/**
	 * Sets the new text data of this element. This must be either HE_TEXT or HE_TEXTGROUP.
	 * In case of failure the current text data is not changed.
	 * Unlike the public variants of SetText, this method just makes the operations related with
	 * setting the new text data (perhaps making or removing HE_TEXTGROUP),
	 * not carrying out any document operations related with the change of the text
	 * of an text element.
	 * @param doc The document of this element.
	 * @param txt A new text to set.
	 * @param txt_len The length of a new text.
	 * @return OpStatus::ERR_NO_MEMORY if allocation for the new text data fails, OK otherwise.
	 */
	OP_STATUS		SetTextInternal(FramesDocument* doc, const uni_char *txt, unsigned int txt_len);

	/**
	 * Puts a new DataSrc object at a specified attribute position.
	 * @param idx The index into the attribute array
	 * @param dupl_head A list of DataSrcElms to put into the list
	 * @returns Returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
	OP_STATUS		SetSrcListAttr(int idx, DataSrc* dupl_head);

	/** @returns TRUE if this element is a descendant of a html:li element */
	BOOL			InsideLIList() const;
	/** @returns TRUE if this element is a descendant of a html:dl element */
	BOOL			InsideDLList() const;

	/** @returns A pointer to the text buffer of this element if it is a text element */
	const uni_char*	LocalContent() const;
	/** @returns Number of characters in the text buffer of this element if it is a text element */
	short			LocalContentLength() const;

	/**
	 * Called when the element is deleted. All the references will be checked
	 * and reset to avoid using a deleted element. The element needs to be
	 * flagged as referenced with the SetReferenced() method to be checked
	 */
    void            CleanReferences(FramesDocument *frm_doc);
	/** Called when the element is deleted. Will delete attributes or text */
	void			LocalClean();

#if defined SEARCH_MATCHES_ALL && !defined HAS_NO_SEARCHTEXT
	/**
	 * Called when the element is deleted. Clears element's subtree from the search hit.
	 * Must be called before element is removed from the tree.
	 */
	void			CleanSearchHit(FramesDocument *frm_doc);
#endif // SEARCH_MATCHES_ALL && !HAS_NO_SEARCHTEXT

	/**
	 * Called when an attribute is deleted. Will delete attribute content
	 * @param i Index into the attribute array of the attribute to clean
	 */
    void            LocalCleanAttr(int i);
	/**
	 * Replace an attribute value with another.
	 * @param i Index into the attribute array of the attribute to replace
	 * @param need_free TRUE if the attribute data needs to be deleted after use
	 * @param is_special TRUE if this is an internal attr. Will not be visible in DOM
	 */
	void			ReplaceAttrLocal(int i, short attr, ItemType item_type, void* value, int ns_idx, BOOL need_free, BOOL is_special, BOOL is_id = FALSE, BOOL is_specified = TRUE, BOOL is_event = FALSE);
	/**
	 * Set an attribute value.
	 * @param i Index into the attribute array of the attribute to replace
	 * @param need_free TRUE if the attribute data needs to be deleted after use
	 * @param is_special TRUE if this is an internal attr. Will not be visible in DOM
	 */
	void			SetAttrLocal(int i, short attr, ItemType item_type, void* value, int ns_idx = NS_IDX_HTML, BOOL need_free = FALSE, BOOL is_special = FALSE, BOOL is_id = FALSE, BOOL is_specified = TRUE, BOOL is_event = FALSE);
	/**
	 * Called from SetAttr()/SetSpecialAttr() to actually set or replace the attribute.
	 * @param i Index into the attribute array of the attribute to set.
	 * @param attr The type code for the attribute to set.
	 * @param item_type The value type of the attribute.
	 * @param val The value to set cast to a void pointer.
	 * @param need_free If set to TRUE the value will be deleted when the attribute is deleted.
	 * @param ns_idx The namespace index of the attribute.
	 * @param is_special TRUE if the attribute to be set is a special internal one.
	 * @param is_id Set to TRUE if the attribute is a unique identifier.
	 * @param is_specified Set to TRUE if the attribute is explicitly specified in the markup.
	 * @param is_event Set to TRUE if it is an event handler.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetAttrCommon(int i, short attr, ItemType item_type, void* val, BOOL need_free, int ns_idx, BOOL is_special, BOOL is_id, BOOL is_specified, BOOL is_event);

	/**
	 * Get the string value of an attribute.
	 * @param i Index into the attribute array of the attribute to replace
	 * @param for_element_type what kind of element this is on/for.
	 *   Used when deciding if negative values should be returned as percentages; HE_ANY to always have them be, HE_UNKNOWN for never.
	 *   For other values of 'for_element_type', negative values will be returned as percentages if a length-like attribute.
	 * @param buffer Buffer to store the string value for attributes that stores
	 *   only a canonical value and needs to generate a string.
	 */
    const uni_char*	GetAttrValueValue(int i, short attr, HTML_ElementType for_element_type = HE_UNKNOWN, TempBuffer *buffer = NULL) const;

	/** Stringify the value of a 'numeric' attribute.
	 * @param buf A uni_char buffer at least 25 bytes long.
	 * @param for_element_type what kind of element this is for.
	 *   Used when deciding if negative values should be returned as percentages; HE_ANY to always have them be, HE_UNKNOWN for never.
	 *   For other values of 'for_element_type', negative values will be returned as percentages if a length-like attribute.
	 */
	const uni_char* GenerateStringValueFromNumAttr(int attr, NS_Type ns_type, void* value, uni_char* buf, HTML_ElementType for_element_type) const;

	/**
	 * Checks if we would nest form elements in an illegal way by
	 * adding a HE_FORM child. Nested form elements are only sometimes
	 * legal.
	 *
	 * @returns TRUE if we have close parent that is a form and not
	 * closed. Only useful while parsing (since afterwards everything
	 * will be closed).
	 */
	BOOL			IsInsideUnclosedFormElement();


	/** @returns The size of the attribute array. */
	short			GetAttrSize() const { return (short) packed1.attr_size; }
	/** Used to set the size of the attribute array. */
	void			SetAttrSize(short val) { OP_ASSERT(val < 0xff || !"8 bit field overflow"); packed1.attr_size = val; }
	/** @returns the number of used attribute slots in the attribute array */
	short			GetAttrCount() const;

	/**
	 * Returns the name of the attribute as a string
	 */
	const uni_char* GetAttrName(int attr_idx, Markup::AttrType attr, NS_Type ns);

	/**
	 * A short text with an unterminated entity that should be decoded.
	 *
	 * Similar to normal Construct(uni_char* text, unsigned text_len) methods but this is
	 * be used when the text ends in an entity (or entity-wannabe) that isn't terminated
	 * and thus may change.
	 *
	 * @param[in] text The text.
	 *
	 * @param[in] text_len The length of the text.
	 *
	 */
	OP_STATUS		ConstructUnterminatedText(const uni_char* text, unsigned text_len);

	/**
	 * Secondary constructor. Used to generate a text element
	 * @param resolve_entities Will replace entity references if TRUE
	 * @returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    OP_STATUS		Construct(const uni_char* txt, unsigned int txt_len, BOOL resolve_entities, BOOL is_cdata);

#ifdef MEDIA_HTML_SUPPORT
    /**
     * Constructs and sets the media element attribute.
     *
     * @param[in] attr_index If not -1, index into the attribute array where the media element should go.
     * 						 If the value is -1 a free slot is found automatically.
     * @param[out] element If non-NULL, the constructed media element.
     */
	OP_STATUS 		ConstructMediaElement(int attr_index = -1, MediaElement **element = NULL);
#endif // MEDIA_HTML_SUPPORT

	/**
	 * Some elements has some extra special attributes with meta data. This method adds
	 * them during construction of the element. Only used during construction of an element.
	 * @param[in,out] attr_i The index into the attribute array where new values can be put. Can be increased in this method.
	 * @param ns The namespace of the element.
	 * @param ha_list To get the values of the other attributes when creating private attributes for plugins.
	 * @param hld_profile The HLDocProfile of the document that the element belongs to.
	 * @returns Normal OOM values.
	 */
	OP_STATUS		SetExtraAttributesForType(unsigned &attr_i, NS_Type ns_type, HtmlAttrEntry *ha_list, int attr_count, HLDocProfile *hld_profile);

	/**
	 * Used internally to delete the contents of the element
	 */
	void            CleanLocal(const DocumentContext& context);
	/**
	 * Used internally to delete the layout parts of an inactive element to save memory
	 */
	void            FreeLayoutLocal(FramesDocument* doc);

	/**
	 * Checks if the attribute value seems to be the same as the one we already have at pos index.
	 * That the attribute at pos index is the same attribute needs to be checked already.
	 *
	 * @param index The index of the current attribute - must exist.
	 *
	 * @param name The name of the attribute. Only used for ATTR_XML attributes.
	 *
	 * @param value The new value of the attribute.
	 *
	 * @returns TRUE if the textual representation of the current and new value is the
	 * same. If uncertain, it will return FALSE.
	 */
	BOOL IsSameAttrValue(int index, const uni_char* name, const uni_char* value);

	/**
	 * Tries to get two strings from the element:
	 * - a concatenation of strings of all descendant text nodes
	 * - image's alt.
	 * @param[out] title_buffer a temporary buffer that should be filled with the total inner text
	 * @param[out] alt_text the value of the alt parameter of the last descendant (including this element)
	 *						img encountered. If there is no img with alt, nothing is assigned.
	 * @return Memory error or OK.
	 */
	OP_STATUS		GetInnerTextOrImgAlt(TempBuffer& title_buffer, const uni_char*& alt_text);

#ifdef XML_EVENTS_SUPPORT
	/**
	 * Adds an xml event handler to this element. To be used when an element is inserted into the document.
	 *
	 * @param[in] frames_doc The document
	 * @param[in] ns_event_attr The attribute in the NS_EVENT namespace
	 * @param[in] value The value of the attribute
	 * @param[in] value_len The length of the value.
	 *
	 * @returns Memory error or OK.
	 */
	OP_STATUS HandleXMLEventAttribute(FramesDocument* frames_doc, XML_Events_Registration *registration, int ns_event_attr, const uni_char* value, int value_len);
#endif

#ifndef MOUSELESS
	/**
	 * Checks if this element can be considered a link. That is
	 * used to determine the default cursor for hovering this
	 * element and doesn't include any deeper considerations
	 * regarding what the 'link' will do.
	 *
	 * @param frames_doc The document that contains this element.
	 *
	 * @returns TRUE if this should have a link mouse cursor,
	 * FALSE otherwise.
	 */
	BOOL IsLink(FramesDocument *frames_doc);
#endif // !MOUSELESS

#ifdef DOCUMENT_EDIT_SUPPORT
	/** called from HandleAttributeChange and HandleDocumentTreeChange */
	OP_STATUS		EnableContentEditable(FramesDocument *frames_doc);
#endif // DOCUMENT_EDIT_SUPPORT

#ifdef JS_PLUGIN_SUPPORT
	/**
	 * Set up this HTML element as a jsplugin OBJECT element, if
	 * the MIME type is claimed by a jsplugin.
	 *
	 * @param type_attr MIME type for the OBJECT element.
	 * @return OpStatus::OK if a jsplugin was successfully setup, OpStatus:ERR if that wasn't
	 * applicable or possible and OpStatus::ERR_NO_MEMORY if an out-of-memory condition was encountered.
	 */
	OP_STATUS SetupJsPluginIfRequested(const uni_char* type_attr, HLDocProfile* hld_profile);
#endif

	OP_BOOLEAN GetResolvedHtmlElementType(URL* inline_url, LogicalDocument* logdoc, const char* resource_type,  HTML_ElementType default_type, HTML_ElementType& resolved_type, BOOL is_currently_parsing_this = FALSE);

protected:

	/* These methods are used to get properties from a specified attribute */
	BOOL			GetItemFree(int i) const { return data.attrs[i].NeedFree(); }
	BOOL			GetAttrIsSpecial(int i) const { return data.attrs[i].IsSpecial(); }
	BOOL			GetAttrIsId(int i) const { return data.attrs[i].IsId(); }
	BOOL			GetAttrIsSpecified(int i) const { return data.attrs[i].IsSpecified();}
	BOOL			GetAttrIsEvent(int i) const { return data.attrs[i].IsEvent();}
	ItemType		GetItemType(int i) const { return data.attrs[i].GetType(); }
	Markup::AttrType
					GetAttrItem(int i) const { return data.attrs[i].GetAttr(); }
	void*			GetValueItem(int i) const { return data.attrs[i].GetValue(); }

public:

                    HTML_Element();
                    ~HTML_Element();
	/**
	 * Secondary constructor. Used to copy a HTML_Element to another.
	 * @param skip_events Will skip copying event handlers if TRUE
	 * @param force_html Create elements with NS_IDX_HTML, that is, as if parsed
	 *   by the HTML parser,regardless of the source elements.
	 * @returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    OP_STATUS       Construct(HLDocProfile* hld_profile, HTML_Element* he,
						BOOL skip_events = FALSE, BOOL force_html = FALSE);
	/**
	 * Secondary constructor. Used to generate an element for a generic element
	 * in a markup document.
	 *
	 * @param[in] hld_profile Context object required for many advanced element
	 * types or if there are attributes. Might be NULL for some simple types like HE_TEXTGROUP.
	 * @param ns_idx The index into the namespace table for the XML namespace
	 * @param ha_list List of raw attribute data
	 * @param inserted The way the element was inserted into the logical tree
	 * @param decode_entities_in_attributes If TRUE they will be decoded by Construct. If FALSE, they should already have been decoded by the caller.
	 * @returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    OP_STATUS       Construct(HLDocProfile* hld_profile, int ns_idx,
						HTML_ElementType type, HtmlAttrEntry* ha_list,
						HE_InsertType inserted = HE_NOT_INSERTED,
						BOOL decode_entities_in_attributes = FALSE);
	/** Secondary constructor. Shortcut for the one below */
    OP_STATUS       Construct(HLDocProfile* hld_profile, const uni_char* ttxt, unsigned int text_len);

	/**
	  * Use the Construct that doesn't take a hldocprofile, or rather, use HTML_Element::SetText, CreateText and AppendText.
	  */
	OP_STATUS      DEPRECATED(Construct(HLDocProfile*, const uni_char* txt,
						unsigned int txt_len, BOOL not_used, BOOL plain_txt,
						BOOL replace_ws, BOOL force_linebreaks = FALSE)); // inlined below


	/**
	 * Adds text to a text element, splitting it into a HE_TEXTGROUP if necessary.
	 *
	 * @param[in] hld_profile Context, may be NULL but in that case invalidation won't work correctly so
	 * it should only be NULL when working on elements outside the tree.
	 * @param[in] text The text to add to the text node. May be NULL (if text_len is 0)
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] resolve_entities If html entities shoud be expanded. Typically FALSE unless called with HTML source code.
	 * @param[in] is_cdata Normally FALSE but TRUE if the element is a CDATA text element.
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] expand_wml_vars If WML variable references should be expanded. Typically FALSE unless we're in a WML document.
	 * @param[in] is_foster_parented The text to be inserted is only to be inserted in the current position because it has been foster parented.
	 */
	OP_STATUS AppendText(HLDocProfile* hld_profile, const uni_char* text, unsigned text_len, BOOL resolve_entities, BOOL is_cdata, BOOL expand_wml_vars, BOOL is_foster_parented = FALSE);

	/**
	 * Function that creates a text node (HE_TEXT or HE_TEXTGROUP depending on what is needed. This
	 * should be used insted of manually contructing the text element.
	 *
	 * @param[in] hld_profile Context, may be NULL but in that case invalidation won't work correctly and neither will
	 * wml variable expansion so it should only be NULL when working on non-wml elements outside the tree.
	 * @param[in] text The text to add to the text node. May be NULL (if text_len is 0)
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] resolve_entities If html entities shoud be expanded. Typically FALSE unless called with HTML source code.
	 * @param[in] is_cdata Normally FALSE but TRUE if the element is a CDATA text element.
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] expand_wml_vars If WML variable references should be expanded. Typically FALSE unless we're in a WML document.
	 */
	static HTML_Element* CreateText(HLDocProfile* hld_profile, const uni_char* text, unsigned text_len, BOOL resolve_entities, BOOL is_cdata, BOOL expand_wml_vars);

	/**
	 * Function that creates a text node (HE_TEXT or HE_TEXTGROUP depending on what is needed. This
	 * should be used insted of manually contructing the text element.
	 *
	 * @param[in] text The text to add to the text node. May be NULL (if text_len is 0)
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] resolve_entities If html entities shoud be expanded. Typically FALSE unless called with HTML source code.
	 * @param[in] is_cdata Normally FALSE but TRUE if the element is a CDATA text element.
	 * @param[in] text_len The length of the text. May be 0.
	 * @param[in] expand_wml_vars If WML variable references should be expanded. Typically FALSE unless we're in a WML document. Since this
	 * method doesn't take a hld_profile no expansion can be done so use the other CreateText.
	 */
	static HTML_Element* CreateText(const uni_char* text, unsigned text_len, BOOL resolve_entities, BOOL is_cdata, BOOL expand_wml_vars)
	{
		OP_ASSERT(!expand_wml_vars);
		return HTML_Element::CreateText(NULL, text, text_len, resolve_entities, is_cdata, expand_wml_vars);
	}

	/**
	 * Used to do all the preprocessing steps needed by the raw attribute data from the
	 * parser in order to make a valid attribute value.
	 * @param hae[in] The struct holding the raw attribute data. All entities must have been replaced in the hae->value member before calling this function.
	 * @param[in] may_steal_hae_value If this is TRUE hae->value can be reused internally and set to NULL in the struct. If it's not set to NULL then it wasn't "stolen". The hae_value must be a null terminated string with the length of hae->value_len if this is TRUE.
	 * @param value[out] The returned attribute value
	 * @param item_type[out] The returned attribute type
	 * @param need_free[out] Will be set to TRUE if the value needs to be freed when it is removed
	 * @param is_event[out] Will be set to TRUE if the attribute is an event handler
	 * @param ha_list[in,out] Contains the array of the raw data for the other attributes. Can be NULL
	 * @param attr_index[in] Will be used to insert attributes directly into the element.
	 *  Contains the new index if it is used.
	 * @returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    OP_STATUS       ConstructAttrVal(HLDocProfile* hld_profile, HtmlAttrEntry* hae,
						BOOL may_steal_hae_value,
						void*& value, ItemType& item_type, BOOL& need_free, BOOL &is_event,
						HtmlAttrEntry* ha_list = NULL, unsigned *attr_index = NULL);

	/**
	 * Used to recursively clean up the element and its children. The cleaning
	 * removes layout structures and references to the elements from the rest
	 * of the code.
	 * @param[in] going_to_delete TRUE if the element will be deleted and not just removed
	 * from the document. You are always guaranteed to eventually get a call to Clean()
	 * with this flag set to TRUE, but not to get a call with this set to FALSE. See
	 * modules/logdoc/documentation/elementref.html for details.
	 * @returns TRUE if there are no other references to this element and it can be Free()'ed
	 */
	BOOL            Clean(const DocumentContext &context, BOOL going_to_delete = TRUE);

	/**
	 * @returns Used to delete an element if it has been Clean()'ed correctly
	 */
	void			Free(const DocumentContext &context);

	/**
	 * @deprecated Please use Clean(const DocumentContext &) instead.
	 * Note: calling with a document (assuming it is the correct one) is always safe;
	 * calling without one is almost always risky.
	 */
	BOOL			DEPRECATED(Clean(int *ptr = NULL));
	/**
	 * @deprecated Please use Free(const DocumentContext &) instead.
	 * Note: calling with a document (assuming it is the correct one) is always safe;
	 * calling without one is almost always risky.
	 */
	void			DEPRECATED(Free(int *ptr = NULL));

	/**
	 * Used to recursively clean up cached layout information for
	 * the the element and its children. This is used in inactive trees
	 * to reduce memory usage.
	 *
	 * @see Clean()
	 */
	void            FreeLayout(const DocumentContext &context);

	/**
	 * Will make a cloned subtree under this element of the subtree specified by src_elm.
	 * @param src_elm The root of the subtree to be cloned
	 * @param force_html Create elements with NS_IDX_HTML, that is, as if parsed by the
	 *   HTML parser, regardless of the source elements.
	 * @returns OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    OP_STATUS		DeepClone(HLDocProfile *hld_profile, HTML_Element *src_elm, BOOL force_html = FALSE);

	/**
	 * Used to serialize a subtree of HTML_Elements to a string of text. This should append
	 * the textual representation closest possible to what was in the original markup.
	 * @param tmp_buf The string representation will be appended to this buffer
	 * @param text_only Only the text of the text elements in the tree will be appended, and
	                    &lt;br&gt; elements are converted to newline
	                    characters (a la the HTMLElement.innerText behaviour of
	                    WebKit and old Operas).
	 * @param include_this If TRUE the tag of this element will be appended, otherwise not
	 * @param root Used to calculate the real parents of an element in an last_descendant structure
	 * @param is_xml Set to TRUE if the serialized version should be valid XML
	 *
	 * Will LEAVE with OpStatus::ERR_NO_MEMORY if allocation fails
	 */
    void			AppendEntireContentAsStringL(TempBuffer *tmp_buf, BOOL text_only, BOOL include_this, HTML_Element *root = NULL, BOOL is_xml = FALSE);
	/**
	 * As the one above only returning a status value
	 */
    OP_STATUS		AppendEntireContentAsString(TempBuffer *tmp_buf, BOOL text_only, BOOL include_this, BOOL is_xml = FALSE);

	/** @returns TRUE if this element has a dynamic pseudo class */
	BOOL HasDynamicPseudo() const { return packed2.check_dynamic; }
	/** @param the_truth Set to TRUE if this element has a dynamic pseudo class */
	void SetHasDynamicPseudo(BOOL the_truth) { packed2.check_dynamic = !!the_truth; }
	/** Set the check_dynamic flag and/or the check-for-pseudo element bits
		based on the passed set of pseudo classes and elements.

		@param pseudo_bits An or'ed set of CSSPseudoClassType values. */
	void SetCheckForPseudo(unsigned int pseudo_bits);
	/** Before reloading CSS properties for an element, reset the check bits
		for pseudo elements so that pseudo element bits are not kept when the
		pseudo selectors no longer apply. The check bits will be correctly
		updated during CSS property loading. */
	void ResetCheckForPseudoElm();

	/** No idea, ask Jens */
	void SetSharedCss() { packed2.shared_css = 1; }
	/** No idea, ask Jens */
	void UnshareCssProperties();
	/** Will delete the CSS properties of the element */
	void DeleteCssProperties();

	/** Sets the flag that indicates whether this element is part of a text selection */
	void SetIsInSelection(BOOL val) { packed2.is_in_selection = val ? 1 : 0; }
	/** @returns TRUE if this element is part of a text selection */
	BOOL IsInSelection() const   { return packed2.is_in_selection; }
	/** @returns TRUE if this element is hovered */
	BOOL IsHovered() const   { return packed2.hovered; }
	/** @returns TRUE if this element is focused */
	BOOL IsFocused() const   { return packed2.focused; }
	/** @returns TRUE if this element is activated */
	BOOL IsActivated() const { return packed2.activated; }

	/** @returns TRUE if the attribute is float instead of integer for this element type.
	 * @param The attribute */
	BOOL IsNumericAttributeFloat(int attr);

#ifdef WEB_TURBO_MODE
	/** Sets the flag indicating that this is an HE_OBJECT that we have found to embed a plugin */
	void SetObjectIsEmbed() { packed2.object_is_embed = TRUE; }
#endif // WEB_TURBO_MODE

	/** Mark that we need to update pseudo element selectors when this
		element is closed or when children are added or removed,
		because we have an :empty selector match for this element, or
		we match :nth-last-child, :last-child, etc. for a child
		element of this element. */
	void SetUpdatePseudoElm() { packed2.update_pseudo_element = 1; }

	/** @return TRUE if this element and its children need update of
		pseudo element selectors when this element is closed or when
		children are added or removed. */
	BOOL GetUpdatePseudoElm() const { return packed2.update_pseudo_element; }

	/** Don't really know, ask Rune */
	void SetCurrentDynamicPseudoClass( unsigned int flags );
	/** Don't really know, ask Rune */
	unsigned int GetCurrentDynamicPseudoClass();

	/** Don't really know, ask Rune */
	BOOL IsDefaultFormElement(FramesDocument* frames_doc);
	/** Don't really know, ask Rune */
	BOOL IsInvalidFormElement(FramesDocument* frames_doc);
	/** Don't really know, ask Rune */
	BOOL IsInRangeFormElement(FramesDocument* frames_doc);
	/** Don't really know, ask Rune */
	BOOL IsRequiredFormElement(FramesDocument* frames_doc);
	/** Don't really know, ask Rune */
	BOOL IsReadOnlyFormElement(FramesDocument* frames_doc);

	/** Used to set if a form element is in the prefocused state */
	void SetIsPreFocused(BOOL prefocused) { SetSpecialBoolAttr(ATTR_PREFOCUSED, prefocused, SpecialNs::NS_LOGDOC); }
	/** @returns TRUE if the form element is in the prefocused state */
	BOOL IsPreFocused() const;

	/** @returns Returns TRUE if this element is any kind of link. */
	BOOL			IsAnchorElement(FramesDocument *frames_doc) { return !GetAnchor_URL(frames_doc).IsEmpty(); }
	BOOL			IsStyleElement();
	BOOL			IsScriptElement();
	BOOL			IsLinkElement();
	BOOL			IsCssImport();

	/** @returns TRUE if the element is represented by a widget which may contain a caret (e.g. is a textarea or a text input). */
	BOOL			IsWidgetWithCaret();

#ifdef DRAG_SUPPORT
	/** @returns TRUE if the element is represented by a widget which may contain a selection which may be dragged. */
	BOOL			IsWidgetWithDraggableSelection();

	/** @returns TRUE if the element is represented by a widget which may accept a drop. */
	BOOL			IsWidgetAcceptingDrop();
#endif // DRAG_SUPPORT

	/**
	 * Decides if an element is focusable. This controls whether an
	 * element has the :focus pseudo class, can be focused with the DOM2HTML focus() method
	 * or can be focused with mousedown.
	 *
	 * The definition of focusable might vary between languages (HTML, SVG, WML, ...).
	 *
	 * The spec for part of this is HTML5 + Anne vKs spec at
	 * https://homes.oslo.opera.com/annevk/specs/action-based-navigation/#focusable
	 *
	 * @param document The document this element lives in (not NULL).
	 *
	 * @returns TRUE if this element is focusable.
	 */
	BOOL			IsFocusable(FramesDocument *document);

	/** @returns the namespace index of the attribute at index i */
    int				GetAttrNs(int i) const { return data.attrs[i].GetNsIdx(); }
	/** @returns the namespace resolved relative to the element of the attribute at index i */
    int				GetResolvedAttrNs(int i) const;
    /** Empty the list of source attributes. Example of use: when link changes its href.*/
    void			EmptySrcListAttr();

	/**
	 * Get the url referring to the script.
	 * @param root_url, the document's URL.
	 */
	URL*			GetScriptURL(URL& root_url, LogicalDocument *logdoc = NULL);

	/** Mostly does some media type and CSS mode magic before calling LoadStyle to
	 *  parse the style declarations of this STYLE element.
	 *  @return OpStatus::OK or what LoadStyle() returns.
	 */
	OP_STATUS		ProcessCSS(HLDocProfile *hld_profile);

	/** Called to handle the different types of operations triggered when a HTML META element
	 *  is inserted into or removed from the logical tree.
	 *
	 *  @param context The relevant pointers to identify the document of this element/operation.
	 *  @param parent_elm The parent of the inserted/removed element.
	 *  @param added TRUE if this element is added to the document, otherwise FALSE.
	 *  @returns FALSE if the character set has been changed and we need to reparse */
	BOOL			CheckMetaElement(const DocumentContext& context, HTML_Element* parent_elm, BOOL added);

	/**
	 * This function parses the http-equiv refresh meta content attribute,
	 * and sets the timer which will refresh the document.
	 * @param hld_profile  The HLDocProfile of the document the element belongs to
	 * @param content  The value of the content attribute of a meta element with a http-equiv attribute of type refresh
	 */
	void			HandleMetaRefresh(HLDocProfile* hld_profile, const uni_char* content);

	/** Used to construct a ISINDEX control. But who cares */
	void			MakeIsindex(HLDocProfile* hld_profile, const uni_char* prompt);

	TextData*		GetTextData() { return (Type() == HE_TEXT) ? data.text : NULL; }
	/** Deletes the TextData of a text element. Use with care */
	void			DeleteTextData();

	/** Used to check the type of the element. Use only when you already know the namespace
	 *  @returns the type code of the element*/
	Markup::Type	Type() const { return static_cast<Markup::Type>(packed1.type); }
	/** Used to check the type and namespace of the element.
	 *  @returns TRUE if both the type and namespace matches this element */
	BOOL			IsMatchingType(int type, NS_Type ns) const { return ((int)packed1.type) == type && GetNsType() == ns; }

	/** @returns the namespace of the element */
	NS_Type         GetNsType() const { return g_ns_manager->GetNsTypeAt(GetNsIdx()); }
	/** @returns the namespace index of the element */
    int             GetNsIdx() const { return (int)packed1.ns_idx; }
	/** Used to set the namespace index */
    void            SetNsIdx(int ns_idx) { packed1.ns_idx = (unsigned int)ns_idx; }
	/** Used to find the namespace index of an attribute resolved relative to the element */
	int				ResolveNsIdx(int ns_idx) const { return ns_idx == NS_IDX_DEFAULT ? GetNsIdx() : ns_idx; }

	/** @returns TRUE if the element is of a type that isn't supposed to be laid out */
    inline BOOL		HasNoLayout() { return Type() > Markup::HTE_LAST_WITH_LAYOUT && GetInserted() != HE_INSERTED_BY_LAYOUT; }

	/** Will traverse to the top of the tree and get the LogicalDocument from the
	 *  root element. If the element is not in the tree it will return NULL
	 *  @returns The logical document the element belongs to. */
	LogicalDocument*	GetLogicalDocument() const;

#ifdef _DEBUG
	void			DumpDebugTree(int level = 0);
#endif

	/**
	 * Used to add or change an attribute on an element.
	 * @param attr The attribute code for the attribute to add
	 * @param name The name of the attribute. Will only be used if attr == ATTR_XML
	 * @param ns_idx Namespace index of the attribute
	 * @param value The string representation of the value of the new attribute
	 * @param value_length The length of the value string
	 * @param thread The origin ES thread or NULL if not from a script
	 * @param case_sensitive If TRUE, name will be handled case sensitively.
	 * @param is_id Set to TRUE if the attribute is an unique id
	 * @param is_specified Set to TRUE if explicitly specified in the markup
	 * @param attribute_may_exist Set to FALSE if known that the attribute does not exist.
	 * @param at_known_index If index of pre-existing attribute is known, set to its non-negative value (saves recomputing it.)
	 */
	OP_STATUS		SetAttribute(const DocumentContext &context, Markup::AttrType attr, const uni_char *name, int ns_idx, const uni_char *value, unsigned value_length, ES_Thread *thread, BOOL case_sensitive, BOOL is_id = FALSE, BOOL is_specified = TRUE);

#ifdef DOCUMENT_EDIT_SUPPORT
	/** Deprecated: use SetAttribute with ns_idx==NS_IDX_DEFAULT instead.*/
	OP_STATUS		DEPRECATED(SetStringHtmlAttribute(FramesDocument *frames_doc, ES_Thread *thread, Markup::AttrType attr, const uni_char *value));
	/** Called from HandleAttributeChange and DOMRemoveFromParent. */
	void			DisableContentEditable(FramesDocument *frames_doc);
#endif // DOCUMENT_EDIT_SUPPORT

	/** @returns the number of attributes specified in markup amd default attributes */
	int				GetAttributeCount();
	/**
	 * Returns the name of an attribute at the given position
	 * @param[IN] index The index of the attribute
	 * @param[IN] buffer The name of the attribute will be appended to this buffer if any case transformations are needed
	 * @param[OUT] name The name of the attribute will be returned in this parameter
	 * @param[OUT] ns_idx The namespace index of the attribute is returned.
	 * @param[OUT] specified This param is set to TRUE if the attribute is explicitly specified in the markup
	 * @param[OUT] id This param is set to TRUE if the attribute is a unique identifier
	 * @returns OpStatus::ERR_NO_MEMORY if we run out of memory
	 */
	OP_STATUS		GetAttributeName(FramesDocument *frames_doc, int index, TempBuffer *buffer, const uni_char *&name, int &ns_idx, BOOL *specified = NULL, BOOL *id = NULL);
	/**
	 * Returns the value of an attribute with the given attribute code or name
	 * @param attr The attribute code for the attribute to find or ATTR_XML if searching by name
	 * @param name The name of the attribute to search for. To use this attr must be ATTR_XML otherwise it is ignored.
	 * @param case_sensitive If TRUE, name will be handled case sensitively.
	 * @param ns_idx The namespace index of the attribute to search for.
	 * @param buffer The value of the attribute will be appended to this buffer if any case transformations are needed
	 * @param resolve_urls If set to TRUE URL attributes will be resolved to absolute addresses
	 * @param at_known_index The index of the attribute, if already known.
	 * @returns A pointer to the value of the attribute if found, otherwise NULL.
	 */
	const uni_char *GetAttribute(FramesDocument *frames_doc, int attr, const uni_char *name, int ns_idx, BOOL case_sensitive, TempBuffer *buffer, BOOL resolve_urls, int at_known_index = -1);

	/**
	 * Checks whether the element has an attribute with the given name. This is
	 * similar to HasAttr(), but takes a string representation of the name, and
	 * can be used to find HA_XML attributes as well.
	 * @param attr_name The name of the attribute to search for.
	 * @param ns_idx The namespace index of the attribute to search for.
	 * @returns TRUE if the element has an attribute with the given name in the given namespace, otherwise FALSE.
	 */
	BOOL			HasAttribute(const uni_char* attr_name, int ns_idx);

	/**
	 * Compares two attributes with the given type to check if they represent
	 * the same value
	 *
	 * @param attr            Attribute ID. If this is ATTR_XML, then this is used
	 *                        to know if the value holds the attribute name and then
	 *                        the value.
	 * @param attr_item_type  Attribute type.
	 * @param left            One of the attribute values.
	 * @param right           The other attribute value.
	 */
	static BOOL AreAttributesEqual(short attr, ItemType attr_item_type, void *left, void *right);

	enum ValueModificationType
	{
		// Must be same order as the DOM_MutationListener::ValueModificationType type.
		MODIFICATION_REPLACING_ALL,
		MODIFICATION_DELETING,
		MODIFICATION_INSERTING,
		MODIFICATION_REPLACING,
		MODIFICATION_SPLITTING
	};

	/**
	 * Called when we insert an element into the tree.or take one out
	 * @param parent The element under which the new element is inserted
	 * @param child The newly inserted element
	 * @param thread The ES thread of the script that did this or NULL if not from script
	 * @param added Must be TRUE if an element is inserted into the tree
	 */
	OP_STATUS			HandleDocumentTreeChange(const DocumentContext &context, HTML_Element *parent, HTML_Element *child, ES_Thread *thread, BOOL added);
	/**
	 * Called when we insert a text element into the tree.or take one out
	 * @param thread The ES thread of the script that did this or NULL if not from script
	 * @param added Must be TRUE if an element is inserted into the tree
	 * @param update_pseudo_elm If FALSE, do not call LayoutWorkplace::ApplyPropertyChanges()
	 *                          even if GetUpdatePseudoElm() returns TRUE.  Typically used if
	 *                          the caller already called it, to avoid duplicate work.
	 */
	OP_STATUS			HandleCharacterDataChange(const DocumentContext &context, ES_Thread *thread, BOOL added, BOOL update_pseudo_elm = TRUE);

	/**
	 * Called before an attribute has been modified.
	 *
	 * @returns OpStatus::OK on success, OpStatus::ERR_NO_MEMORY in case of OOM and OpStatus::ERR when a script is not allowed to change an attribute.
	 */
	OP_STATUS			BeforeAttributeChange(const DocumentContext &context, ES_Thread *thread, int attr_idx, short attr, int ns_idx, BOOL is_same_value);

	/**
	 * Called by HandleAttributeChange to update DOM collections when an attribute has changed
	 */
	void				UpdateCollectionStatus(const DocumentContext &context, short attr, NS_Type ns, BOOL in_document);

	/**
	 * Called after an attribute has been set or removed, but only if was changed from the previous value.
	 *
	 * @param attr_name A copy of the attribute name when an ATTR_XML attribute is removed. NULL otherwise, or if a copy can't be created due to OOM.
	 */
	OP_STATUS			HandleAttributeChange(const DocumentContext &context, ES_Thread *thread, int attr_idx, Markup::AttrType attr, int ns_idx, BOOL was_removed = FALSE, const uni_char* attr_name = NULL);

	/**
	 * Called after an attribute has been set every time BeforeAttributeChange has been called.
	 */
	OP_STATUS			AfterAttributeChange(const DocumentContext &context, ES_Thread *thread, int attr_idx, short attr, int ns_idx, BOOL is_same_value);

	/** Sets the checked state for radiobuttons and checkboxes. Does nothing for other elements. */
	void				SetBoolFormValue(FramesDocument *frames_doc, BOOL value);

	DOM_Object*			GetESElement() { return exo_object; }
	void				SetESElement(DOM_Object* node) { exo_object = node; }

	/** @returns Namespace index of the given URI and prefix. Either can be NULL */
	int					DOMGetNamespaceIndex(DOM_Environment *environment, const uni_char *ns_uri, const uni_char *ns_prefix = NULL);
	/** Used to find namespace data for a namespace index.
	 *  @param[IN] ns_idx The index into the namespace table.
	 *	@param[OUT] ns_uri Will be set to the URI of the namespace.
	 *	@param[OUT] ns_prefix Will be set to the prefix of the namespace.
	 *	@returns FALSE if element is in default namespace and no data is returned. */
	BOOL				DOMGetNamespaceData(DOM_Environment *environment, int ns_idx, const uni_char *&ns_uri, const uni_char *&ns_prefix);

	/** @returns The namespace index matching ns_prefix in the current scope */
	int					FindNamespaceIndex(const uni_char *ns_prefix);

	/** @param ns_uri If it's the empty string or NULL, then the default namespace prefix is returned if any
	 *  @returns The namespace prefix matching the namespace URI ns_uri in the current scope */
	const uni_char*		DOMLookupNamespacePrefix(DOM_Environment *environment, const uni_char *ns_uri);

	/** @param ns_prefix If it's the empty string or NULL, then the default namespace uri is returned if any
	 *  @returns The namespace URI matching the namespace prefix ns_prefix in the current scope. */
	const uni_char*		DOMLookupNamespaceURI(DOM_Environment *environment, const uni_char *ns_prefix);

	/** Returns the name of the element.
	 *	@param buffer Buffer where the element name will be appended as uppercase, if needed.
	 *	@param[OUT] ns_idx Set to the namespace index of the element.
	 *  @param[IN] uppercase If TRUE, the returned name will be all uppercase letters if the element is an HTML element.
	 *	@returns NULL on OOM, otherwise reference to the tag name. */
	const uni_char*		DOMGetElementName(DOM_Environment *environment, TempBuffer *buffer, int &ns_idx, BOOL uppercase);

	/** Checks if the element has an attribute.
	 *  @param attr The numeric code of the attribute. ATTR_XML if name is to be used.
	 *	@param name Name of the attribute to be found. Only if attr == ATTR_XML.
	 *	@param found_at_index If attribute exists, record at what index.
	 *	@param ns_idx Namespace index of the attribute. NS_IDX_ANY_NAMESPACE if namespace is insignificant.
	 *	@param case_sensitive If TRUE, the search will be case sensitive.
	 *	@param specified If set to TRUE the function will only search attributes specified in the markup.
	 *  @returns TRUE if the requested attribute exists on the element. */
	BOOL				DOMHasAttribute(DOM_Environment *environment, int attr, const uni_char *name, int ns_idx, BOOL case_sensitive, int &found_at_index, BOOL specified = FALSE);
	BOOL				DEPRECATED(DOMHasAttribute(DOM_Environment *environment, const uni_char *name, int ns_idx, BOOL specified = FALSE));
	/**< @deprecated Use the other DOMHasAttribute function. */

	/** @returns The number of non-internal attributes on this element */
	int					DOMGetAttributeCount();
	/** Returns the name of the attribute.
	 *  @param index Index into the attribute array.
	 *  @param buffer Buffer where the attribute name will be appended as uppercase if needed. Can be NULL
	 *	@param[OUT] name Set to a pointer to the name or NULL if no name is available.
	 *	@param[OUT] ns_idx Set to the namespace index of the element. */
	void				DOMGetAttributeName(DOM_Environment *environment, int index, TempBuffer *buffer, const uni_char *&name, int &ns_idx);
	/** @returns Namespace index of the attribute with name name */
	int					DOMGetAttributeNamespaceIndex(DOM_Environment *environment, const uni_char *name, int ns_idx = NS_IDX_ANY_NAMESPACE);

	/** Gets the value of a named attribute.
	 *  @param attr Numeric code of the attribute. ATTR_XML if name is to be used.
	 *  @param name Name of the attribute.
	 *  @param case_sensitive If TRUE, name will be handled case sensitively.
	 *  @param resolve_urls If TRUE any URL attribute will be resolved to an absolute URL.
	 *  @param at_known_index The index of the attribute, if known.
	 *  @returns Value of the attribute */
	const uni_char*		DOMGetAttribute(DOM_Environment *environment, int attr, const uni_char *name, int ns_idx, BOOL case_sensitive, BOOL resolve_urls = TRUE, int at_known_index = -1);

	/** Gets the numeric value of attribute 'attr', or 'name' if 'attr' is ATTR_XML.
	 *  @param attr Numeric code of the attribute. ATTR_XML if 'name' is to be used.
	 *  @param name Name of the attribute.
	 *  @param ns_idx Namespace index of the attribute. NS_IDX_ANY_NAMESPACE
	 *         if namespace is insignificant.
	 *  @param [out]absent Result set to TRUE if attribute value present, FALSE
	 *         if absent.
	 *  @returns Value of the attribute; 0 if attribute is absent. */
	double				DOMGetNumericAttribute(DOM_Environment *environment, int attr, const uni_char *name, int ns_idx, BOOL &absent);

	/** Gets the Boolean value of attribute 'attr', or 'name' if 'attr' is ATTR_XML.
	 *  @param attr Numeric code of the attribute. ATTR_XML if 'name' is to be used.
	 *  @param name Name of the attribute.
	 *  @param ns_idx Namespace index of the attribute. NS_IDX_ANY_NAMESPACE
	 *         if namespace is insignificant.
	 *  @returns Boolean value of the attribute; FALSE if attribute is absent. */
	BOOL				DOMGetBooleanAttribute(DOM_Environment *environment, int attr, const uni_char *name, int ns_idx);

	OP_STATUS			DOMSetAttribute(DOM_Environment *environment, Markup::AttrType attr, const uni_char *name, int ns_idx, const uni_char *value, unsigned value_length, BOOL case_sensitive);
	/**< Set attribute.  The value is given in the form of a string, but this function
	     is used to set any type of attributes, not just those that are plain strings. */
	OP_STATUS			DOMSetNumericAttribute(DOM_Environment *environment, Markup::AttrType attr, const uni_char *name, int ns_idx, double value);
	/**< Typically used instead of DOMSetAttribute for properties of type "long" or such
	     in DOM interfaces, that is, when the value will be supplied by the script as a
	     number.  Doesn't necessarily mean it will be stored as ITEM_TYPE_NUM, just that
	     it is the attribute's data type according to some DOM specification. */
	OP_STATUS			DOMSetBooleanAttribute(DOM_Environment *environment, Markup::AttrType attr, const uni_char *name, int ns_idx, BOOL value);
	/**< Typically used instead of DOMSetAttribute for properties of type "boolean" in
	     DOM interfaces, that is, when the value will be supplied by the script as a
	     boolean.  Doesn't necessarily mean it will be stored as ITEM_TYPE_BOOL, just
	     that it is the attribute's data type according to some DOM specification. */

	OP_STATUS			DOMRemoveAttribute(DOM_Environment *environment, const uni_char *name, int ns_idx, BOOL case_sensitive);
	/**< Called to remove a named attribute from an element.

	     @param environment The DOM environment of the element's current document.
	     @param name A null terminated string representing the name of the attribute.
	     @param ns_idx Set to the namespace index of the attribute.
	     @param case_sensitive Set to TRUE if the attribute name should exactly
	     match the case of the string during lookup.
	     @returns Normal OOM values. */

	BOOL				DOMGetImageSize(DOM_Environment *environment, unsigned& width, unsigned& height);
	/**< Extracts the intrinsic image size (only to be used on image elements) to be returned as
	     dom properties naturalWidth and naturalHeight.

	     @param environment The DOM environment of the element's current document.
	     @param[out] width Will be set to the image width if the width is available (if the function returns TRUE)
	     @param[out] height Will be set to the image height if the width is available (if the function returns TRUE)
	     @returns TRUE if width and height were available, FALSE otherwise. */

	void				DOMMoveToOtherDocument(DOM_Environment *environment, DOM_Environment *new_environment);
	/**< Called when an element is moved from one document (as in FramesDocument, not
	     DOM_Document) to another via Document.adoptNode.  Resets whatever links the
	     element might have to its old document (for instance via HEListElm:s stored as
	     attributes.)

	     @param environment The DOM environment of the element's current document.
	     @param new_environment The DOM environment of the new document. */

	OP_BOOLEAN			DOMGetDataSrcContents(DOM_Environment *environment, TempBuffer *buffer);
	/**< Used to retrieve the content loaded from a DataSrc held by this element.
	     Can be the contents of an external script or external stylesheet.
	     @param environment The element's environment.
	     @param buffer Buffer to which the contents are appended.
	     @return OpStatus::IS_TRUE if linked content was found, IS_FALSE if no content was found,
	             OpStatus::ERR_NO_MEMORY if OOM. */

	OP_STATUS			DOMGetContents(DOM_Environment *environment, TempBuffer *buffer, BOOL just_childrens_text = FALSE);
	/**< Used to retrieve the text contents of nodes.  For Text, Comment, CDATASection and
	     ProcessingInstruction nodes returns the direct contents, for Element nodes returns
	     the concatenated contents of all child nodes.
	     @param environment The element's environment.
	     @param buffer Buffer to which the contents are appended.
	     @param just_childrens_text bool telling whether to retrieve all content
	                                or just text content from children
	     @return OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	const uni_char*		DOMGetContentsString(DOM_Environment *environment, TempBuffer *buffer, BOOL just_childrens_text = FALSE);
	/**< Used to retrieve the text contents of nodes.  For Text, Comment, CDATASection and
	     ProcessingInstruction nodes returns the direct contents, for Element nodes returns
	     the concatenated contents of all child nodes.
	     @param environment The element's environment.
	     @param buffer Buffer which may or may not be used to construct the result string.
	     @param just_childrens_text bool telling whether to retrieve all content
	                                or just text content from children
	     @return NULL on OOM, the empty string if no content. */

	OP_STATUS			DOMSetContents(DOM_Environment *environment, const uni_char *contents, HTML_Element::ValueModificationType modification_type = MODIFICATION_REPLACING_ALL, unsigned offset = 0, unsigned length1 = 0, unsigned length2 = 0);
	/**< Used to set the contents of Text, Comment, CDATASection and
	 * ProcessingInstruction nodes.
	 *
	 * @param[in] modification_type What kind of modification it
	 * does. This is used to perform intelligent changes of for
	 * instance selection. Can be MODIFICATION_REPLACING,
	 * MODIFICATION_DELETING, MODIFICATION_INSERTING,
	 * MODIFICATION_REPLACING_ALL or MODIFICATION_SPLITTING.
	 *
	 * @param[in] offset If MODIFICATION_REPLACING, it's the offset of the replaced
	 * text. length1 is the length of the replaced text and length2 is
	 * the length of the text that was inserted.  <p>If MODIFICATION_DELETING, the
	 * offset of the deleted text and length1 is the length of the
	 * inserted text.  <p>If MODIFICATION_INSERTING, the offset of the inserted
	 * text and length1 is the length of the inserted text.  <p>If
	 * MODIFICATION_REPLACING_ALL, the whole block is assumed to be replaced by a new
	 * block.
	 * If MODIFICATION_SPLITTING then then the block is split at offset, and the data after
	 * offset will be put in a new text element that can be found with Suc(). The expected
	 * behaviour on ranges and selections is that any boundary point/selection point
	 * after the split point is modified to point to the Suc() element.
	 *
	 * @param[in] length1 See the offset parameter.
	 *
	 * @param[in] length2 See the offset parameter.
	 */

	OP_STATUS			DOMSelectContents(DOM_Environment *environment);
	/**< Used to select the contents of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	OP_STATUS			DOMGetFormValue(DOM_Environment *environment, TempBuffer *buffer, BOOL with_crlf);
	/**< Used to get the current value of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */
	OP_STATUS			DOMSetFormValue(DOM_Environment *environment, const uni_char *value);
	/**< Used to set the current value of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	BOOL				DOMGetBoolFormValue(DOM_Environment *environment);
	/**< Used to get the current value of a radio or checkbox element. */
	void				DOMSetBoolFormValue(DOM_Environment *environment, BOOL value);
	/**< Used to set the current value of a radio or checkbox element. */

	OP_STATUS			DOMStepUpDownFormValue(DOM_Environment *environment, int step_count);
	/**< Used to set the current value of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */
	OP_STATUS			DOMGetDefaultOutputValue(DOM_Environment *environment, TempBuffer *buffer);
	/**< Used to get the default value of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */
	OP_STATUS			DOMSetDefaultOutputValue(DOM_Environment *environment, const uni_char *value);
	/**< Used to set the default value of a form control.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	OP_STATUS			DOMGetSelectedIndex(DOM_Environment *environment, int &index);
	OP_STATUS			DOMSetSelectedIndex(DOM_Environment *environment, int index);
	/** Used to get or set the selected index of a select element.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	OP_STATUS			DOMGetOptionSelected(DOM_Environment *environment, int index, BOOL &selected);
	OP_STATUS			DOMSetOptionSelected(DOM_Environment *environment, int index, BOOL selected);
	/** Used to get or set the selected state of an option in a select element.  Returns OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

	/**
	 * Locks/unlocks select element updates.
	 * It should be called to reduce unneccessary updates of this <select> when doing
	 * multiple DOM operations which should be treated as one e.g. replacing a child is
	 * a one operation consisting of removing a child and inserting another.
	 *
	 * @param[in] lock If TRUE all the updates to a select element would be ignored untill
	 * called with locked = FALSE. Calling with locked = FALSE may triger an immediate update
	 * of this <select>.
	 */
	void				DOMSelectUpdateLock(BOOL lock);

	/**
	 * Get current selection of a form control in the out varibles
	 * or 0, 0, SELECTION_NONE if there is no selection.
	 *
	 * @param environment The element's environment.
	 * @param start The offset of the first selected character.
	 * @param stop The offset of the character after the last
	 * selected character. stop == start means that no
	 * character is selected.
	 * @param direction The direction of the selection.
	 */
	void				DOMGetSelection(DOM_Environment *environment, int &start, int &end, SELECTION_DIRECTION& direction);

	/**
	 * Get current selection of a form control in the out varibles
	 * or 0, 0 if there is no selection.
	 *
	 * @param environment The element's environment.
	 * @param start The offset of the first selected character.
	 * @param stop The offset of the character after the last
	 * selected character. stop == start means that no character is selected.
	 */
	void				DOMGetSelection(DOM_Environment *environment, int &start, int &end) { SELECTION_DIRECTION direction; DOMGetSelection(environment, start, end, direction); }

	/**
	 * Set current selection of a form control.
	 *
	 * @param environment The element's environment.
	 * @param start The offset of the first selected character.
	 * @param stop The offset of the character after the last selected
	 * character. stop == start means that no character is selected.
	 * @param direction The direction of the selection.
	 */
	void				DOMSetSelection(DOM_Environment *environment, int start, int end, SELECTION_DIRECTION direction = SELECTION_DIRECTION_DEFAULT);

	/** Used for getting caret position in form controls */
	int					DOMGetCaretPosition(DOM_Environment *environment);
	/** Used for setting caret position in form controls */
	void				DOMSetCaretPosition(DOM_Environment *environment, int position);

	const uni_char*		DOMGetPITarget(DOM_Environment *environment);
	/** Used to get the target of a ProcessingInstruction node. */

	OP_STATUS			DOMGetInlineStyle(CSS_DOMStyleDeclaration *&styledeclaration, DOM_Environment *environment);
	OP_STATUS			DOMGetComputedStyle(CSS_DOMStyleDeclaration *&styledeclaration, DOM_Environment *environment, const uni_char *pseudo_class);
#ifdef CURRENT_STYLE_SUPPORT
	OP_STATUS			DOMGetCurrentStyle(CSS_DOMStyleDeclaration *&styledeclaration, DOM_Environment *environment);
#endif // CURRENT_STYLE_SUPPORT

	/**
	 * Used for getting DOM environment for the frame created by this element
	 *  Returns OpStatus::OK except for serious errors. frame_environment
	 * becoming NULL is not a serious error so the calling code has to
	 * handle that.
	 *
	 * @param[out] frame_environment The environment for the frame. Is a wrapper
	 * environment that will change its content depending on what the frame contains
	 * and exists even before the frame has loaded anything.
	 *
	 * @param[out] frame_frames_doc The current document in the frame if any. Might
	 * be NULL if the frame doesn't yet/currently contain a document.
	 *
	 * @param[in] environment The environment of this element.
	 */
	OP_STATUS			DOMGetFrameProxyEnvironment(DOM_ProxyEnvironment *&frame_environment, FramesDocument*& frame_frames_doc, DOM_Environment *environment);

	BOOL				DOMElementLoaded(DOM_Environment *environment);
	/**< Returns FALSE if this element has an associated external resource that hasn't been loaded yet. */

	BOOL				DOMGetStylesheetDisabled(DOM_Environment *environment);
	/**< For LINK and STYLE, returns TRUE if the stylesheet is disabled (isn't applied but could be.) */
	OP_STATUS			DOMSetStylesheetDisabled(DOM_Environment *environment, BOOL value);
	/**< For LINK and STYLE, enable or disable the stylesheet. */
	OP_STATUS			SetStylesheetDisabled(FramesDocument *frames_doc, BOOL value);
	/**< Inner function for DOMSetStylesheetDisabled. */

	const uni_char*		DOMGetInputTypeString();
	/**< Returns the effective string for the type of a HE_INPUT or HE_BUTTON. Will not return NULL since it's static strings. */


#ifdef _PLUGIN_SUPPORT_
	OpNS4Plugin*		DOMGetNS4Plugin();
#endif // _PLUGIN_SUPPORT_

	OP_STATUS			DOMGetOffsetParent(DOM_Environment *environment, HTML_Element *&parent);
	/**< Used to retrieve the value of the DOM property offsetParent. */

	enum DOMPositionAndSizeType { DOM_PS_OFFSET, DOM_PS_CLIENT,
		/** Returns values matching scrollLeft, scrollWidth and similar properties */
		DOM_PS_SCROLL,

		/** Return values corresponding to the content box. These are
		    relative the viewport, not the document. */
		DOM_PS_CONTENT,

		/** Return values corresponding to the border box. These are
		    relative the viewport, not the document. */
		DOM_PS_BORDER
	};

	OP_STATUS			DOMGetPositionAndSize(DOM_Environment *environment, DOMPositionAndSizeType type, int &left, int &top, int &width, int &height);
	/**< Used to retrieve the values of the properties {offset,client,scroll}{Left,Top,Width,Height}. */

	OP_STATUS			DOMGetPositionAndSizeList(DOM_Environment *environment, DOMPositionAndSizeType type, OpVector<RECT> &rect_vector);
	/**< Used to retrieve the list of rectangles from the elements layout box. */

	OP_STATUS			DOMGetXYPosition(DOM_Environment *environment, int &x, int &y);
	/**< Used to retrieve the position of this element but calculated the way firefox
	 *   calculates the x and y properties of HTMLImageElement:s.
	 *
	 *   More details inside the function.
	 */

	/************************************************************************
	 * Used to retrieve the list of surrounding rectangles from this element
	 * to the endpoint specified by end_elm.
	 * @param[in,out] bounding_rect If non-null, this will be filled the smallest
	 *	rectangle surrounding the entire range. Can not be used in conjunction
	 *	with rect_vector.
	 * @param[in,out] rect_vector If non-null, this will be filled with the
	 *	rectangles surrounding each of the sections of the range. Can not be
	 *	used in conjunction with bounding_rect.
	 * @param end_elm is the element in which the range ends.
	 * @param text_start_offset The offset in characters within the this element
	 *	to start the range from. Only for text elements. 0 indicates from the start
	 * @param text_end_offset The offset in characters where within the end_elm
	 *	the range will stop. -1 will use the entire content.
	 * @returns Normal OOM values.
	 */
	OP_STATUS			DOMGetClientRects(DOM_Environment *environment, RECT *bounding_rect, OpVector<RECT> *rect_vector, HTML_Element *end_elm, int text_start_offset = 0, int text_end_offset = -1);

	OP_STATUS			DOMSetPositionAndSize(DOM_Environment *environment, DOMPositionAndSizeType type, int *left, int *top, int *width, int *height);
	/**< Used to set the values of the properties {offset,client,scroll}{Left,Top,Width,Height}.  If
	     'left', 'top', 'width' and/or 'height' are non-NULL, that property is set. */

	OP_STATUS			DOMScrollIntoView(DOM_Environment *environment, BOOL align_to_top);
	/**< Used to scroll the element into view, either with the top aligned to the top of the
	     viewport (align_to_top==TRUE) or the bottom aligned with the bottom of the viewport. */

	OP_STATUS			DOMGetDistanceToRelative(DOM_Environment *environment, int &left, int &top, BOOL &relative_found);
	/**< Used to calculate the distance from this element to its nearest
	     relatively positioned parent, or the BODY element if no such
	     parent exists. */

	OP_STATUS			DOMGetPageInfo(DOM_Environment *environment, unsigned int& current_page, unsigned int& page_count);
	/**< Get current page number and page count. */

	OP_STATUS			DOMSetCurrentPage(DOM_Environment *environment, unsigned int current_page);
	/**< Set current page number. */

	OP_STATUS			DOMInsertChild(DOM_Environment *environment, HTML_Element *child, HTML_Element *reference);
	/**< Used to insert a child under this or before reference */
	OP_STATUS			DOMRemoveFromParent(DOM_Environment *environment);
	OP_STATUS			DOMRemoveAllChildren(DOM_Environment *environment);

	OP_STATUS			DOMSetInnerHTML(DOM_Environment *environment, const uni_char *html, int html_length, HTML_Element *actual_parent_element = NULL, BOOL use_xml_parser = FALSE);
	/**< Used for innerHTML, outerHTML and insertAdjacentHTML.  Parse 'html'
	     and insert the resulting elements as children of this element.

	     @param environment DOM Environment.
	     @param html HTML string to parse.
	     @param html_length The length of HTML string.
	     @param actual_parent_element The element the new content will be placed under (if not NULL).
	     @param use_xml_parser If TRUE, XML parser will be used to parse the string.


	     @return OpStatus::OK on success, OpStatus::ERR if the operation could not be
	             performed or OpStatus::ERR_NO_MEMORY on OOM. */

	void				DOMMarqueeStartStop(BOOL stop);
	/**< Used to (re)start a marguee animation.

		 @param stop If TRUE then the animation should stop, else it
		             should start. */

	static OP_STATUS	DOMCreateNullElement(HTML_Element *&element, DOM_Environment *environment);
	/**< Create an HTML_Element that will only be used as a placeholder for
	     child elements.  No attributes will be set on it and it will never
	     be inserted into a document.

	     @param element Set to the created element.
	     @param environment DOM environment.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
		         or OpStatus::ERR_NO_MEMORY on OOM. */

	static OP_STATUS	DOMCreateElement(HTML_Element *&element, DOM_Environment *environment, const uni_char *name, int ns_idx = NS_IDX_DEFAULT, BOOL case_sensitive = FALSE);
	/**< Create an HTML_Element object of the specified type.

	     @param element Set to the created element.
	     @param environment DOM environment.
	     @param name Element name.  Not NULL.
	     @param ns_idx Namespace index.
	     @param case_sensitive If TRUE the element will be created with the name having
	     exactly the same case as given in name. Otherwise it will be flattened according
	     to how HTML 5 specifies parsing element names.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
		         or OpStatus::ERR_NO_MEMORY on OOM. */

	static OP_STATUS	DOMCloneElement(HTML_Element *&element, DOM_Environment *environment, HTML_Element *prototype, BOOL deep);
	/**< Create an HTML_Element object that is a clone of 'prototype'.  If 'deep'
	     is TRUE, the prototype's children will be cloned as well.

	     @param element Set tot the created element.
	     @param environment DOM environment.
	     @param prototype Prototype element.
	     @param deep If TRUE, a deep cloning is performed.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
	             or OpStatus::ERR_NO_MEMORY on OOM. */

	static OP_BOOLEAN DOMAreEqualNodes(const HTML_Element *left_initial, HLDocProfile *left_hldoc, const HTML_Element *right_initial, HLDocProfile *right_hldoc, BOOL case_sensitive);
	/**< Compares both elements and their descendant trees according to the
		 DOM 3 Core isEqualNode function specification
		 http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isEqualNode

		 @param left_initial    element to compare. Cannot be NULL.
		 @param left_hldoc      HlDocProfile of left's document.
		 @param right_initial   element to compare. Cannot be NULL.
		 @param right_hldoc     HlDocProfile of right's document.
		 @param case_sensitive  use case sensitive comparison for tag and attribute names.

		 @returns ERR_NO_MEMORY if OOM, IS_TRUE is the nodes are indeed equal, IS_FALSE otherwise.
	 */

#ifdef DRAG_SUPPORT
	BOOL IsDraggable(FramesDocument* doc);
	/**< Checks if the elements is draggable (if the draggable dom
	     property should return true.

		 @returns TRUE if draggable (explicitly or implicitly),
		 FALSE otherwise */

	HTML_Element* GetDraggable(FramesDocument* doc);
	/**< Returns pointer to the nearest draggable element (may be this element or some of its draggable ancestors). */

	const uni_char* GetDropzone();
	/**< Gets dropzone attribute string value. */
#endif // DRAG_SUPPORT

private:
	static void DOMAreEqualNodes_GetDocTypeHEInfo(const HTML_Element *element, HLDocProfile *hldoc,
			const uni_char *&pubid, const uni_char *&sysid, const uni_char *&name, const uni_char *&intsubset);
	/** < Helper for DOMAreEqualNodes */

	static OP_STATUS DOMAreEqualNodes_GetText(const HTML_Element *elm, TempBuffer &buffer, const uni_char *&result, unsigned &result_length);
	/** < Helper for DOMAreEqualNodes */
public:

	static OP_STATUS	DOMCreateTextNode(HTML_Element *&element, DOM_Environment *environment, const uni_char *text, BOOL comment, BOOL cdata_section);
	/**< Create an HTML_Element containing 'text', either a text element, comment
	     element or CDATA section element.

	     @param element Set to the created element.
	     @param environment DOM environment.
	     @param text Text contents.
	     @param comment If TRUE, create a comment element.
	     @param cdata If TRUE, create a CDATA section element.
	     @param force_linebreaks If TRUE, line break characters in 'text' will be
	                             layed out as line breaks.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
		         or OpStatus::ERR_NO_MEMORY on OOM. */

	static OP_STATUS	DOMCreateProcessingInstruction(HTML_Element *&element, DOM_Environment *environment, const uni_char *target, const uni_char *data);
	/**< Create a processing instruction with the target 'target' and the contents
	     'data'.

	     @param element Set to the created element.
	     @param environment DOM environment.
	     @param target Target.
	     @param data Contents.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
		         or OpStatus::ERR_NO_MEMORY on OOM. */

	static OP_STATUS	DOMCreateDoctype(HTML_Element *&element, DOM_Environment *environment, XMLDocumentInformation *docinfo);
	/**< Create a DOCTYPE element.

	     @param element Set to the created element.
	     @param environment DOM environment.

	     @return OpStatus::OK, OpStatus::ERR if the element could not be created
	             or OpStatus::ERR_NO_MEMORY on OOM. */

	static void			DOMFreeElement(HTML_Element *element, DOM_Environment *environment);

	/**
	 * Called to make sure everything that has to happen when DOM changes a form happens.
	 * @param frames_doc A document.
	 * @param thread The thread causing the change.
	 */
	void				HandleFormValueChange(FramesDocument *frames_doc, ES_Thread* thread);

	/**
	 * Called when an input element's type is altered.
	 * @returns OpStatus::OK on success, OpStatus::ERR_NO_MEMORY in case of OOM.
	 */
	OP_STATUS			HandleInputTypeChange(const DocumentContext &context);

	BOOL				HasEventHandlerAttribute(FramesDocument *doc, DOM_EventType type);
	BOOL				HasEventHandlerAttributes(FramesDocument *doc);
	/**< Returns TRUE if this element has any attributes that is an
	     event handler.  Note: this does not return TRUE for event
	     handlers set with EventTarget.addEventListener or with XML
	     Events. */

	BOOL				DOMHasEventHandlerAttribute(DOM_Environment *environment, DOM_EventType type);
	/**< Returns TRUE if this element has an attribute that is an
	     event handler.  Note: this does not return TRUE for event
	     handlers set with EventTarget.addEventListener or with XML
	     Events. */

	BOOL				DOMHasEventHandlerAttributes(DOM_Environment *environment);
	/**< Returns TRUE if this element has any attributes that is an
	     event handler.  Note: this does not return TRUE for event
	     handlers set with EventTarget.addEventListener or with XML
	     Events. */

	OP_STATUS			DOMSetEventHandlers(DOM_Environment *environment);
	/**< Call DOM_Environment::SetEventHandler for each attribute on
	     this element that is an event handler.

	     @return OpStatus::OK or OpStatus::ERR_NO_MEMORY. */

    DOM_EventType		GetEventType(int attr, int attr_ns_idx);

	OP_STATUS			SendEvent(DOM_EventType event, FramesDocument *doc);
	/**< Dispatches an event of type event to the document doc with this element as target */

	BOOL				HasEventHandler(FramesDocument *doc, DOM_EventType type, BOOL local_only);
	/**< If 'local_only' is TRUE, returns TRUE if this element has an
	     event listener that would handle the specified type of event.

	     If 'local_only' is FALSE, returns TRUE if any event handler
	     currently registered would handle the specified type of event
	     fired with this element as its target. */

	BOOL				HasAfter() const { return packed2.has_after; }
	BOOL				HasBefore() const { return packed2.has_before; }
	BOOL				HasFirstLetter() const { return packed2.has_first_letter; }
	BOOL				HasFirstLine() const { return packed2.has_first_line; }

#ifdef XSLT_SUPPORT
	void				XSLTStripWhitespace(LogicalDocument *logdoc, XSLT_Stylesheet *stylesheet);
#endif // XSLT_SUPPORT

	void				SetInserted(HE_InsertType itype) { packed1.inserted = itype; OP_ASSERT(packed1.inserted == static_cast<unsigned int>(itype)); }
	BOOL				GetIsGeneratedContent() const { return packed2.generated_content; }
	void				SetIsGeneratedContent() { packed2.generated_content = 1; }
	BOOL				HasClass() const { return packed1.has_class; }
	void				SetHasClass() { packed1.has_class = 1; }
	/** @returns TRUE if the element is a text node or a group of text nodes */
	BOOL				IsText() const { return Type() == HE_TEXT || Type() == HE_TEXTGROUP; }

	/** @returns TRUE if the element has text and is not any of the element types for which we want a different cursor */
	BOOL				CanUseTextCursor();

	BOOL				GetIsCDATA() const;
	BOOL				HasBeforeOrAfter() const { return packed2.has_after || packed2.has_before; }
	BOOL				HasBgImage() const { return packed2.has_bg_image; }
	void				SetHasBgImage(BOOL value) { packed2.has_bg_image = value ? 1 : 0; }

	/**
	 * Set if this element is indeterminate or not.
	 * @param frames_doc The document for this element or NULL
	 * @param indeterminate TRUE for indeterminate state, FALSE for normal.
	 * @param apply_property_changes TRUE if the property changes should be applied (should always
	 *                               happen at some point after changing the indeterminate status)
	 */
	void				SetIndeterminate(FramesDocument *frames_doc, BOOL indeterminate, BOOL apply_property_changes);

	/** Get if this element is indeterminate or not. */
	BOOL				GetIndeterminate();

#ifdef _WML_SUPPORT_
	/**
	 * Must be called once per WML element when loading a WML page. Setting
	 * up the correct tasks and handlers.
	 * @param doc_man The DocumentManager for the document this element belongs to. */
    OP_STATUS       WMLInit(DocumentManager *doc_man);
#endif // _WML_SUPPORT_

	/** Used to set the type of the element. USE WITH CARE. The type should only be set at creation. */
	void			SetType(HTML_ElementType new_type) { packed1.type = new_type; }

	/**
	 * Used to fetch an attribute with a given local name
	 * @param attr_name The name of the element
	 * @param case_sensitive Must be TRUE if the name of the element should be matched exactly
	 * @returns The string value of the attribute with the name attr_name
	 */
	const uni_char*	GetXmlAttr(const uni_char* attr_name, BOOL case_sensitive = TRUE);

	/**
	 * Returns TRUE if the attribute exists in a preprocessed form
	 * retrievable with GetNumAttr(). This only works for predefined
	 * attributes, i.e. not ATTR_XML. Also, it assumes that the
	 * attribute is non-special. For special attributes use HasSpecialAttr()
	 * instead (you're assumed to know the type of it anyway).
	 */
	BOOL			HasNumAttr(short attr, int ns_idx = NS_IDX_HTML) const;
	/** Returns TRUE if the attribute with the type attr in the namespace indicated by ns_idx exists */
	BOOL			HasAttr(short attr, int ns_idx = NS_IDX_HTML) const;
	/** Returns TRUE if the special attribute with the type attr in the namespace indicated by ns exists */
	BOOL			HasSpecialAttr(short attr, SpecialNs::Ns ns) const;
	/**
	 * Used to find the index of an attribute with the matching type code or name.
	 * Two modes: attr==ATTR_XML => use name; if ns_idx==NS_IDX_ANY_NAMESPACE, search in any namespace.
	 *            attr!=ATTR_XML => ignore name; ns_idx cannot be NS_IDX_ANY_NAMESPACE.
	 *
	 * Note: attr==ATTR_XML does not mean that name cannot be translated into an
	 *       attribute code, just that it hasn't been yet.
	 * Note: If searching for a special attribute, use FindSpecialAttrIndex()
	 *       instead for performance reasons.
	 *
	 * @param attr The attribute type or ATTR_XML if name is to be used
	 * @param name The name of the attribute if attr is ATTR_XML
	 * @param ns_idx The namespace index of the attribute
	 * @param strict_ns If TRUE namespace uri comparison is skipped for known namespaces,
	 *  causing all known HTML namespaces to be treated as one.
	 *
	 * @returns The index into the attribute array of the attribute or -1 if not found.
	 */
	int				FindAttrIndex(int attr, const uni_char *name, int ns_idx, BOOL case_sensitive, BOOL strict_ns = FALSE) const
	{
		return FindAttrIndexNs(attr, name, ns_idx, case_sensitive, strict_ns);
	}
	int				FindAttrIndexNs(int attr, const uni_char *name, int ns_idx, BOOL case_sensitive, BOOL strict_ns) const;
	int				FindHtmlAttrIndex(int attr, const uni_char *name) const;
	int				FindSpecialAttrIndex(int attr, SpecialNs::Ns ns_idx) const;

	/**
	 * Resolve a namespace prefix and name against this element's attributes, returning its
	 * namespace index or NS_IDX_DEFAULT if no match. This is used to direct lookup of qualified
	 * names (by getAttribute*()/removeAttribute*()), resolving what namespace to perform
	 * the attribute lookup at.
	 * @param prefix The namespace prefix.
	 * @param prefix_length The length of the prefix. If 0, then 'prefix'
	 *        can be NULL.
	 * @param name The attribute name, without a prefix.
	 * @returns The namespace index this qualified name was resolved at, or
	 *          NS_IDX_DEFAULT if no match.
	 */
	int				ResolveNameNs(const uni_char *prefix, unsigned prefix_length, const uni_char *name) const;

	/**
	 * Gets an attribute value of a given attribute.
	 * @param attr The attribute code for the attribute to fetch
	 * @param ns_idx The namespace index of the attribute
	 * @returns The string value of the attribute if it is found and has the string type otherwise NULL
	 */
	const uni_char*	GetStringAttr(short attr, int ns_idx = NS_IDX_HTML) const { return static_cast<const uni_char *>(GetAttr(attr, ITEM_TYPE_STRING, NULL, ns_idx)); }
	/** Same as GetStringAttr() only returns number attributes instead of string attributes.
	 * @returns The numeric value of the attribute or def_value if it is not found.*/
	INTPTR			GetNumAttr(short attr, int ns_idx = NS_IDX_HTML, INTPTR def_value = 0) const { return PTR_TO_INTPTR(GetAttr(attr, ITEM_TYPE_NUM, INT_TO_PTR(def_value), ns_idx)); }
	/** Same as GetStringAttr() only returns boolean attributes instead of string attributes.
	 *
	 * Note: This method can only be used with special (internal)
	 * attributes and with attributes that the parser recognizes as
	 * boolean. It is not always equivalent to HasAttr().
	 *
	 * @returns The boolean value of the attribute or FALSE if it is not found.*/
	BOOL			GetBoolAttr(short attr, int ns_idx = NS_IDX_HTML, BOOL def_value = FALSE) const { return PTR_TO_BOOL(GetAttr(attr, ITEM_TYPE_BOOL, INT_TO_PTR(def_value), ns_idx)); };
	/** Same as GetStringAttr() only returns URL attributes instead of string attributes.
	 * @returns The URL pointer value of the attribute or NULL if it is not found.*/
	URL*			GetUrlAttr(short attr, int ns_idx = NS_IDX_HTML, LogicalDocument *logdoc = NULL);

	/** @returns The base URL for this element derived from the document and the base of the parents */
	URL				DeriveBaseUrl(LogicalDocument *&logdoc) const;
	/**
	 * Resolves a string into a URL taking into context the base url of the document and the parent nodes
	 * @param url_str The url as a string
	 * @param logdoc The logical document to which the element belongs. If NULL we will try to fetch it
	 *  from the root node of the tree. If the element is not in the tree the string will be solved as
	 *  an absolute URI.
	 * @param attr Some URLs are treated differently for some elements (like OBJECT)
	 * @param set_context_id If TRUE we should force the use of logdocs current URL context.
	 * @returns The resolved URL or empty if resolving failed */
	URL				ResolveUrl(const uni_char *url_str,
						LogicalDocument *logdoc = NULL,
						short attr = ATTR_NULL
#ifdef WEB_TURBO_MODE
						, BOOL set_context_id = FALSE
#endif // WEB_TURBO_MODE
						) const;

	/**
	 * Clears all resolved URL attributes on the element. Must be used if a change in the tree
	 * makes the URL attributes resolve to something else. For instance if you insert an xml:base
	 * attribute all URL attributes in the subtree must be re-resolved.
	 * This method is recursive and will clear all descendants as well. */
	void			ClearResolvedUrls();

	/**
	 * Checks if the element in inside a HE_TABLE. A real HE_TABLE, not something
	 * based on CSS or similar. Used during HTML parsing.
	 *
	 * @returns TRUE if the element is a child in one or more steps to a HE_TABLE that is not
	 * inserted by layout.
	 */
	BOOL			HasParentTable() const;

	/**
	 * Will traverse up through the ancestors of the element until an ancestor matching the type and ns_idx
	 * is found. Will not accept a hit at the root because all the callers of this method used it to
	 * find an element to close and we don't want to close the root element.
	 *
	 * @param stop_at_special If TRUE the traversal will stop if a certain element, like TABLE or BUTTON is reached
	 * @param exclude_root TRUE (default) means that we'll never match the root element. This affects innerHTML mostly.
	 * @returns TRUE if a matching element is found or a special element is found. */
	BOOL			HasParentElement(HTML_ElementType type, int ns_idx = NS_IDX_HTML, BOOL stop_at_special = TRUE) const;

	/** @returns TRUE if the element is or has been referenced from outside the tree */
    BOOL            IsReferenced() { return packed1.is_referenced_by_doc; }
	/** Used to set that the element is referenced. If true, deleting this element will also clean up other references. */
    void            SetReferenced(BOOL the_truth) { packed1.is_referenced_by_doc = the_truth; }

	/** @returns TRUE if the endtag for this element has been found in markup or it is inserted by DOM */
	BOOL			GetEndTagFound() const { return packed1.end_tag_found; }
	void			SetEndTagFound(BOOL found = TRUE) { packed1.end_tag_found = found; }

	BOOL			HasRealSizeDependentCss() const { return packed2.css_is_real_size_dependent; }
	void			SetHasRealSizeDependentCss(BOOL value) { packed2.css_is_real_size_dependent = (value ? 1 : 0); }

	/** The Mark* functions are used to indicate that the element has changed in some way and needs some change in layout. */
	BOOL			IsDirty() const { return packed2.dirty != ELM_NOT_DIRTY; }
	int				GetDirty() const { return packed2.dirty; }
	BOOL			IsExtraDirty() const { return (packed2.dirty & ELM_EXTRA_DIRTY) != 0; }
	BOOL			IsPropsDirty() const { return !packed2.props_clean; }
	BOOL			HasDirtyChildProps() const { return packed2.child_props_dirty; }
	void			SetDirty(int dirty) { packed2.dirty = dirty; }
	void			SetPropsDirty() { packed2.props_clean = 0; }

	/* Marks the element dirty and triggers a reflow if one isn't scheduled already.
	 * Used when size or position of the element changes.
	 * @param delete_minmax_widths Will delete the minmax width. See layout module for details.
	 * @param needs_update Will invalidate the box of the element */
	void			MarkDirty(FramesDocument* doc, BOOL delete_minmax_widths = TRUE, BOOL needs_update = FALSE);
	/* Marks the element dirty and triggers a reflow if one isn't scheduled already.
	 * Used when the box type changes or other structural changes.
	 * @param successor_subtrees Number of sibling subtrees to mark props dirty.
	 * Used for documents with adjacent sibling selectors.*/
	void			MarkExtraDirty(FramesDocument* doc, int successors = 0);

	/* FIXME */
	void			MarkContainersDirty(FramesDocument* doc);

	/**
	 * Mark the properties of this element dirty, schedule for reload. Will
	 * post a reflow message - which will reload properties. A reflow may not
	 * be needed in the end, but one cannot tell until properties have been
	 * reloaded. Special rule for root element: If this element is the document
	 * root element, all elements in the entire document will be scheduled for
	 * reload.
	 * @param doc The document in which this element resides. May not be NULL.
	 * @param successor_subtrees Number of sibling subtrees to mark props dirty.
	 * Used for documents with adjacent sibling selectors.
	 * @param mark_this_subtree Schedule all descendants of this element for
	 * reload as well.
	 */
	void			MarkPropsDirty(FramesDocument* doc, int successor_subtrees = 0, BOOL mark_this_subtree = FALSE);

	void			MarkPropsClean() { packed2.props_clean = 1; packed2.child_props_dirty = 0; }
	BOOL            NeedsUpdate() const { return packed2.needs_update; }
	int				MarkClean()
	{
		int was_dirty = packed2.dirty;
		packed2.needs_update = FALSE;
		packed2.dirty = ELM_NOT_DIRTY;
		return was_dirty;
	}

    /** Used to indicate if this element has specific settings for which cursor to use when hovering it. */
	void            SetHasCursorSettings(BOOL the_truth) { packed2.has_cursor_settings = the_truth; }
    /** @returns TRUE if this element has specific settings for which cursor to use when hovering it. */
    BOOL            HasCursorSettings() { return packed2.has_cursor_settings; }
#ifndef MOUSELESS
	void			UpdateCursor(FramesDocument *frames_doc);
#endif // !MOUSELESS

	/** @returns The number of PARAM elements contained in this one. Recursive. */
	int				CountParams() const;
	/** Recursively look for first PARAM with name 'type' and also return 'codetype'.
	 *  Ignore PARAMs inside nested OBJECT or APPLET elements.
	 *  @param[OUT] codetype Will be set to the value of the CODETYPE attribute.
	 *	@returns The value of the first type attribute of a PARAM in the subtree. */
	const uni_char*	GetParamType(const uni_char* &codetype) const;
	/** Recursively look for PARAMs with name 'filename', 'movie', 'src' or 'url'
	 *  Ignore PARAMs inside nested OBJECT or APPLET elements.
	 *  @returns URL of one of the mentioned attributes. */
	const uni_char*	GetParamURL() const;

#ifdef _PLUGIN_SUPPORT_
	OpNS4Plugin*	GetNS4Plugin();
	/**
	 * Will construct an array of attributes from */
	OP_STATUS		GetEmbedAttrs(int& argc, const uni_char** &argn, const uni_char** &argv) const;
#endif // _PLUGIN_SUPPORT_
	/** Used to fetch an array of parameters to an object. Consists of attributes and PARAMs
	 * @param names A pointer which will be assigned an array of names. Must not be deleted.
	 * @param values A pointer which will be assigned an array of values. Must not be deleted.
	 * @param next_index The first index after the last name in the array.
	 */
	void			GetParams(const uni_char** names, const uni_char** values, int& next_index) const;
	/**
	 * Used to find the correct type of an OBJECT element based on the type attribute and
	 * the type of URL.
	 * @param inline_url The URL used to load the object. Might be NULL and then the resolved object
	 *  type will depend on the type attribute alone. If that is not wanted, it shouldn't be called with
	 *  a NULL URL.
	 * @param[out] resolved_type Will return HE_IMG for images, HE_IFRAME for text or SVG,
	 *  HE_EMBED for plugins in general and HE_OBJECT for undetermined content, which will
	    typically result in fallback content for now but that might change as the inline
	    data is loaded. Only available if the function returns OpBoolean::IS_TRUE.
	 * @param[in] logdoc The document with this element. Might be NULL but then
	 *  the reliability of the response drops.
	 * @returns OpBoolean::IS_FALSE if the object type could not be resolved
	 *  at this time. It might be resolved to something correct later, when
	 *  resource loading and document parsing has completed (if it hasn't
	 *  already). Returns OpBoolean::IS_TRUE if the returned type is our final
	 *  decision. Will return OpStatus::ERR_NO_MEMORY if oom.
	 */
	OP_BOOLEAN		GetResolvedObjectType(URL* inline_url, HTML_ElementType &resolved_type, LogicalDocument* logdoc);
	/**
	 * Used to find the correct type of an EMBED element based on the type attribute and
	 * the type of URL.
	 * @param inline_url The URL used to load the object.
	 * @param[out] resolved_type Will return HE_IMG for images, HE_IFRAME for text or SVG,
	 *  HE_EMBED for plugins in general and for undetermined content, which will
	    typically result in fallback content for now but that might change as the inline
	    data is loaded. Only available if the function returns OpBoolean::IS_TRUE.
	 * @param[in] logdoc The document with this element. Might be NULL but then
	 *  the reliability of the response drops.
	 * @returns OpBoolean::IS_FALSE if the embed type could not be resolved
	 *  at this time. It might be resolved to something correct later, when
	 *  resource loading and document parsing has completed (if it hasn't
	 *  already). Returns OpBoolean::IS_TRUE if the returned type is our final
	 *  decision. Will return OpStatus::ERR_NO_MEMORY if oom.
	 */
	OP_BOOLEAN		GetResolvedEmbedType(URL* inline_url, HTML_ElementType &resolved_type, LogicalDocument* logdoc);

	/**
	 * Used to find the correct type of an IMG element based on the
	 * type of URL. Currently the only variation of IMG is SVGs in
	 * IMG.
	 */
	OP_BOOLEAN		GetResolvedImageType(URL* inline_url, HTML_ElementType &resolved_type, BOOL doc_loading, FramesDocument* doc);

#ifdef _WML_SUPPORT_
# define HTML_OR_WML(attr1, attr2) GetHtmlOrWmlStringAttr(attr1, attr2)
	/** Helper function for getting attributes from both HTML and WML namespace */
	const uni_char*	GetHtmlOrWmlStringAttr(short html_attr, short wml_attr) const;
#else // _WML_SUPPORT_
# define HTML_OR_WML(attr1, attr2) GetStringAttr(attr1)
#endif // _WML_SUPPORT_

public:

	HE_InsertType 	GetInserted() const { return (HE_InsertType) packed1.inserted; }
	/** Did the parser or DOM insert this element (is it actual)?
	 *
	 * @see HE_InsertType for more information on how elements can be inserted.
	 */
	BOOL			IsIncludedActual() const { return packed1.inserted < HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL; }
	BOOL			IsIncludedActualStyle() const { return packed1.inserted < HE_INSERTED_FIRST_HIDDEN_BY_ACTUAL_STYLE; }
	/**
	 * Used to get the value of the attribute of a given type
	 * @param attr The type code for the attribute to fetch.
	 * @param item_type The value type of the attribute.
	 * @param def_value The value returned if the attribute is not found.
	 * @param ns_idx The namespace index of the attribute.
	 * @returns A void pointer to the attribute value or def_value if not found.
	 */
	void*			GetAttr(short attr, ItemType item_type, void* def_value, int ns_idx = NS_IDX_HTML) const;

	/**
	 * Used to get the value of the first attribute of a given type.
	 * @param idx The index of the attribute to fetch.
	 * @param item_type The value type of the attribute.
	 * @param def_value The value returned if the attribute is not found.
	 * @returns A void pointer to the attribute value or def_value if not found.
	 */
	void*			GetAttrByIndex(int idx, ItemType item_type, void* def_value) const;

	/**
	 * Get string contents of some HTML attribute or text contents of this
	 * element (including children text contents), depending on type of HTML
	 * element.
	 *
	 * @param buffer For temporary string operations when getting text contents.
	 * @param frm_doc FramesDocument this HTML_Element belongs to.  It must have DOMEnvironment created.
	 * @returns String contents of respective attribute or text contents.
	 */
	const uni_char* GetMicrodataItemValue(TempBuffer& buffer, FramesDocument* frm_doc);

	/**
	 * Checks existence and absence of adequate HTML attributes.
	 */
	BOOL IsToplevelMicrodataItem() const;

	/**
	 * Used to set or replace the value of the first attribute of a given type.
	 * @param attr The type code for the attribute to set.
	 * @param item_type The value type of the attribute.
	 * @param val The value to set cast to a void pointer.
	 * @param need_free If set to TRUE the value will be deleted when the attribute is deleted.
	 * @param ns_idx The namespace index of the attribute.
	 * @param strict_ns Set to TRUE if you want to match the ns index exactly and not resolve the ns.
	 * @param is_id Set to TRUE if the attribute is a unique identifier.
	 * @param is_specified Set to TRUE if the attribute is explicitly specified in the markup.
	 * @param is_event Set to TRUE if it is an event handler.
	 * @param case_sensitive If TRUE, the search for an existing attribute will be case sensitive.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetAttr(short attr, ItemType item_type, void* val, BOOL need_free = FALSE, int ns_idx = NS_IDX_DEFAULT, BOOL strict_ns = FALSE, BOOL is_id = FALSE, BOOL is_specified = TRUE, BOOL is_event = FALSE, int at_known_index = -1, BOOL case_sensitive = FALSE);

	/**
	 * Set or replace a boolean attribute value.
	 * @param attr The type code for the attribute to set.
	 * @param val The value to set cast to a void pointer.
	 * @param ns_idx The namespace index of the attribute.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetBoolAttr(short attr, BOOL val, int ns_idx = NS_IDX_HTML) { return SetAttr(attr, ITEM_TYPE_BOOL, INT_TO_PTR(val), FALSE, ns_idx);	}

	/**
	 * Set or replace an integer attribute value.
	 * @param attr The type code for the attribute to set.
	 * @param val The value to set cast to a void pointer.
	 * @param ns_idx The namespace index of the attribute.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetNumAttr(short attr, long val, int ns_idx = NS_IDX_HTML) { return SetAttr(attr, ITEM_TYPE_NUM, INT_TO_PTR(val), FALSE, ns_idx); }

	/**
	 * Used to get the value of the special attribute of a given type.
	 * @param attr The type code for the attribute to fetch.
	 * @param item_type The value type of the attribute.
	 * @param def_value The value returned if the attribute is not found.
	 * @param ns The special namespace of the attribute.
	 * @returns A void pointer to the attribute value or def_value if not found.
	 */
	void*			GetSpecialAttr(Markup::AttrType attr, ItemType item_type, void* def_value, SpecialNs::Ns ns) const;

	/**
	 * Same as GetSpecialNumAttr() only returns string attributes instead of numeric attributes.
	 * @param attr The type code for the attribute to fetch.
	 * @param ns The special namespace index of the attribute.
	 * @returns The string value of the attribute or NULL if it is not found or the attribute
	 *  value is not a string.
	 */
	const uni_char*	GetSpecialStringAttr(Markup::AttrType attr, SpecialNs::Ns ns) const { return static_cast<const uni_char*>(GetSpecialAttr(attr, ITEM_TYPE_STRING, NULL, ns)); };

	/**
	 * Used to get the value of the special numeric attribute of a given type.
	 * @param attr The type code for the attribute to fetch.
	 * @param ns The special namespace index of the attribute.
	 * @param def_value The value returned if the attribute is not found.
	 * @returns The numeric value of the attribute or def_value if it is not found.
	 */
	long			GetSpecialNumAttr(Markup::AttrType attr, SpecialNs::Ns ns, long def_value = 0) const { return PTR_TO_LONG(GetSpecialAttr(attr, ITEM_TYPE_NUM, INT_TO_PTR(def_value), ns)); }

	/**
	 * Same as GetSpecialNumAttr() only returns boolean attributes instead of numeric attributes.
	 * @param attr The type code for the attribute to fetch.
	 * @param ns The special namespace index of the attribute.
	 * @returns The boolean value of the attribute or FALSE if it is not found.
	 */
	BOOL			GetSpecialBoolAttr(Markup::AttrType attr, SpecialNs::Ns ns, BOOL def_value = FALSE) const { return PTR_TO_BOOL(GetSpecialAttr(attr, ITEM_TYPE_BOOL, INT_TO_PTR(def_value), ns)); };

	/**
	 * Used to set or replace the value of the first special attribute of a given type.
	 * @param attr The type code for the attribute to set.
	 * @param item_type The value type of the attribute.
	 * @param val The value to set cast to a void pointer.
	 * @param need_free If set to TRUE the value will be deleted when the attribute is deleted.
	 * @param ns The special namespace index of the attribute.
	 * @return The index of the new attribute or -1 if OOM.
	 */
	int				SetSpecialAttr(Markup::AttrType attr, ItemType item_type, void* val, BOOL need_free, SpecialNs::Ns ns);

	/**
	 * Set or replace a boolean special internal attribute value.
	 * @param attr The type code for the attribute to set.
	 * @param val The value to set cast to a void pointer.
	 * @param ns The special namespace of the attribute.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetSpecialBoolAttr(Markup::AttrType attr, BOOL val, SpecialNs::Ns ns) { return SetSpecialAttr(attr, ITEM_TYPE_BOOL, INT_TO_PTR(val), FALSE, ns); }

	/**
	 * Set or replace an integer special internal attribute value.
	 * @param attr The type code for the attribute to set.
	 * @param val The value to set cast to a void pointer.
	 * @param ns The special namespace of the attribute.
	 * @returns The index of the new attribute or -1 if we fail.
	 */
	int				SetSpecialNumAttr(Markup::AttrType attr, long val, SpecialNs::Ns ns) { return SetSpecialAttr(attr, ITEM_TYPE_NUM, INT_TO_PTR(val), FALSE, ns); }

	/**
	 * Gets a pointer to the list of references.
	 * @returns the first entry in the list.
	 */
	ElementRef*		GetFirstReference() { return m_first_ref; }

	/**
	 * Gets a pointer to the first reference of the given reference type.
	 * @param type The type of reference.
	 * @returns the first entry in the list of type type.
	 */
	ElementRef*		GetFirstReferenceOfType(ElementRef::ElementRefType type);

	/**
	 * Used to set or replace the value of the first ATTR_XML attribute of a given name.
	 * @param attr The name of the attribute to set.
	 * @param value The value string to set.
	 * @param create If FALSE it will not create a new if one doesn't exist.
	 * @returns TRUE if successful.
	 */
	BOOL			SetAttrValue(const uni_char* attr, const uni_char* value, BOOL create);

	HTML_Element*	Parent() const { return static_cast<HTML_Element*>(DocTree::Parent()); };
	HTML_Element*	Suc() const { return static_cast<HTML_Element*>(DocTree::Suc()); };
	HTML_Element*	Pred() const { return static_cast<HTML_Element*>(DocTree::Pred()); };
	HTML_Element*	FirstChild() const { return static_cast<HTML_Element*>(DocTree::FirstChild()); };
	HTML_Element*	LastChild() const { return static_cast<HTML_Element*>(DocTree::LastChild()); };
	HTML_Element*	LastLeaf() { return static_cast<HTML_Element*>(DocTree::LastLeaf()); };
	HTML_Element*	Next() const { return static_cast<HTML_Element*>(DocTree::Next()); };
	HTML_Element*	Prev() const { return static_cast<HTML_Element*>(DocTree::Prev()); };
	HTML_Element*	NextSibling() const { return static_cast<HTML_Element*>(DocTree::NextSibling()); };
	HTML_Element*	PrevSibling() const { return static_cast<HTML_Element*>(DocTree::PrevSibling()); };
	HTML_Element*	Root() { return static_cast<HTML_Element*>(DocTree::Root()); };


	/**
	 * The *Actual() functions are used to traverse the logical tree skipping
	 * the nodes inserted by Opera that are not actually in the markup
	 * as well as those inserted by the Delayed Script Execution. To
	 * see which nodes are skipped see the documentation of HE_InsertType.
	 */
	HTML_Element*	ParentActual() const;
	HTML_Element*	SucActual() const;
	HTML_Element*	PredActual() const;
	HTML_Element*	FirstChildActual() const;
	HTML_Element*	LastChildActual() const;
	HTML_Element*	FirstLeafActual() const;
	HTML_Element*	LastLeafActual() const;
	HTML_Element*	NextActual() const;
	HTML_Element*	NextSiblingActual() const;
	HTML_Element*	PrevSiblingActual() const;
	HTML_Element*	PrevActual() const;

#ifdef DELAYED_SCRIPT_EXECUTION
	/**
	 * The *ActualStyle() functions are used to traverse the logical tree
	 * skipping the nodes inserted by Opera that are not actually in the
	 * markup but not those inserted by Delayed Script Execution. To see
	 * which nodes are skipped see the documentation of HE_InsertType.
	 */
	HTML_Element*	ParentActualStyle() const;
	HTML_Element*	SucActualStyle() const;
	HTML_Element*	PredActualStyle() const;
	HTML_Element*	FirstChildActualStyle() const;
	HTML_Element*	LastChildActualStyle() const;
	HTML_Element*	FirstLeafActualStyle() const;
	HTML_Element*	LastLeafActualStyle() const;
	HTML_Element*	NextActualStyle() const;
	HTML_Element*	PrevActualStyle() const;
	HTML_Element*	NextSiblingActualStyle() const;
#else // DELAYED_SCRIPT_EXECUTION
# define ParentActualStyle ParentActual
# define SucActualStyle SucActual
# define PredActualStyle PredActual
# define FirstChildActualStyle FirstChildActual
# define LastChildActualStyle LastChildActual
# define FirstLeafActualStyle LastLeafActual
# define LastLeafActualStyle LastLeafActual
# define NextActualStyle NextActual
# define PrevActualStyle PrevActual
# define NextSiblingActualStyle NextSiblingActual
#endif // DELAYED_SCRIPT_EXECUTION

	/** Put this element at the end of the child list of element elm */
	void			Under(HTML_Element* elm) { DocTree::Under( elm ); };
	/** Put this element after the element elm under its parent */
	void			Follow(HTML_Element* elm) { DocTree::Follow( (DocTree*)elm ); };
	/** Put this element before the element elm under its parent */
	void			Precede(HTML_Element* elm) { DocTree::Precede( (DocTree*)elm ); };

	/**
	 * Used to take elements out of the tree and keeping the integrity
	 * of the internal structures of the tree.
	 * @param going_to_delete TRUE if the element is taken out to be deleted, or FALSE
	 *  if the element is just moved somewhere else.
	 * @returns TRUE if the subtree is not referenced and can be
	 *  deleted using Free(). */
    BOOL            OutSafe(const DocumentContext &context, BOOL going_to_delete = TRUE);

	/** @deprecated Please use OutSafe(const DocumentContext &, HTML_Element *) instead.
	 * Note: calling with a document (assuming it is the correct one) is always safe;
	 * calling without one is almost always risky.
	 */
    void            DEPRECATED(OutSafe(int *ptr = NULL));

	/**
	 * Used to insert an element under another and keeping the integrity
	 * of the internal structures of the logical tree.
	 * @param mark_dirty If FALSE, the layout is not marked dirty. Use
	 *                   this with care: normally the layout must be
	 *                   marked dirty when * inserting elements.
	 */
	OP_STATUS		UnderSafe(const DocumentContext &context, HTML_Element* parent, BOOL mark_dirty = TRUE);
	/**
	 * Used to insert an element before another and keeping the integrity
	 * of the internal structures of the logical tree.
	 * @param mark_dirty If FALSE, the layout is not marked dirty. Use
	 *                   this with care: normally the layout must be
	 *                   marked dirty when * inserting elements.
	 */
	OP_STATUS		PrecedeSafe(const DocumentContext &context, HTML_Element* sibling, BOOL mark_dirty = TRUE);
	/**
	 * Used to insert an element after another and keeping the integrity
	 * of the internal structures of the logical tree.
	 * @param mark_dirty If FALSE, the layout is not marked dirty. Use
	 *                   this with care: normally the layout must be
	 *                   marked dirty when * inserting elements.
	 */
	OP_STATUS		FollowSafe(const DocumentContext &context, HTML_Element* sibling, BOOL mark_dirty = TRUE);

	BOOL			HasWhiteSpaceOnly();

    const uni_char*	Content() const { return LocalContent(); }
	unsigned		ContentLength() const { return LocalContentLength(); }

	/** Same as LocalContent() but includes linebreaks for BR */
    const uni_char*	TextContent() const;

	/**
	 * Get the string value of a named attribute.
	 * @param attr_name The localpart of the name of the attribute.
	 * @param ns_idx The namespace index.
	 * @param for_element_type what kind of element this is on.
	 *   Used when deciding if negative values should be returned as percentages; HE_ANY to always have them be, HE_UNKNOWN for never.
	 *   For other values of 'for_element_type', negative values will be returned as percentages if a length-like attribute.
	 * @param buffer A buffer to append generated values.
	 * @param known_index Known index of attribute; -1 if not.
	 * @returns A pointer to the value. If the value is generated this pointer
	 *  will not be valid after the buffer is deleted.
	 */
	const uni_char* GetAttrValue(const uni_char* attr_name, int ns_idx = NS_IDX_HTML, HTML_ElementType for_element_type = HE_UNKNOWN, TempBuffer *buffer = NULL, int known_index = -1);
	/**
	 * Get the string value of an attribute of a given type.
	 * @param attr The numeric type of the attribute.
	 * @param ns_idx The namespace index.
	 * @param for_element_type what kind of element this is on.
	 *   Used when deciding if negative values should be returned as percentages; HE_ANY to always have them be, HE_UNKNOWN for never.
	 *   For other values of 'for_element_type', negative values will be returned as percentages if a length-like attribute.
	 * @param strict_ns If set to TRUE the attribute must match the ns_idx exactly.
	 * @param buffer A buffer to append generated values.
	 * @param known_index Known index of attribute; -1 if not.
	 * @returns A pointer to the value. If the value is generated this pointer
	 *  will not be valid after the buffer is deleted.
	 */
	const uni_char* GetAttrValue(short attr, int ns_idx = NS_IDX_HTML, HTML_ElementType for_element_type = HE_UNKNOWN, BOOL strict_ns = FALSE, TempBuffer *buffer = NULL, int known_index = -1);

	/** @returns the first title element found in this element or any of its children. */
	HTML_Element*	GetTitle();

	/** @returns The language, specified or inherited, for this element */
	const uni_char*	GetCurrentLanguage();

	/** @returns The element that has the name or id matching name */
    HTML_Element*	GetNamedElm(const uni_char* name);
	/** @returns The element that has the id matching name */
	HTML_Element*	GetElmById(const uni_char* name);

	/** @returns The first form element contained in this or this if it is a form element */
    HTML_Element*   FindFirstContainedFormElm();

    /** Verifies that the object is properly connected to a DOM object.
      * @param frames_doc  is used to create DOM objects
      * @param statically_allocated
      * @return OK if the object is properly connected to a DOM object.
      */
    OP_STATUS		InitESObject(ES_Runtime* runtime, BOOL statically_allocated = TRUE);

	/**
	 * Registers a DOM event handler on this element
	 * @param event The type of event that you want to handle
	 * @param value The string with the handler code
	 * @param value_length The length of the handler code string
	 */
	OP_STATUS		SetEventHandler(FramesDocument *frames_doc, DOM_EventType event, const uni_char *value, int value_length);

	/**
	 * Clears a DOM event handler on this element
	 * @param event The type of event that you want to handle
	 */
	OP_STATUS		ClearEventHandler(DOM_Environment *environment, DOM_EventType event);

	/** Enables registered event handlers */
	OP_STATUS		EnableEventHandlers(FramesDocument *frames_doc);

	/** @returns TRUE if this element has an event handler */
	BOOL			HasEventHandler(FramesDocument *frames_doc, DOM_EventType event, HTML_Element* referencing_elm = NULL, HTML_Element** handling_elm = NULL, ES_EventPhase phase = ES_PHASE_AT_TARGET);

	/** The object holding options needed by HandleEvent.
	 *
	 * @see HTML_Element::HandleEvent.
	 */
	struct HandleEventOptions
	{
		 /** The target of the corresponding ONMOUSEOUT for an ONMOUSEOVER and vice versa. Otherwise NULL. */
		HTML_Element* related_target;
		/** How far into the target element the event occurred in document coordinates.
		 * Typically only used by mouse events. Can be set to 0 if it's not relevant.
		 */
		int offset_x;
		/** How far into the target element the event occurred in document coordinates. Typically only used by mouse
		 * events. Can be set to 0 if it's not relevant.
		 */
		int offset_y;
		/** How far into the document the event occurred in document coordinates. Typically only used by mouse
		 * events. Can be set to 0 if it's not relevant.
		 */
		int document_x;
		/** document_y How far into the document the event occurred in document coordinates. Typically only used by mouse
		 * events. Can be set to 0 if it's not relevant.
		 */
		int document_y;
		/** Multi purpose integer giving extra information related to the event.
		 * If the event is a mouse button event, then the information is the button and the sequence count (double
		 * clicking gives sequence count 2 on the second mousedown and mouseup).
		 * To get the mouse button, use the EXTRACT_MOUSE_BUTTON macro, to get the sequence count, use the
		 * EXTRACT_SEQUENCE_COUNT. If the event is a mouse wheel event, then the parameter is a
		 * number that says how far and in what direction the mouse wheel was spun.
		 * Negative numbers are scrolling up and positive numbers are scrolling down.
		 * If the event is a key event, then the number is a key identifier.
		 */
		int sequence_count_and_button_or_key_or_delta;
		/** Which key modifiers were pressed when the event was triggered. This is used to distinguish shift+clicks
		 * and similar. The integer is a bit field containing bits  matching SHIFTKEY_SHIFT, SHIFTKEY_CTRL and/or SHIFTKEY_ALT,
		 * or it is 0 (also known as SHIFTKEY_NONE).
		 */
		ShiftKeyState modifiers;
		/** If this is TRUE, a script (tried to) cancel the event.
		 * Typically that means that this method will do nothing, but there are some events that scripts
		 * cannot or should not be able to cancel so this method must still always be run. */
		BOOL has_keyboard_origin;
		/** Set to TRUE if event originates from the keyboard. Introduced to
		    handle ONCONTEXTMENU event which can have either mouse or keyboard
		    origin. Don't necessarily rely on it to be set appropriately for any
		    other event. */
		BOOL cancelled;
		/** Set to TRUE if a script has generated the event, FALSE if a user or opera code has generated the event.
		 * A script can generate events with for instance dispatchEvent and methods like click().
		 * Those events should often be handled like if the user had done the action, but in some cases it's
		 * important to not do the same thing to avoid for instance unsolicited popups. */
		BOOL synthetic;
		/** The thread that is waiting for this event to be processed, or NULL if there are no such thread. This is needed
		 * in case this event generates another event, in which case that event thread will block the supplied thread.
		 * It's also important in case we need to know more about the script trying to invoke the action.
		 * See the |synthetic| parameter. If this is forgotten scripts may run in the wrong order and web
		 * applications will break.
		 */
		ES_Thread* thread;
		/** Radius of the touch event in document units. */
		int radius;
		/** Platform-supplied identifier used by touch. */
		void* user_data;
		/** Event's id. Used to identify an event in case more than one event of a given type may be handled at the same time.
		 * May also be used to associate an event with some external data.
		 */
		unsigned int id;

		/** Extra platform key event data needed for plugin forwarding. */
		OpPlatformKeyEventData *key_event_data;

		HandleEventOptions()
		: related_target(NULL)
		, offset_x(0)
		, offset_y(0)
		, document_x(0)
		, document_y(0)
		, sequence_count_and_button_or_key_or_delta(0)
		, modifiers(SHIFTKEY_NONE)
		, has_keyboard_origin(FALSE)
		, cancelled(FALSE)
		, synthetic(FALSE)
		, thread(NULL)
		, radius(0)
		, user_data(NULL)
		, id(0)
		, key_event_data(NULL)
		{
		}
	};

	/**
	 * Called by external code to handle an event targetted at the
	 * |target| element, and bubbles (internally through recursive
	 * invocations of this method) up to the root element. This is
	 * called after any scripts have processed the event, but
	 * regardless if the script cancelled or let the event through
	 * (see the |cancelled| parameter. In script terminology, this
	 * corresponds to the DefaultAction.
	 *
	 * This should not be called directly to send an event. Use
	 * FramesDocument::Handle*Event to do that. It will run scripts
	 * (if any) and then call this when scripts are done (or directly
	 * if there were no script).
	 *
	 * Actions triggered by a call to this method includes following
	 * links triggered by clicks, generating ONCLICK, ONDBLCLICK,
	 * ONMOUSEOVER and ONMOUSEOUT events (triggered by mousemoves,
	 * mousedowns and mouseups), submitting forms, changing the mouse
	 * cursor (if hovering a link), informing the UI what is hovered,
	 * moving focus, toggle/trigger checkboxes and radio buttons.
	 *
	 * There are some things that should be here (after scripts) that
	 * are still done before scripts are run so it's not yet complete.
	 *
	 * This code is typically triggered by a user action, but it's also
	 * possible for scripts to generate events and it may be important to
	 * distinguish those two cases. See the |synthetic| parameter.
	 *
	 * This is not able to check for the existence of window events,
	 * only ordinary element events. It might assume that the event
	 * bubbles when making the decision.
	 *
	 * @param event - The code for the event sent to the element.
	 * Examples are ONFOCUS, ONCLICK, ONLOAD...
	 *
	 * @param target - The element the event is directly targetted at. For the first call,
	 * this is the same as the element itself.
	 *
	 * @param options - An instance of HandleEventOptions struct.
	 * @see HandleEventOptions for details.
	 *
	 * @param imagemap - The map element that this element belongs to if any, otherwise NULL.
	 *
	 * @param event_bubbling_path - The array of elements the event needs to be propagated to.
	 *
	 * @param event_bubbling_path_len - The length of the default event path
	 * -1 - means 'find the default path yourself',
	 * 0 - means that the path ended.
	 *
	 * @returns TRUE if the event was handled, meaning that a default
	 * action for the event has been triggered and that we should not
	 * propagate the event further.
	 *
	 * @todo Clean up, break apart, and make the code more
	 * maintainable.
	 */
	BOOL			HandleEvent(DOM_EventType event, FramesDocument* frames_doc, HTML_Element* target,
                                const HandleEventOptions& options, HTML_Element* imagemap = NULL, HTML_Element** event_bubbling_path = NULL, int event_bubbling_path_len = -1);

#ifdef TOUCH_EVENTS_SUPPORT
	/**
	 * Simulate mouse behaviour based on touch events. Used by HandleEvent to
	 * allow navigation of documents either lacking touch handlers or desiring
	 * both types of events.
	 *
	 * @see TWEAK_DOC_TOUCH_SMARTPHONE_COMPATIBILITY.
	 *
	 * @param[in] doc HTML Document to target.
	 * @param[in] event Type of event handled.
	 * @param[in] x Coordinates of event sequence relative to documents left edge.
	 * @param[in] y Coordinates of event sequence relative to document top edge.
	 * @param[in] radius Radius of inducing touch in document units.
	 * @param[in] modifiers The combination of key modifiers pressed when events are triggered.
	 */
	void			SimulateMouse(HTML_Document* doc, DOM_EventType event, int x, int y, int radius, ShiftKeyState modifiers);
#endif // TOUCH_EVENTS_SUPPORT

	/**
	 * Helper method to figure out at what document coordinates a caret can be found. Used
	 * when the context menu is invoked by the keyboard.
	 *
	 * @param[in] frames_doc The document
	 *
	 * @param[out] caret_x Will be set to the caret position if any, or to 0.
	 *
	 * @param[out] caret_y Will be set to the caret position if any, or to 0.
	 *
	 * @param[out] caret_offset_x Will be set to the offset of the caret position if any, or to 0.
	 *
	 * @param[out] caret_offset_y Will be set to the offset of the caret position if any, or to 0.
	 */
	void GetCaretCoordinate(FramesDocument* frames_doc, int& caret_x, int& caret_y, int& caret_offset_x, int& caret_offset_y);

	HTML_Element*	GetNextLinkElementInMap(BOOL forward, HTML_Element* map_element);

	/**
	 * Gets the HE_MAP element that is the closest ancestor of this element, NULL if none found.
	 * Valid only when this belongs to NS_HTML. */
	HTML_Element*	GetAncestorMapElm();

	/** Recursively looks for the link element in an image map that matches the coordinates.
	 *	@param[IN] img_element The image you want to check the map for.
	 *	@param[IN] default_element Will be set to the default element of the map if no match found.
	 *@returns the area or a element that matches the matches the coordinates given */
	HTML_Element*	GetLinkElement(VisualDevice* vd, int rel_x, int rel_y,
								const HTML_Element* img_element,
								HTML_Element* &default_element,
								LogicalDocument *logdoc = NULL);

	/**
	  *	Get element linked to from an usemap image based on coordinates. If the alt text is
	  *	shown, the linked element is based on the href of the clicked element that was
	  *	INSERTED_BY_LAYOUT to act as an alt link.
	  *
	  *	@param frames_doc
	  *	@param rel_x
	  *	@param rel_y
	  *	@param clicked_element Corresponding alt text link that was clicked.
	  */
	HTML_Element*	GetLinkedElement(FramesDocument* frames_doc,
								     int rel_x, int rel_y, HTML_Element* clicked_alt_text_element = NULL);

	/** Finds the containing A element, including this element itself. */
	HTML_Element*	GetA_Tag();

	/**
	 * Adds the data pointed to by src to the source list for the
	 * element. src need not be nul terminated and can contain nuls.
	 *
	 * @param origin The source of this data or the empty URL in case
	 * it's from the document itself (as in a HE_STYLE element).
	 */
	OP_STATUS		AddToSrcListAttr(const uni_char* src, int src_len, URL origin);

	/**
	  * Fetches the CSS object stored in an attribute of the element or returns NULL.
	  */
	CSS*			GetCSS() const { return (CSS*) GetSpecialAttr(ATTR_CSS, ITEM_TYPE_CSS, (void*)0, SpecialNs::NS_LOGDOC); }

	/**
	  * Removes the stylesheet for this element. Make sure all imports are removed too.
	  */
	void			RemoveCSS(const DocumentContext& context);

	/** @returns The first enclosing link for this element. Includes all link types. */
	HTML_Element*	GetAnchorTags(FramesDocument *document = NULL);

	/** @returns Returns the target address if this element is any kind of link. */
	const uni_char*	GetAnchor_HRef(FramesDocument *doc);

	/** @returns Returns the target URL if this element is any kind of link. */
	URL				GetAnchor_URL(HTML_Document *doc);

	/** @returns Returns the target URL if this element is any kind of link. */
	URL				GetAnchor_URL(FramesDocument *doc);

	/**
	 * Get the target URL as a string if this element is any kind of link.
	 * @param doc the document which this element is a part of
	 * @param[out] url url string. It is guaranteed that after successful call, it has CStr() non NULL.
	 * @return OpStatus::OK or OpStatus::ERR_NO_MEMORY in case of oom. */
	OP_STATUS		GetAnchor_URL(FramesDocument *doc, OpString& url);

	/**
	 * Gets both URL string and a title string associated with the element. Title can be an image's alt
	 * or simply the inner text of the element.
	 * @param doc the document which this element is a part of
	 * @param[out] url url string. It is guaranteed that after successful call, it has CStr() non NULL.
	 * @param[out] title title string. It is guaranteed that after successful call, it has CStr() non NULL.
	 * @return OpStatus::OK or OpStatus::ERR_NO_MEMORY in case of oom. */
	OP_STATUS		GetURLAndTitle(FramesDocument *doc, OpString& url, OpString& title);

	const uni_char*	GetA_Name() const { return (Type() == HE_A) ? GetStringAttr(ATTR_NAME) : 0; };
	const uni_char*	GetA_Target() const { return (Type() == HE_A) ? GetStringAttr(ATTR_TARGET) : 0; };
	const uni_char*	GetA_Title() const { return (Type() == HE_A) ? GetStringAttr(ATTR_TITLE) : 0; };
	/** @returns The href string of the A element */
	const uni_char*	GetA_HRef(FramesDocument *doc, BOOL insert_password = FALSE);

	/**
	 * function generally performs the same actions as GetA_HRef (except for it gets url with rel)
	 * and additional check in GetA_HRef and declaration change could be enough however because GetA_HRef
	 * might be invoked hundreds of times while page is loaded I decided to add another function */
	const char*     GetA_HRefWithRel(FramesDocument *doc);
	/** @returns The fragment identifier (#frag) of the href string of the A element */
	const char*		GetA_HRefRel(LogicalDocument *logdoc = NULL);
	/** @returns The target URL of the A element */
	URL*			GetA_URL(LogicalDocument *logdoc = NULL) { return GetUrlAttr(ATTR_HREF, NS_IDX_HTML, logdoc); };

	const uni_char*	GetAPPLET_Name() const { return (Type() == HE_APPLET) ? GetStringAttr(ATTR_NAME) : 0; };

	const uni_char*	GetBase_Target() const { return (Type() == HE_BASE) ? GetStringAttr(ATTR_TARGET) : 0; };

	BYTE			GetFontSize() const { return (BYTE)GetNumAttr(ATTR_SIZE, NS_IDX_HTML, 3); };
	BOOL			GetFontSizeDefined() const { return HasAttr(ATTR_SIZE, NS_IDX_HTML); };
	COLORREF		GetFontColor() const { return (COLORREF)GetNumAttr(ATTR_COLOR, NS_IDX_HTML, USE_DEFAULT_COLOR); };
	short			GetFontNumber() const { return (Type() == HE_FONT) ? (short)GetNumAttr(ATTR_FACE, NS_IDX_DEFAULT, -1) : -1; };

	/** @returns The list item marker type for lists and list items. */
	CSSValue		GetListType() const;

	const uni_char*	GetISINDEX_Action() const { return GetStringAttr(ATTR_ACTION); };
	const uni_char*	GetISINDEX_Prompt() const { return GetStringAttr(ATTR_PROMPT); };

	/** @returns The URL of the SRC attribute of an EMBED element. */
	URL*			GetEMBED_URL(LogicalDocument *logdoc = NULL);
	const uni_char*	GetEMBED_Type() const { return GetStringAttr(ATTR_TYPE); };
	const uni_char*	GetEMBED_PluginSpace() const { return GetStringAttr(ATTR_PLUGINSPACE); };
	int				GetEMBED_Width() const { return (int)GetNumAttr(ATTR_WIDTH); };
	int				GetEMBED_Height() const { return (int)GetNumAttr(ATTR_HEIGHT); };
	BOOL			GetEMBED_Hidden() const { return GetBoolAttr(ATTR_HIDDEN); };
	/** Returns the private attrs of an EMBED element. See documentation of PrivateAttrs. */
	int				GetEMBED_PrivateAttrs(uni_char** &argn, uni_char** &argv) const;
	const uni_char*	GetOBJECT_Name() const { return (Type() == HE_OBJECT) ? GetStringAttr(ATTR_NAME) : 0; };
	const uni_char*	GetFORM_Name() const { return (Type() == HE_FORM) ? GetStringAttr(ATTR_NAME) : 0; };

	const uni_char*	GetPARAM_Name() const { return GetStringAttr(ATTR_NAME); };
	const uni_char*	GetPARAM_Value() const { return GetStringAttr(ATTR_VALUE); };

	URL*			GetAREA_URL(LogicalDocument *logdoc = NULL) { return GetUrlAttr(ATTR_HREF, NS_IDX_HTML, logdoc); };
	const uni_char*	GetAREA_Alt() const { return GetStringAttr(ATTR_ALT); };
    const uni_char*	GetAREA_Target() const { return GetStringAttr(ATTR_TARGET); };

	int				GetAREA_Shape() const { return (int)GetNumAttr(ATTR_SHAPE, NS_IDX_HTML, AREA_SHAPE_RECT); };
	BOOL			GetAREA_NoHRef() const { return GetBoolAttr(ATTR_NOHREF); };
	const uni_char*	GetAREA_Name() const { return (Type() == HE_AREA) ? GetStringAttr(ATTR_NAME) : 0; };
	/** @returns TRUE if this element is mapped to the coordinates given by x and y in the map for img_element. */
	BOOL			GetMapUrl(VisualDevice* vd, int x, int y, const HTML_Element* img_element, URL* url, LogicalDocument *logdoc = NULL);
	const uni_char*	GetMAP_Name() const { return GetStringAttr(ATTR_NAME); };
	/** Will recursively search for a MAP element matching name. @returns the map element. */
    HTML_Element*   GetMAP_Elm(const uni_char* name);
	/** Used to draw a rectangular border around an element or calculate the region for it,
	 *	mainly used for image maps. The colors of the rectangle will be the inverted of
	 *	the underlaying content.
	 *	@param bsize The width in pixels of the border to be drawn.
	 *	@param region_rect Will be filled with the coordinates of the enclosing rectangle if non-NULL
	 *	@param clear Unused
	 *	@param img_element The image which the image map belongs to. */
	void			InvertRegionBorder(VisualDevice* vd, int xpos, int ypos, int width, int height,
						int bsize, RECT* region_rect, BOOL clear, HTML_Element* img_element);

#ifdef SKINNABLE_AREA_ELEMENT
	/** Used to draw a rectangular border around an element or calculate the region for it,
	 *	mainly used for image maps.
	 *	@param bsize The width in pixels of the border to be drawn.
	 *	@param region_rect Will be filled with the coordinates of the enclosing rectangle if non-NULL
	 *	@param clear Unused
	 *	@param img_element The image which the image map belongs to. */
	void			DrawRegionBorder(VisualDevice* vd, int xpos, int ypos, int width, int height,
						int bsize, RECT* region_rect, BOOL clear, HTML_Element* img_element);
#endif //SKINNABLE_AREA_ELEMENT

	/** Will fetch the URL of any element capable of showing images. That
	 *  includes IMG, INPUT, EMBED, OBJECT and the background of TABLE, TH, TD
	 *  and BODY.
	 *  @returns The URL of the image content. */
	URL 			GetImageURL(BOOL follow_redirect = TRUE, LogicalDocument *logdoc = NULL);
	URL*			GetIMG_UsemapURL(LogicalDocument *logdoc = NULL) { return GetUrlAttr(ATTR_USEMAP, NS_IDX_HTML, logdoc); };

	BOOL			IsMap() const { return GetBoolAttr(ATTR_ISMAP); };
	const uni_char*	GetIMG_Alt() const { return GetStringAttr(ATTR_ALT); };

	/** @returns TRUE if the Marquee has been stopped by a script. FALSE otherwise. */
	BOOL IsMarqueeStopped() { return GetSpecialBoolAttr(ATTR_MARQUEE_STOPPED, SpecialNs::NS_LOGDOC); }

	/** @returns the StyleAttribute object for the style attribute. NULL if the element has no style attribute. */
	StyleAttribute*	GetStyleAttribute();

	CSS_property_list*
					GetCSS_Style();
	/** Sets the style attribute to a new parsed prop_list. */
	OP_STATUS		SetCSS_Style(CSS_property_list* prop_list);

	/** Ensure that a StyleAttribute exists.
	 *
	 *  This function checks whether or not a StyleAttribute exists for
	 *  this HTML_Element, and creates one if it doesn't.
	 *
	 *  @return OpStatus::OK on success, or OpStatus::ERR_NO_MEMORY.
	 */
	OP_STATUS EnsureCSS_Style();

	/** Set (or create) the value for an inline style declaration.
	 *
	 *  This function may be used to set the value of an inline style
	 *  declaration such as 'width' and 'height'. The function may be used
	 *  with any CSS property that accepts a single number as the value.
	 *
	 *  This function will replace the value for the last occurrence of the
	 *  specified property. If no such property is found, a declaration with
	 *  the specified property and value will be appended to the current
	 *  inline style.
	 *
	 *  If the HTML_Element currently has no inline style, one will be
	 *  created.
	 *
	 *  The property will marked as important.
	 *
	 *  Style changes made using this function should be applied using
	 *  ApplyStyle().
	 *
	 *  @see ApplyStyle
	 *
	 *  @param property The CSS property to replace (or create).
	 *  @param value The (new) value for the property.
	 *  @param val_type The type of the value, e.g. CSS_PX. See CSSValueType.
	 *  @return OpStatus::OK if the style was set successfully; or
	 *          OpStatus::ERR_NO_MEMORY if we ran out of memory.
	 */
	OP_STATUS SetStyleDecl(CSSProperty property, float value, CSSValueType val_type);

	/** Apply changes to the inline style of this HTML_Element.
	 *
	 *  @see LayoutWorkPlace::ApplyPropertyChanges
	 *
	 *  @param hld_profile The HLDocProfile associated with this element.
	 *  @return OpStatus::OK if the style was successfully applied; or
	 *          OpStatus::ERR_NO_MEMORY if we ran out of memory.
	 */
	OP_STATUS ApplyStyle(HLDocProfile* hld_profile);

	/** @returns The value of the first attribute of type ID. Works for id in different namespaces. */
	const uni_char*	GetId() const;

	/** @returns the first class attribute. Works for class in different namespaces. */
	const ClassAttribute* GetClassAttribute() const
	{
		OP_PROBE4(OP_PROBE_HTML_ELEMENT_GETCLASSATTRIBUTE);

#if defined(SVG_SUPPORT)
		if (GetNsType() == NS_SVG)
			return GetSvgClassAttribute();
		else
#endif // SVG_SUPPORT
			return static_cast<ClassAttribute*>(GetAttr(ATTR_CLASS, ITEM_TYPE_COMPLEX, NULL));
	}

	const StringTokenListAttribute* GetItemPropAttribute() const
	{
		return static_cast<StringTokenListAttribute*>(GetAttr(ATTR_ITEMPROP, ITEM_TYPE_COMPLEX, NULL));
	}
	const StringTokenListAttribute* GetItemRefAttribute() const
	{
		return static_cast<StringTokenListAttribute*>(GetAttr(ATTR_ITEMREF, ITEM_TYPE_COMPLEX, NULL));
	}

#if defined(SVG_SUPPORT)
	/** @returns the class attribute in the svg namespace. */
	const ClassAttribute* GetSvgClassAttribute() const;
#endif // SVG_SUPPORT

	CSS_MediaObject*
					GetLinkStyleMediaObject() const;
	void			SetLinkStyleMediaObject(CSS_MediaObject* media_object);

	const uni_char*	GetLinkRel() const { return GetStringAttr(ATTR_REL); };

	/**
	 * Returns the resolved URL specified by the HREF attribute.
	 *
	 * @param[in] logdoc Needs to be specified for reliably correct
	 *                   interpretation of relative URLs.
	 * @return Pointer to URL or NULL if attribute isn't present.
	 */
	URL*			GetLinkURL(LogicalDocument *logdoc = NULL) { return GetUrlAttr(ATTR_HREF, NS_IDX_HTML, logdoc); };
	/**
	 * Returns the actual origin URL of the contents loaded via the
	 * link.  This is the final redirect target at the time data was
	 * read from the URL (the redirect chain may since have changed)
	 * unless the final redirect target is a data: or javascript: URL,
	 * in which case the second to last redirect target is returned.
	 *
	 * @return A URL object.  Same as returned by GetLinkURL() or
	 *         a URL to which that URL was redirected.
	 */
	URL				GetLinkOriginURL();

	/**
	 * @deprecated Use the SetText that takes a doc as argument.
	 */
	OP_STATUS		DEPRECATED(SetText(const uni_char *txt, unsigned int txt_len)); // inlined below

	/**
	 * Same as SetText() above, but will also notify the document that the text has changed.
	 *
	 * @param[in] doc FramesDocument, may be NULL, but then there will not be correct invalidations
	 * so NULL should only be used on elements outside the tree.
	 *
	 * @param[in] txt The new text of the node.
	 *
	 * @param[in] txt_len The length of the text pointed to by txt.
	 *
	 * @param[in] modification_type What kind of modification it
	 * does. This is used to perform intelligent changes of for
	 * instance selection. Can be MODIFICATION_REPLACING,
	 * MODIFICATION_DELETING, MODIFICATION_INSERTING,
	 * MODIFICATION_REPLACING_ALL or MODIFICATION_SPLITTING.
	 *
	 * @param[in] offset If REPLACING, it's the offset of the replaced
	 * text. length1 is the length of the replaced text and length2 is
	 * the length of the text that was inserted.  <p>If DELETING, the
	 * offset of the deleted text and length1 is the length of the
	 * inserted text.  <p>If INSERTING, the offset of the inserted
	 * text and length1 is the length of the inserted text.  <p>If
	 * UNKNOWN, the whole block is assumed to be replaced by a new
	 * block.
	 *
	 * @param[in] length1 See the offset parameter.
	 *
	 * @param[in] length2 See the offset parameter.
	 */
	OP_STATUS       SetText(const DocumentContext &context, const uni_char *txt, unsigned int txt_len, HTML_Element::ValueModificationType modification_type = MODIFICATION_REPLACING_ALL, unsigned offset = 0, unsigned length1 = 0, unsigned length2 = 0);

	/**
	 * Sets the new text of the layout inserted numeration list item marker.
	 * It should be used only for the HE_TEXT elements that are first children of layout inserted
	 * list marker elements (@see GetIsListMarkerPseudoElement()).
	 *
	 * @param doc The document that the element belongs to.
	 * @param txt The new text (numeration string).
	 * @param txt_len The length of txt.
	 * @return OK or OOM.
	 */
	OP_STATUS		SetTextOfNumerationListItemMarker(FramesDocument* doc, const uni_char *txt, unsigned int txt_len);

	/**
	 * Gathers source from the text children of this element (or
	 * already loaded external data) and parses it using the CSS parser
	 * and creates a style object as an attribute on the element.
	 *
	 *	@param[IN] user_defined Set to TRUE if the style is user defined.
	 */
	OP_STATUS		LoadStyle(const DocumentContext& context, BOOL user_defined);
	/** Removes child style elements imported by a stylesheet */
	void			RemoveImportedStyleElements(const DocumentContext &context);

	const uni_char*	GetFramesetRowspec() const { return GetStringAttr(ATTR_ROWS); };
	const uni_char*	GetFramesetColspec() const { return GetStringAttr(ATTR_COLS); };
	BOOL			GetFramesetRow(int i, int& val, int& type) const;
	BOOL			GetFramesetCol(int i, int& val, int& type) const;
	int				GetFramesetBorder() const { return (int)GetNumAttr(ATTR_BORDER, NS_IDX_HTML, DEFAULT_FRAMESETBORDER); };
	int				GetFramesetRowCount() const;
	int				GetFramesetColCount() const;

	BOOL			GetFrameBorder() const { return GetBoolAttr(ATTR_FRAMEBORDER); };
	int				GetFrameMarginWidth() const { return (int)GetNumAttr(ATTR_MARGINWIDTH, NS_IDX_HTML, DEFAULT_FRAMEMARGINWIDTH); };
	int				GetFrameMarginHeight() const { return (int)GetNumAttr(ATTR_MARGINHEIGHT, NS_IDX_HTML, DEFAULT_FRAMEMARGINHEIGHT); };
	BYTE			GetFrameScrolling() const { return (BYTE)GetNumAttr(ATTR_SCROLLING, NS_IDX_HTML, SCROLLING_AUTO); };
	BOOL			GetFrameNoresize() const { return GetBoolAttr(ATTR_NORESIZE); };
	const uni_char*	GetFrameName() const { return HasAttr(ATTR_NAME) ? GetStringAttr(ATTR_NAME) : GetId(); };

	COLORREF        GetBgColor() const { return (COLORREF)GetNumAttr(ATTR_BGCOLOR, NS_IDX_HTML, USE_DEFAULT_COLOR); };
	COLORREF        GetTextColor() const { return (COLORREF)GetNumAttr(ATTR_TEXT, NS_IDX_HTML, USE_DEFAULT_COLOR); };
	COLORREF        GetLinkColor() const { return (COLORREF)GetNumAttr(ATTR_LINK, NS_IDX_HTML, USE_DEFAULT_COLOR); };
	COLORREF        GetVLinkColor() const { return (COLORREF)GetNumAttr(ATTR_VLINK, NS_IDX_HTML, USE_DEFAULT_COLOR); };
	COLORREF        GetALinkColor() const { return (COLORREF)GetNumAttr(ATTR_ALINK, NS_IDX_HTML, USE_DEFAULT_COLOR); };

	const uni_char*	GetName() const { return GetStringAttr(ATTR_NAME); };
	const uni_char*	GetValue() const { return GetStringAttr(ATTR_VALUE); };
	const uni_char*	GetTarget() const { return GetStringAttr(ATTR_TARGET); };
	/**
	 * Returns the most suitable title attribute (there is one in
	 * html and another in xlink for instance) for display in some UI.
	 */
	const uni_char*	GetAction() const { return GetStringAttr(ATTR_ACTION); };
	const uni_char*	GetEncType() const { return HTML_OR_WML(ATTR_ENCTYPE, WA_ENCTYPE); }
	const uni_char*	GetAcceptCharset() const { return HTML_OR_WML(ATTR_ACCEPT_CHARSET, WA_ACCEPT_CHARSET); };
	const uni_char*	GetAccesskey() const { return HTML_OR_WML(ATTR_ACCESSKEY, WA_ACCESSKEY); };
	HTTP_Method		GetMethod() const;
    InputType		GetInputType() const;
	const uni_char* GetElementTitle() const;
	BOOL			GetChecked() const { return GetBoolAttr(ATTR_CHECKED); };
	BOOL			GetSelected() const { return GetBoolAttr(ATTR_SELECTED); };
	BOOL			GetDisabled() const { return GetBoolAttr(ATTR_DISABLED); };
	BOOL			GetReadOnly() const { return GetBoolAttr(ATTR_READONLY); };
	BOOL            GetAutocompleteOff();
	BOOL            GetUnselectable();
	int				GetRowsOrCols(BOOL get_row) const;
	int				GetRows() const;
	int				GetCols() const;
	int				GetMaxLength() const { return (int)GetNumAttr(ATTR_MAXLENGTH, NS_IDX_HTML, SHRT_MAX); };
	int				GetSize() const;
	int				GetElmNr() const { return static_cast<int>(GetSpecialNumAttr(ATTR_JS_ELM_IDX, SpecialNs::NS_LOGDOC)); };
	BOOL			GetMultiple() const;

#ifdef JS_PLUGIN_SUPPORT

	/**
	 * Help function for getting a JSPluginObject from an HTML element.
	 *
	 * @return The JSPluginObject, ot NULL if no object could be found.
	 */
	JS_Plugin_Object* GetJSPluginObject();

	/**
	 * Check if the element is an <object> tag with a type which is
	 * matched with a jsplugin in a particular hldoc_profile.
	 *
	 * @param hld_profile Document context for object.
	 * @param obj_pp[out] Pointer to the JS_Plugin_Object handling this type.
	 * @return OpBoolean::IS_TRUE if there was a match. Otherwise
	 * returns OpBoolean::IS_FALSE unless there was an OOM condition
	 * and OpStatus::ERR_NO_MEMORY is returned.
	 */
	OP_BOOLEAN      IsJSPluginObject(HLDocProfile* hld_profile, JS_Plugin_Object **obj_pp = NULL) const;

	/**
	 * Pass the name and value of any <param> tag/s on an object
	 * element to the JSPlugin listener.
	 *
	 * @param logdoc The logical document of the object element that
	 * holds the param elements to pass.
	 */
	OP_STATUS   PassParamsForJSPlugin(LogicalDocument* logdoc);
#endif // JS_PLUGIN_SUPPORT

	/**
	 * Returns the effective tab index. Negative = don't tab here.
	 *
	 * @param[in] doc The document for this element. Must be used to get
	 * the right value for iframe tabbing.
	 */
	int				GetTabIndex(FramesDocument* doc = NULL);

	/**
	 * Get the form number of the form. Can be called on form element
	 * and form control elements. With WebForms2 a form control can
	 * belong to several forms at once in which case this method
	 * returns the form number for the first of the forms. It is
	 * recommended to use the BelongsToForm instead.
	 *
	 * @param frames_doc May be NULL but in that case this method will
	 * be really slow.
	 *
	 * @return The form number of the primary frame this form control
	 * belongs to, or if it is a form element the form's number. If
	 * the control appears to be disassociated with any forms the
	 * method will return -1.
	 */
	int				GetFormNr(FramesDocument* frames_doc = NULL) const;
	long			GetFormElmNr() const;

	/**
	 * Checks if the current form control (this must be a form control) belongs to the give form.
	 *
	 * @param frames_doc May be NULL but in that case this method will be really slow.
	 */
	BOOL			BelongsToForm(FramesDocument* frames_doc, const HTML_Element* form) const
	{
		return FormManager::BelongsToForm(frames_doc, const_cast<HTML_Element*>(form), const_cast<HTML_Element*>(this));
	}

    /**
    Get the stored initial value of the value attribute
    */
//    const uni_char      * GetInitialValue();

	OP_STATUS		GetOptionText(TempBuffer *buffer);

	/**
	 * Called on elements (HE_OPTIONs and HE_OPTGROUPs) to check if they are really
	 * included in the ancestor element "select". Only HE_OPTION/HE_OPTGROUP that are immediate
	 * children of the select or a child through HE_OPTGROUPs only will return TRUE.
	 * Any other element should (for the purpose of the select) just be ignored.
	 *
	 * @param[in] select An ancestor HE_SELECT of this element.
	 */
	BOOL IsIncludedInSelect(HTML_Element* select);

#ifdef _WML_SUPPORT_
	/** @returns WA_NAME if it exists, else return ATTR_NAME. */
	const uni_char*	GetWmlName() const;
	/** @eturns WA_VALUE if it exists, else return ATTR_VALUE. */
	const uni_char* GetWmlValue() const;

	/** Determine if an HE_OPTION is default selected by wml value/ivalue */
	BOOL			IsWmlSelected(INT32 index) { return FormManager::IsWmlSelected(this, index); }
#endif //_WML_SUPPORT_

#if defined _SSL_SUPPORT_ && !defined _EXTERNAL_SSL_SUPPORT_
	const uni_char*	GetChallenge() const { return GetStringAttr(ATTR_CHALLENGE); };
#endif // _SSL_SUPPORT_ && !_EXTERNAL_SSL_SUPPORT_

	/** @returns TRUE if this element is a descendant of an element with type tpe */
	BOOL			IsPartOf(HTML_ElementType tpe) const;

	/** @retusn The first element in this elements subtree of type tpe in the namespace ns. */
	HTML_Element*	GetFirstElm(HTML_ElementType tpe, NS_Type ns = NS_HTML);

	/** Counts the number of elements before he in this elements subtree.
	 *	@param[IN] he The element to look for
	 *	@param[OUT] found Is set to TRUE if the element he is found in this elements subtree.
	 *	@returns The number of elements from this element to the element he. */
	int 			GetElmNumber(HTML_Element* he, BOOL& found);
	/** Returns the element number elm_nr in this elements subtree.
	 *	@param[IN] elm_nr The sequence number of the element in the subtree.
	 *	@param[OUT] i Counter used for calculating numbers. Set to 0 on the first call, and reuse for further searches.
	 *	@returns The element number elm_nr under this element. */
	HTML_Element* 	GetElmNumber(int elm_nr, int &i);

	/**
	 * Returns if the element (typically a form element) is disabled
	 * somehow. This is related to the DISABLED attribute
	 * (see GetDisabled()) but elements can be disabled in
	 * other ways as well. Is not guaranteed to return a relevant
	 * value for elements which are not supposed to be disablable.
	 * @param frames_doc A document.
	 * @returns TRUE if the element is disabled. False otherwise.
	 */
	BOOL			IsDisabled(FramesDocument* frames_doc);

	/** Used internally to remove the entry at index idx from the
	 *	attribute array and replace it with the last entry of the list. */
	void			RemoveAttrAtIdx(int idx);
	/** Used to remove an attribute matching numeric code and namespace. */
	void			RemoveAttribute(short attr, int ns_idx = NS_IDX_HTML);
	/** Used to remove a special attribute matching numeric code and namespace. */
	void			RemoveSpecialAttribute(short attr, SpecialNs::Ns ns_idx);

	/** See documentation of the FormManager functions for these */
	BOOL IsFormElement() { return FormManager::IsFormElement(this); }
	BOOL IsSelectedOption() { return FormManager::IsSelectedOption(this); }

	/** @returns TRUE if the subtree contains renderable content like text or form controls. */
    BOOL			HasContent();

	/** Used to parse a buffer and insert the resulting tree under this element.
	 *	@param[IN] html The start of the markup buffer.
	 *	@param[IN] html_len The length of the buffer or -1 if uni_strlen() is to be used.
	 *	@param[IN] actual_parent_element The actual parent element if the buffer will
	 *	  be parsed under an element not actually in the logical tree.
	 *	@param[IN] use_xml_parser If TRUE, XML parser will be used to parse the markup buffer.
	 *	@return OpStatus::OK on success, OpStatus::ERR if the operation could not be
	 *	  performed or OpStatus::ERR_NO_MEMORY on OOM. */
	OP_STATUS		SetInnerHTML(FramesDocument* frames_doc, const uni_char* html, int html_len = -1,
						HTML_Element *actual_parent_element = NULL, BOOL use_xml_parser = FALSE);

	/** Used to handle parsing and loading of scripts.
	 *	@param[IN] thread The currently running ES thread. NULL if none.
	 *	@param[IN] register_first Set to TRUE if the script should be registered first (See ES_LoadManager::RegisterScript())
	 *	@param[IN] is_inline_script If we create / register a script, we need to tell if it is an inline script (run during parsing) or not (triggered by an event handler or similar, for instance by dynamically inserting a script element). Set to TRUE if this is an inline script. Only used if register_first is TRUE.
	 *	@param[IN] stream_position The current position in the document source stream.
	 *	@returns OpBoolean::IS_TRUE if the script was loaded and executed. Can return normal OOM values. */
	OP_BOOLEAN		HandleScriptElement(HLDocProfile* hld_profile, ES_Thread *thread = NULL,
						BOOL register_first = FALSE, BOOL is_inline_script = FALSE, unsigned stream_position = 0);
	/** Cancels loading and execution of a script. */
	void			CancelScriptElement(HLDocProfile* hld_profile);
#if defined(USER_JAVASCRIPT) && defined(_PLUGIN_SUPPORT_)
	/** See documentation of DOM_Environment::PluginInitializedElement() */
	OP_BOOLEAN		PluginInitializedElement(HLDocProfile* hld_profile);
#endif // USER_JAVASCRIPT && _PLUGIN_SUPPORT_
	/** Checks if the element supports the script language stated in 'type' and 'language' attributes */
	BOOL IsScriptSupported(FramesDocument* frm_doc);
	/** Compiles the script text and queues it for execution. */
	OP_BOOLEAN		LoadScript(HLDocProfile* hld_profile);
	/** Triggers loading of an external script.
	 *	@param[IN] thread The currently executing thread or NULL if none.
	 *	@param[OUT] already_loaded Will be set to TRUE if the script URL is already loading.
	 *	@param[IN] load_inline Set to TRUE if.
	 *  @returns OpBoolean::IS_TRUE if the script was fetched successfully. Can return normal OOM values. */
	OP_BOOLEAN		FetchExternalScript(HLDocProfile* hld_profile, ES_Thread *thread = NULL, BOOL *already_loaded = NULL, BOOL load_inline = TRUE);
	/** Handles the loaded data of an external script.
	 *  @returns OpBoolean::IS_TRUE if the script was fetched successfully. Can return normal OOM values. */
	OP_BOOLEAN		LoadExternalScript(HLDocProfile* hld_profile);
	/**
	 * @param root_url The document's URL.
	 */
	OP_STATUS		ConstructESProgramText(ES_ProgramText *&program_text, int &program_text_len, URL& root_url, LogicalDocument *logdoc = NULL);
	/** Frees the script source from memory. To be called for scripts after everything that might need the source
	 *  has completed. That includes script compiling and UserJS handlers. */
	void			CleanupScriptSource();
	/** Puts whatever source we have in the provided DataSrc.
	 *  @param[OUT] other The DataSrc that will take care of the source. */
	void			StealScriptSource(DataSrc* other);

	/** @returns The stored element name or NULL if none is stored. */
	const uni_char*	GetXmlName() const;

	/** @returns A textual representation of the element type or the stored element name if it exists. If 'in_uppercase' is TRUE use accompanying 'buffer' to case-translate tag name. */
	const uni_char*	GetTagName(BOOL as_uppercase = FALSE, TempBuffer *buffer = NULL) const;
	/** @returns A textual representation of the attribute type or the stored element name if it exists. */
    const uni_char* GetAttrNameString(int i) const;
	/** @returns A textual representation of the attribute value. See GetAttrValueValue() for details. */
    const uni_char* GetAttrValueString(int i) const;

	PseudoElementType
					GetPseudoElement() const { return PseudoElementType(packed2.pseudo); }
	BOOL			GetIsPseudoElement() const { return packed2.pseudo != ELM_NOT_PSEUDO; }
	BOOL			GetIsAfterPseudoElement() const { return packed2.pseudo == ELM_PSEUDO_AFTER; }
	BOOL			GetIsBeforePseudoElement() const { return packed2.pseudo == ELM_PSEUDO_BEFORE; }
	BOOL			GetIsFirstLetterPseudoElement() const { return packed2.pseudo == ELM_PSEUDO_FIRST_LETTER; }
	BOOL			GetIsFirstLinePseudoElement() const { return packed2.pseudo == ELM_PSEUDO_FIRST_LINE; }
	BOOL			GetIsListMarkerPseudoElement() const {return packed2.pseudo == ELM_PSEUDO_LIST_MARKER; }
	void			SetIsAfterPseudoElement() { packed2.pseudo = ELM_PSEUDO_AFTER; }
	void			SetIsBeforePseudoElement() { packed2.pseudo = ELM_PSEUDO_BEFORE; }
	void			SetIsFirstLetterPseudoElement() { packed2.pseudo = ELM_PSEUDO_FIRST_LETTER; }
	void			SetIsFirstLinePseudoElement() { packed2.pseudo = ELM_PSEUDO_FIRST_LINE; }
	void			SetIsListMarkerPseudoElement() {packed2.pseudo = ELM_PSEUDO_LIST_MARKER; }

	Box*			GetLayoutBox() const { return layout_box; }
	void			SetLayoutBox(Box* box) { layout_box = box; }
	void			RemoveLayoutBox(FramesDocument* doc, BOOL clean_references = FALSE);

	void			DisableContent(FramesDocument* doc);
	OP_STATUS		EnableContent(FramesDocument* doc);
	int				GetTextContentLength();
	int				GetTextContent(uni_char* buf, int buf_len);

	Box*			GetInnerBox(int x, int y, FramesDocument* doc, BOOL text_boxes = TRUE);

	FormObject*		GetFormObject();
	FormValue*		GetFormValue();
	void			ReplaceFormValue(FormValue* value);

	OP_STATUS		ConstructFormValue(HLDocProfile *hld_profile, FormValue*& value);
# if defined(SELFTEST) || defined(_DEBUG)
	BOOL			ElementHasFormValue();
#endif // SELFTEST || _DEBUG

	/** Returns TRUE if this element would match the :first-child pseudo class. */
	BOOL			IsFirstChild();

	/** Remove cached info from the layout structure recursively on
		this element and all children elements. Also call MarkDirty on
		each element where cached info was removed. Used for removing
		text info.

	    If you pass `doc' as, the element will be marked dirty if it
		was modified. */

	void			RemoveCachedTextInfo(FramesDocument* doc = NULL);

	/** Needs to be called for all elements when ERA layout mode is changed between MSR and SSR. */

	void			ERA_LayoutModeChanged(FramesDocument* doc, BOOL apply_doc_styles_changed, BOOL support_float, BOOL column_strategy_changed);

public:

	CssPropertyItem*	css_properties;

	int					GetCssPropLen() const { return (int) packed2.css_props_size; }
	void				SetCssPropLen(int val) { packed2.css_props_size = val; }
	CssPropertyItem*	GetCssProperties() { return css_properties; }
	void				SetCssProperties(CssPropertyItem* props) { css_properties = props; }

	BOOL			SupportAttribute(long attr);

public:
#ifdef CSS_SCROLLBARS_SUPPORT
	void			GetScrollbarColor(class ScrollbarColors* colors);
#endif // CSS_SCROLLBARS_SUPPORT

	COLORREF		DEPRECATED(GetCssBackgroundColor());
	COLORREF		DEPRECATED(GetCssColor());
    CursorType      DEPRECATED(GetCursorType());
	/**
	 * This fetches the color specified as CSS in a style attribute.
	 * It's highly unlikely that this is what you want to use since
	 * it doesn't take inheritance and special color keywords into
	 * account.
	 * Instead you should create a cascade and get the color from it.
	 *
	 * @param[in] doc Document, needed in case we need to do some style calculations before returning.
	 *
	 * @returns USE_DEFAULT_COLOR or a OP_RGB color.
	 */
	COLORREF		GetCssBackgroundColorFromStyleAttr(FramesDocument* doc = NULL);
	/**
	 * This fetches the color specified as CSS in a style attribute.
	 * It's highly unlikely that this is what you want to use since
	 * it doesn't take inheritance and special color keywords into
	 * account.
	 * Instead you should create a cascade and get the color from it.
	 *
	 * @param[in] doc Document, needed in case we need to do some style calculations before returning.
	 *
	 * @returns USE_DEFAULT_COLOR or a OP_RGB color.
	 */
	COLORREF		GetCssColorFromStyleAttr(FramesDocument* doc = NULL);

	/**
	 * Remove the element from its parent and notify everyone that needs to know
	 * about such a change. After removing an element from its parent it might be
	 * without owner so the caller must either adopt it (insert it into another
	 * protected tree for instance) or call Clean()+Free() to delete it if it's
	 * now unused.
	 *
	 * @param context The document that contains the element.
	 * @param going_to_delete TRUE if the element is removed to be deleted,
	 * FALSE if it is going to be reinserted into the tree.
	 */
	void			Remove(const DocumentContext &context, BOOL going_to_delete = FALSE);
	void			MarkImagesDirty(FramesDocument* doc);

	OP_STATUS		LoadAllCSS(const DocumentContext& context);

#ifdef _PRINT_SUPPORT_
	HTML_Element*	CopyAll(HLDocProfile* hld_profile);
#endif // _PRINT_SUPPORT_

	void			SetFormObjectBackup(FormObject* fobj);
	FormObject*		GetFormObjectBackup();
	void			DestroyFormObjectBackup();

#ifdef DOCUMENT_EDIT_SUPPORT
	void            SetContentEditable(BOOL editable) { OP_ASSERT(0); } ///< Depricated. Will not be called from DOM module dumdum_2_beta_101.
	BOOL			IsContentEditable(BOOL inherit = FALSE);
	/** Return the value of contentEditable attribute on this element.
	 *
	 * @return YES - contentEditable set to true,
	 *         NO - contentEditable set to false,
	 *         MAYBE - contentEditable not set explicitly on this element.
	 */
	BOOL3			GetContentEditableValue();
#endif

#if defined(DOCUMENT_EDIT_SUPPORT) && defined(WIDGETS_IME_SUPPORT)
	void			SetIMEStyling(int value);
	int				GetIMEStyling();
#endif

#ifdef SVG_SUPPORT
	void			SetSVGContext(SVGContext* ctx);
	SVGContext*		GetSVGContext()
	{
		OP_ASSERT(IsText() || GetNsType() == NS_SVG);
		return svg_context;
	}
	void			DestroySVGContext();

	/**
	 * Set a listener that gets notified when an SVG element is finished.
	 *
	 * This listener is used when an SVG image is accessed via an <img> element
	 * and it has to be parsed as an IFRAME. */
	OP_STATUS		SetSVGIMGResourceListener(SVGIMGResourceListener* listener)
	{
		int ret = SetSpecialAttr(Markup::SVGA_IMG_RESOURCE_LISTENER, ITEM_TYPE_COMPLEX, listener, FALSE, SpecialNs::NS_SVG);
		return ret == -1 ? OpStatus::ERR_NO_MEMORY : OpStatus::OK;
	}

	void			RemoveSVGIMGResourceListener()
	{
		RemoveSpecialAttribute(Markup::SVGA_IMG_RESOURCE_LISTENER, SpecialNs::NS_SVG);
	}

	SVGIMGResourceListener* GetSVGIMGResourceListener()
	{
		return static_cast<SVGIMGResourceListener*>(GetSpecialAttr(Markup::SVGA_IMG_RESOURCE_LISTENER, ITEM_TYPE_COMPLEX, NULL, SpecialNs::NS_SVG));
	}

	/**
	 * Signal that an SVG element has finished processing.
	 *
	 * After this function has been called, the SVG element must be ready to use.
	 */
	void			SignalSVGIMGResourceFinished()
	{
		SVGIMGResourceListener* listener = GetSVGIMGResourceListener();
		if (listener)
			listener->SignalFinished();
	}
#endif // SVG_SUPPORT

	class BgImageIterator
	{
	public:
		BgImageIterator(HTML_Element *elm) : m_elm(elm), m_current(NULL) {}

		void		Reset() { m_current = NULL; }
		HEListElm*	Next();

	private:
		HTML_Element*	m_elm;
		ElementRef*		m_current;
	};

	/** Fetch the HEListElm matching an inline type stored as an
		attribute. */
	HEListElm*		GetHEListElmForInline(InlineResourceType inline_type);

	/** Get HEListElm for element.

		If background is FALSE, the HEListElm corresponding to
		IMAGE_INLINE is returned, typically used for image
		elements.

		If background is TRUE, the HEListElm corresponding to the
		first background image is returned. */
	HEListElm*		GetHEListElm(BOOL background);

	/**
	 * Traverse recursively through the subtree and for each element
	 * with an anchor url (see GetAnchor_URL) check if that url has
	 * been visited and update visited pseudo class.
	 */
	void			UpdateLinkVisited(FramesDocument* doc);

	/** You could also use Box::GetRect */
	BOOL			GetBoxRect(FramesDocument* doc, BoxRectType type, RECT& rect);

	const XMLDocumentInformation *GetXMLDocumentInfo() const;

#ifdef XML_EVENTS_SUPPORT
	XML_Events_Registration *GetXMLEventsRegistration() const { return (XML_Events_Registration *) GetSpecialAttr(ATTR_XML_EVENTS_REGISTRATION, ITEM_TYPE_XML_EVENTS_REGISTRATION, NULL, SpecialNs::NS_LOGDOC); }

	/**
	 * Called to register the xml event properly. Should only be called on element with event attributes.
	 *
	 * @param[in] frames_doc The document.
	 */
	OP_STATUS HandleInsertedElementWithXMLEvent(FramesDocument* frames_doc);

	/**
	 * Returns TRUE if there is an attribute in the NS_EVENT namespace.
	 */
	BOOL HasXMLEventAttribute();
#endif

#if defined SAVE_DOCUMENT_AS_TEXT_SUPPORT
	OP_STATUS		WriteAsText(UnicodeOutputStream* out, HLDocProfile* hld_profile, LayoutProperties* cascade, int max_line_length, int& line_length, BOOL& trailing_ws, BOOL& prevent_newline, BOOL& pending_newline);
#endif // SAVE_DOCUMENT_AS_TEXT_SUPPORT

	void			UndisplayImage(FramesDocument* doc, BOOL background);

	OP_STATUS		CreateSrcListFromChildren();

	BOOL            ShowAltText();

	BOOL			IsFlashType(const uni_char* mime_type) {
		return uni_strcmp(mime_type, UNI_L("application/x-shockwave-flash")) == 0 || uni_strcmp(mime_type, UNI_L("application/futuresplash")) == 0;
	}

#ifdef MANUAL_PLUGIN_ACTIVATION
	BOOL			GetPluginActivated();
	void			SetPluginActivated(BOOL activate);
	BOOL			GetPluginExternal();
	void			SetPluginExternal(BOOL external);
#endif // MANUAL_PLUGIN_ACTIVATION

	/**
	 * Returns TRUE if the layout box has been created or if no layout box will be created for this element
	 */
	BOOL			IsLayoutFinished() { return GetLayoutBox() || (!IsPropsDirty() && !IsExtraDirty()); }

	/**
	 * Returns TRUE if the element is currently showing replaced content. The typical
	 * use is to check if an HE_OBJECT is active or if the backup content is shown.
	 * Depending on whether the layout engine has processed the node we can get
	 * different answers.
	 */
	BOOL			IsDisplayingReplacedContent();

	/**
	 * Reset the extra background list.
	 *
	 * This function must be called before calling LoadInline on extra
	 * background images.
	 *
	 * 'Extra background images' is all background images except the
	 * first one, which is stored as in an attribute of its own for
	 * performance reasons.
	 *
	 * This allows the document loading code to reuse the HEListElm's
	 * it already has for extra background images.
	 */
	void			ResetExtraBackgroundList();

	/**
	 * Commit to the current extra background list.
	 *
	 * This function must be called after LoadInline has been called
	 * on all extra background images.
	 *
	 * This allows the document loading code to throw away all
	 * HEListElms that are unused.
	 */
	void			CommitExtraBackgroundList();

	enum SPC_ATTR_STATE {
		SPC_DISABLE_DEFAULT=-2,
		SPC_DISABLE=-1,
		SPC_ENABLE=1,
		SPC_ENABLE_DEFAULT=2
	};

	/**
	 * Returns the spellcheck state the element should have according to the rules of the spellcheck attribute.
	 * A positive value means spellcheck a negative value means don't spellcheck.
	 */
	SPC_ATTR_STATE SpellcheckEnabledByAttr();

#ifdef WEB_TURBO_MODE
	/**
	 * Will be called for every element in the tree to make sure all links
	 * will be updated to use the correct Web Turbo Mode url context.
	 */
	OP_STATUS			UpdateTurboMode(LogicalDocument *logdoc, URL_CONTEXT_ID context_id);

	/**
	 * @brief Used to switch Turbo off for element that (may) contain image content.
	 *
	 * @returns	ERR_NOT_SUPPORTED if element is not one of the supported element types,
	 *			ERR_NO_MEMORY in case of OOM or ERR if creation of new URL fails.
	 */
	OP_STATUS			DisableTurboForImage();
#endif // WEB_TURBO_MODE

	/**
	 * Checks if there is a DataSrc object for this link/style/script/... element.
	 */
	BOOL			HasDataSrc() { return HasSpecialAttr(ATTR_SRC_LIST, SpecialNs::NS_LOGDOC); }

	/**
	 * Returns the DataSrc object for the element. HE_STYLE, HE_SCRIPT, HE_LINK and
	 * some others have such to store downloaded or collected source for a parser.
	 */
	DataSrc*		GetDataSrc() { return static_cast<DataSrc*>(GetSpecialAttr(ATTR_SRC_LIST, ITEM_TYPE_COMPLEX, NULL, SpecialNs::NS_LOGDOC)); }

#ifdef ON_DEMAND_PLUGIN
	/**
	 * Is this a plugin placeholder element?
	 */
	BOOL			IsPluginPlaceholder() { return HasSpecialAttr(ATTR_PLUGIN_PLACEHOLDER, SpecialNs::NS_LOGDOC); }

	/**
	 * Mark this (plugin-)element as a plugin placeholder element
	 */
	void			SetIsPluginPlaceholder();

	/**
	 * Has this (plugin-)element been demanded to be loaded?
	 */
	BOOL			IsPluginDemanded() { return HasSpecialAttr(ATTR_PLUGIN_DEMAND, SpecialNs::NS_LOGDOC); }

	/**
	 * Marks the (plugin-)element as "demanded".  To turn the element into a real plugin, mark the element extra dirty.
	 */
	void			SetPluginDemanded();

#endif // ON_DEMAND_PLUGIN

#ifdef MEDIA_HTML_SUPPORT
	/**
	 * Returns MediaElement associated with this HTML_Element.
	 * For elements other than audio/video element will return NULL as there should be no MediaElement associated.
	 */
	MediaElement*	GetMediaElement();

	/**
	 * Returns TrackElement associated with this HTML_Element.
	 * For elements other than a track element NULL will be returned as there should be no TrackElement associated.
	 */
	TrackElement*	GetTrackElement() { return static_cast<TrackElement *>(GetSpecialAttr(Markup::MEDA_COMPLEX_TRACK_ELEMENT, ITEM_TYPE_COMPLEX, NULL, SpecialNs::NS_MEDIA)); }
#endif // MEDIA_HTML_SUPPORT

#ifdef MEDIA_SUPPORT
	/**
	 * Returns any Media based object associated with given HTML_Element.
	 */
	Media*			GetMedia();

	/**
	 * Sets media attribute by associating given Media object with specified media attribute
	 */
	BOOL			SetMedia(Markup::AttrType media_attr, Media *media, BOOL need_free);
#endif // MEDIA_SUPPORT

	/**
	 * Secondary constructor. Used by the HTML 5 parser to generate an element for a
	 * generic element in a markup document.
	 *
	 * @param[in] logdoc Context object required for many advanced element
	 * types or if there are attributes. Might be NULL for some simple types like HE_TEXTGROUP.
	 * @param[in] type The type of the element to insert.
	 * @param[in] ns The parser namespace the element should have.
	 * @param[in] token The parser token containing attributes and element name.
	 */
	void				ConstructL(LogicalDocument *logdoc, Markup::Type type, Markup::Ns ns, HTML5TokenWrapper *token);
	/**
	 * @returns The namespace of the element in type the parser uses.
	 */
	Markup::Ns			GetNs() const;
	/**
	 * Checks if the element has the specified name. The name will only be checked if type
	 * is HTE_UNKNOWN. The check is case sensitive. Namespace is not considered.
	 * @param name A null terminated string representing the name of the element. Only used if type is not known.
	 * @param type The element type to check for, or HTE_UNKONWN if the name is to be used.
	 * @returns TRUE if the element has the type type or the name name in case type is unknown.
	 */
	BOOL				IsNamed(const uni_char *name, Markup::Type type)
	{
		if (Type() == type)
		{
			if (type != HE_UNKNOWN)
				return TRUE;

			OP_ASSERT(name);
			const uni_char *this_elm_name = GetTagName();
			OP_ASSERT(this_elm_name);
			return uni_str_eq(this_elm_name, name);
		}

		return FALSE;
	}
	/**
	 * Adds an attribute to the element. Used by the HTML 5 parser.
	 * @param[in] logdoc The context object the element belongs to.
	 * @param[in] name A null terminated string with the name of the attribute.
	 * @param[in] value A string with the value of the attribute.
	 * @param[in] value_len The number of uni_chars in the value.
	 */
	void				AddAttributeL(LogicalDocument *logdoc, const HTML5TokenBuffer *name, const uni_char *value, unsigned value_len);

	/**
	 * Checks if the codebase attribute is a local file, which might be a security issue.
	 *
	 * @param[in] logdoc    The document containing the html element
	 * @param[in] type      The suggested element type being either HE_APPLET or HE_EMBED
	 * @param[in] mime_type In case of HE_EMBED, the mimetype used when checking for the java plugin, default value is NULL
	 *
	 * @returns HE_OBJECT if the codebase is a local file contained in a non-local document, otherwise the input parameter 'type'
	 */
	HTML_ElementType CheckLocalCodebase(LogicalDocument* logdoc, HTML_ElementType type, const uni_char* mime_type = NULL);

#ifdef CSS_VIEWPORT_SUPPORT
	/**
	 * Return the CSS_ViewportMeta object stored in the ATTR_VIEWPORT_META attribute.
	 * This method is used for HE_META elements with a name attribute set to "viewport".
	 *
	 * @param create If the attribute/object could not be found, create a new CSS_ViewportMETA
	 *		  object and store it as the ATTR_VIEWPORT_META attribute.
	 *
	 * @returns The CSS_ViewportMeta stored for ATTR_VIEWPORT_META. If create is FALSE,
	 *			NULL is returned if the attribute was not found. If create is TRUE, NULL
	 *			is returned on OOM.
	 */
	CSS_ViewportMeta* GetViewportMeta(const DocumentContext &context, BOOL create=FALSE);
#endif // CSS_VIEWPORT_SUPPORT

	/** Finds a common ancestor between the two elements if any, or NULL if not found.
	 *
	 * @param left          one the elments
	 * @param right         the other element
	 * */
	static HTML_Element *GetCommonAncestorActual(HTML_Element *left, HTML_Element *right);
};

/* gcc 3.3 can't handle deprecated inline; so split DEPRECATED declaration from inline definition */

inline OP_STATUS HTML_Element::SetText(const uni_char *txt, unsigned int txt_len)
{
	return SetText(static_cast<FramesDocument *>(NULL), txt, txt_len);
}

inline	OP_STATUS HTML_Element::Construct(HLDocProfile*, const uni_char* txt,
						unsigned int txt_len, BOOL not_used, BOOL plain_txt,
						BOOL replace_ws, BOOL force_linebreaks/* = FALSE*/)
{
	return Construct(txt, txt_len, !plain_txt, FALSE);
}

inline COLORREF HTML_Element::GetCssBackgroundColor()
{
	// The best we can get without a cascade and it would
	// be too expensive to create a cascade for every call
	// to this.
	return GetCssBackgroundColorFromStyleAttr();
}

inline	COLORREF HTML_Element::GetCssColor()
{
	// The best we can get without a cascade and it would
	// be too expensive to create a cascade for every call
	// to this.
	return GetCssColorFromStyleAttr();
}

class HTML_AttrIterator
{
public:
	HTML_AttrIterator(HTML_Element *element)
		: element(element), idx(0)
	{
	}

	int Count();
	/**
	 * @param ns Optional namespace. NULL if not interesting
	 */
	BOOL GetNext(const uni_char *&name, const uni_char *&value, int* ns_idx = NULL);

	BOOL GetNext(const uni_char *&name, const uni_char *&value, int &ns_idx, BOOL &specified, BOOL &id);

#ifdef WEB_TURBO_MODE
	BOOL GetNext(int& attr, int& ns_idx, BOOL& is_special, void*& obj, ItemType& item_type);
#endif // WEB_TURBO_MODE

	void Reset(HTML_Element *element);

private:
	TempBuffer buffer;
	HTML_Element *element;
	int idx;
};

/**
 * Attribute iterator for when we only want to read, but don't change
 * the attribute list.
 *
 * Modifications to the attribute list while using this iterator will
 * lead to undefined behavior, so make sure that none can happen.
 */
class HTML_ImmutableAttrIterator
{
public:
	HTML_ImmutableAttrIterator(HTML_Element *element)
		: element(element), idx(0) {}

	/** Iterate through the id attributes. */
	const uni_char* GetNextId();

#ifdef SVG_SUPPORT
	BOOL GetNext(int& attr, int& ns_idx, BOOL& is_special, void*& obj, ItemType& item_type);
#endif // SVG_SUPPORT

private:
	HTML_Element *element;
	int idx;
};

#ifdef DELAYED_SCRIPT_EXECUTION
inline HTML_Element* HTML_Element::ParentActualStyle() const
{
	HTML_Element *p = Parent();
	while (p && !p->IsIncludedActualStyle())
		p = p->Parent();

	return p;
}
#endif // DELAYED_SCRIPT_EXECUTION

#define DELETE_CSS_PROPERTIES(elm)  (elm)->DeleteCssProperties()
#define SHARE_CSS_PROPERTIES(elm)
#define UNSHARE_CSS_PROPERTIES(elm) (elm)->UnshareCssProperties()

/**
 * Iterator helper object which traverses the tree downwards
 * between an ancestor and a descendant.
 */
class HE_AncestorToDescendantIterator
{
	OpVector<HTML_Element> m_path;
public:
	HE_AncestorToDescendantIterator(){}
	~HE_AncestorToDescendantIterator(){}

	/**
	 * Initialize object. GetNextActual() will then return all
	 * nodes between ancestor and descendant from top to bottom.
	 *
	 * @param ancestor      top element. If NULL, then traversal
	 *                      will start at the document root
	 * @param descendant    bottom element. Cannot be NULL.
	 * @param skip_ancestor If TRUE, the ancestor is not returned
	 *                      by GetNextActual();
	 */
	OP_STATUS Init(HTML_Element *ancestor, HTML_Element *descendant, BOOL skip_ancestor);

	/**
	 * @returns current node and traverses to the following. If NULL, traversal is over
	 */
	HTML_Element *GetNextActual();
};

#endif /* _HTM_ELM_H_ */
