#include "misc/loader.h"
#include "dom/html_block.h"
#include "dom/html_head.h"
#include "dom/html_image.h"
#include "dom/html_inline.h"
#include "dom/html_list.h"
#include "dom/html_table.h"
#include "dom/html_object.h"
#include "dom/dom_exception.h"
#include "xml/dom2_eventsimpl.h"
#include "html/html_baseimpl.h"
#include "html/html_canvasimpl.h"
#include "html/html_documentimpl.h"
#include "html/html_formimpl.h"
#include "html/html_imageimpl.h"
#include "html/html_objectimpl.h"
#include "khtml_part.h"
#include "khtmlview.h"
#include "ecma/kjs_css.h"
#include "ecma/kjs_html.h"
#include "ecma/kjs_window.h"
#include "ecma/kjs_html.lut.h"
#include "kjs_events.h"
#include "kjs_proxy.h"
#include "misc/htmltags.h"
#include "rendering/render_canvasimage.h"
#include "rendering/render_object.h"
#include "rendering/render_layer.h"
#include <kdebug.h>
#include "cssparser.h"
#include "css_stylesheetimpl.h"
#include "qcolor.h"
#include "qpixmap.h"
#include "qpainter.h"
#include <ApplicationServices/ApplicationServices.h>
using namespace KJS;
using DOM::DocumentImpl;
using DOM::DOMString;
using DOM::ElementImpl;
using DOM::HTMLFrameElementImpl;
using DOM::HTMLGenericFormElementImpl;
using DOM::HTMLHtmlElementImpl;
using DOM::HTMLIFrameElementImpl;
using DOM::HTMLInputElement;
using DOM::HTMLInputElementImpl;
using DOM::HTMLTextAreaElement;
using DOM::HTMLTextAreaElementImpl;
IMPLEMENT_PROTOFUNC(HTMLDocFunction)
Value KJS::HTMLDocFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&HTMLDocument::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
DOM::HTMLDocument doc = static_cast<KJS::HTMLDocument *>(thisObj.imp())->toDocument();
switch (id) {
case HTMLDocument::Clear: return Undefined();
case HTMLDocument::Open:
if (args.size() > 2) {
KHTMLPart *part = static_cast<DOM::DocumentImpl *>(doc.handle())->part();
if (part) {
Window *window = Window::retrieveWindow(part);
if (window) {
Object functionObject = Object::dynamicCast(window->get(exec, "open"));
if (functionObject.isNull() || !functionObject.implementsCall()) {
Object exception = Error::create(exec, TypeError);
exec->setException(exception);
return exception;
}
Object windowObject(window);
return functionObject.call(exec, windowObject, args);
}
}
return Undefined();
}
doc.open();
return Undefined();
case HTMLDocument::Close:
doc.close();
return Undefined();
case HTMLDocument::Write:
case HTMLDocument::WriteLn: {
UString str = "";
for (int i = 0; i < args.size(); i++)
str += args[i].toString(exec);
if (id == HTMLDocument::WriteLn)
str += "\n";
doc.write(str.string());
return Undefined();
}
case HTMLDocument::GetElementsByName:
return getDOMNodeList(exec,doc.getElementsByName(args[0].toString(exec).string()));
case HTMLDocument::CaptureEvents:
case HTMLDocument::ReleaseEvents:
break;
}
return Undefined();
}
const ClassInfo KJS::HTMLDocument::info =
{ "HTMLDocument", &DOMDocument::info, &HTMLDocumentTable, 0 };
bool HTMLDocument::hasOwnProperty(ExecState *exec, const Identifier &p) const
{
#ifdef KJS_VERBOSE
#endif
DOM::HTMLDocumentImpl *docImpl = static_cast<DOM::HTMLDocumentImpl *>(node.handle());
return DOMDocument::hasOwnProperty(exec, p) || docImpl->haveNamedImageOrForm(p.qstring());
}
Value KJS::HTMLDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLDocument::tryGet " << propertyName.qstring() << endl;
#endif
DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
DOM::HTMLBodyElement body = doc.body();
KHTMLView *view = static_cast<DOM::DocumentImpl*>(doc.handle())->view();
const HashEntry* entry = Lookup::findEntry(&HTMLDocumentTable, propertyName);
if (entry) {
switch (entry->value) {
case Title:
return String(doc.title());
case Referrer:
return String(doc.referrer());
case Domain:
return String(doc.domain());
case URL:
return String(doc.URL());
case Body:
return getDOMNode(exec,doc.body());
case Location:
if ( view && view->part() )
{
Window* win = Window::retrieveWindow(view->part());
if (win)
return Value(win->location());
else
return Undefined();
}
else
return Undefined();
case Cookie:
return String(doc.cookie());
case Images:
return getHTMLCollection(exec,doc.images());
case Embeds:
return getHTMLCollection(exec,doc.embeds());
case Applets:
return getHTMLCollection(exec,doc.applets());
case Links:
return getHTMLCollection(exec,doc.links());
case Forms:
return getHTMLCollection(exec,doc.forms());
case Anchors:
return getHTMLCollection(exec,doc.anchors());
case Scripts: {
kdWarning() << "KJS::HTMLDocument document.scripts called - not implemented" << endl;
Object obj( new ObjectImp() );
obj.put( exec, lengthPropertyName, Number(0) );
return obj;
}
case All:
if ( exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat )
return Undefined();
return getHTMLCollection(exec,doc.all());
case Clear:
case Open:
case Close:
case Write:
case WriteLn:
case GetElementsByName:
case CaptureEvents:
case ReleaseEvents:
return lookupOrCreateFunction<HTMLDocFunction>( exec, propertyName, this, entry->value, entry->params, entry->attr );
}
}
ValueImp * val = ObjectImp::getDirect(propertyName);
if (val)
return Value(val);
if (entry) {
switch (entry->value) {
case BgColor:
return String(body.bgColor());
case FgColor:
return String(body.text());
case AlinkColor:
return String(body.aLink());
case LinkColor:
return String(body.link());
case VlinkColor:
return String(body.vLink());
case LastModified:
return String(doc.lastModified());
case Height:
return Number(view ? view->contentsHeight() : 0);
case Width:
return Number(view ? view->contentsWidth() : 0);
case Dir:
return String(body.dir());
case DesignMode:
{
DocumentImpl *docimpl = static_cast<DocumentImpl *>(doc.handle());
if (!docimpl)
return Undefined();
return String(docimpl->inDesignMode() ? "on" : "off");
}
}
}
ValueImp *proto = prototype().imp();
if (DOMDocument::hasOwnProperty(exec, propertyName) || (proto->dispatchType() == ObjectType && static_cast<ObjectImp *>(proto)->hasProperty(exec, propertyName)))
return DOMDocument::tryGet(exec, propertyName);
#if APPLE_CHANGES
DOM::HTMLCollection applets = doc.applets();
DOM::HTMLElement anApplet = applets.namedItem (propertyName.string());
if (!anApplet.isNull()) {
return getDOMNode(exec,anApplet);
}
DOM::HTMLCollection embeds = doc.embeds();
DOM::HTMLElement anEmbed = embeds.namedItem (propertyName.string());
if (!anEmbed.isNull()) {
return getDOMNode(exec,anEmbed);
}
DOM::HTMLCollection objects = doc.objects();
DOM::HTMLElement anObject = objects.namedItem (propertyName.string());
if (!anObject.isNull()) {
return getDOMNode(exec,anObject);
}
#endif
DOM::HTMLDocumentImpl *docImpl = static_cast<DOM::HTMLDocumentImpl*>(node.handle());
if (!docImpl->haveNamedImageOrForm(propertyName.qstring())) {
return Undefined();
}
DOM::HTMLCollection nameableItems = doc.nameableItems();
KJS::HTMLCollection kjsCollection(exec,nameableItems);
return kjsCollection.getNamedItems(exec, propertyName);
return Undefined();
}
void KJS::HTMLDocument::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLDocument::tryPut " << propertyName.qstring() << endl;
#endif
DOMObjectLookupPut<HTMLDocument, DOMDocument>( exec, propertyName, value, attr, &HTMLDocumentTable, this );
}
void KJS::HTMLDocument::putValue(ExecState *exec, int token, const Value& value, int )
{
DOM::HTMLDocument doc = static_cast<DOM::HTMLDocument>(node);
DOM::HTMLBodyElement body = doc.body();
switch (token) {
case Title:
doc.setTitle(value.toString(exec).string());
break;
case Body: {
DOMNode *node = new DOMNode(exec, KJS::toNode(value));
Value nodeValue(node);
doc.setBody(node->toNode());
break;
}
case Domain: { DOM::HTMLDocumentImpl* docimpl = static_cast<DOM::HTMLDocumentImpl*>(doc.handle());
if (docimpl)
docimpl->setDomain(value.toString(exec).string());
break;
}
case Cookie:
doc.setCookie(value.toString(exec).string());
break;
case Location: {
KHTMLPart *part = static_cast<DOM::DocumentImpl *>( doc.handle() )->part();
if (part)
{
QString str = value.toString(exec).qstring();
KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
if (activePart)
str = activePart->htmlDocument().completeURL(str).string();
#if APPLE_CHANGES
bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
part->scheduleLocationChange(str, activePart->referrer(), !userGesture);
#else
part->scheduleLocationChange(str, activePart->referrer(), false);
#endif
}
break;
}
case BgColor:
body.setBgColor(value.toString(exec).string());
break;
case FgColor:
body.setText(value.toString(exec).string());
break;
case AlinkColor:
{
DOM::DOMString newColor = value.toString(exec).string();
if (body.aLink() != newColor) {
body.setALink(newColor);
}
}
break;
case LinkColor:
{
DOM::DOMString newColor = value.toString(exec).string();
if (body.link() != newColor) {
body.setLink(newColor);
}
}
break;
case VlinkColor:
{
DOM::DOMString newColor = value.toString(exec).string();
if (body.vLink() != newColor) {
body.setVLink(newColor);
}
}
break;
case Dir:
body.setDir(value.toString(exec).string());
break;
case DesignMode:
{
DocumentImpl *docimpl = static_cast<DocumentImpl *>(doc.handle());
if (!docimpl)
break;
DOMString modeString = value.toString(exec).string();
DocumentImpl::InheritedBool mode;
if (!strcasecmp(modeString, "on"))
mode = DocumentImpl::on;
else if (!strcasecmp(modeString, "off"))
mode = DocumentImpl::off;
else
mode = DocumentImpl::inherit;
docimpl->setDesignMode(mode);
}
break;
default:
kdWarning() << "HTMLDocument::putValue unhandled token " << token << endl;
}
}
const ClassInfo KJS::HTMLElement::info = { "HTMLElement", &DOMElement::info, &HTMLElementTable, 0 };
const ClassInfo KJS::HTMLElement::html_info = { "HTMLHtmlElement", &KJS::HTMLElement::info, &HTMLHtmlElementTable, 0 };
const ClassInfo KJS::HTMLElement::head_info = { "HTMLHeadElement", &KJS::HTMLElement::info, &HTMLHeadElementTable, 0 };
const ClassInfo KJS::HTMLElement::link_info = { "HTMLLinkElement", &KJS::HTMLElement::info, &HTMLLinkElementTable, 0 };
const ClassInfo KJS::HTMLElement::title_info = { "HTMLTitleElement", &KJS::HTMLElement::info, &HTMLTitleElementTable, 0 };
const ClassInfo KJS::HTMLElement::meta_info = { "HTMLMetaElement", &KJS::HTMLElement::info, &HTMLMetaElementTable, 0 };
const ClassInfo KJS::HTMLElement::base_info = { "HTMLBaseElement", &KJS::HTMLElement::info, &HTMLBaseElementTable, 0 };
const ClassInfo KJS::HTMLElement::isIndex_info = { "HTMLIsIndexElement", &KJS::HTMLElement::info, &HTMLIsIndexElementTable, 0 };
const ClassInfo KJS::HTMLElement::style_info = { "HTMLStyleElement", &KJS::HTMLElement::info, &HTMLStyleElementTable, 0 };
const ClassInfo KJS::HTMLElement::body_info = { "HTMLBodyElement", &KJS::HTMLElement::info, &HTMLBodyElementTable, 0 };
const ClassInfo KJS::HTMLElement::form_info = { "HTMLFormElement", &KJS::HTMLElement::info, &HTMLFormElementTable, 0 };
const ClassInfo KJS::HTMLElement::select_info = { "HTMLSelectElement", &KJS::HTMLElement::info, &HTMLSelectElementTable, 0 };
const ClassInfo KJS::HTMLElement::optGroup_info = { "HTMLOptGroupElement", &KJS::HTMLElement::info, &HTMLOptGroupElementTable, 0 };
const ClassInfo KJS::HTMLElement::option_info = { "HTMLOptionElement", &KJS::HTMLElement::info, &HTMLOptionElementTable, 0 };
const ClassInfo KJS::HTMLElement::input_info = { "HTMLInputElement", &KJS::HTMLElement::info, &HTMLInputElementTable, 0 };
const ClassInfo KJS::HTMLElement::textArea_info = { "HTMLTextAreaElement", &KJS::HTMLElement::info, &HTMLTextAreaElementTable, 0 };
const ClassInfo KJS::HTMLElement::button_info = { "HTMLButtonElement", &KJS::HTMLElement::info, &HTMLButtonElementTable, 0 };
const ClassInfo KJS::HTMLElement::label_info = { "HTMLLabelElement", &KJS::HTMLElement::info, &HTMLLabelElementTable, 0 };
const ClassInfo KJS::HTMLElement::fieldSet_info = { "HTMLFieldSetElement", &KJS::HTMLElement::info, &HTMLFieldSetElementTable, 0 };
const ClassInfo KJS::HTMLElement::legend_info = { "HTMLLegendElement", &KJS::HTMLElement::info, &HTMLLegendElementTable, 0 };
const ClassInfo KJS::HTMLElement::ul_info = { "HTMLUListElement", &KJS::HTMLElement::info, &HTMLUListElementTable, 0 };
const ClassInfo KJS::HTMLElement::ol_info = { "HTMLOListElement", &KJS::HTMLElement::info, &HTMLOListElementTable, 0 };
const ClassInfo KJS::HTMLElement::dl_info = { "HTMLDListElement", &KJS::HTMLElement::info, &HTMLDListElementTable, 0 };
const ClassInfo KJS::HTMLElement::dir_info = { "HTMLDirectoryElement", &KJS::HTMLElement::info, &HTMLDirectoryElementTable, 0 };
const ClassInfo KJS::HTMLElement::menu_info = { "HTMLMenuElement", &KJS::HTMLElement::info, &HTMLMenuElementTable, 0 };
const ClassInfo KJS::HTMLElement::li_info = { "HTMLLIElement", &KJS::HTMLElement::info, &HTMLLIElementTable, 0 };
const ClassInfo KJS::HTMLElement::div_info = { "HTMLDivElement", &KJS::HTMLElement::info, &HTMLDivElementTable, 0 };
const ClassInfo KJS::HTMLElement::p_info = { "HTMLParagraphElement", &KJS::HTMLElement::info, &HTMLParagraphElementTable, 0 };
const ClassInfo KJS::HTMLElement::heading_info = { "HTMLHeadingElement", &KJS::HTMLElement::info, &HTMLHeadingElementTable, 0 };
const ClassInfo KJS::HTMLElement::blockQuote_info = { "HTMLBlockQuoteElement", &KJS::HTMLElement::info, &HTMLBlockQuoteElementTable, 0 };
const ClassInfo KJS::HTMLElement::q_info = { "HTMLQuoteElement", &KJS::HTMLElement::info, &HTMLQuoteElementTable, 0 };
const ClassInfo KJS::HTMLElement::pre_info = { "HTMLPreElement", &KJS::HTMLElement::info, &HTMLPreElementTable, 0 };
const ClassInfo KJS::HTMLElement::br_info = { "HTMLBRElement", &KJS::HTMLElement::info, &HTMLBRElementTable, 0 };
const ClassInfo KJS::HTMLElement::baseFont_info = { "HTMLBaseFontElement", &KJS::HTMLElement::info, &HTMLBaseFontElementTable, 0 };
const ClassInfo KJS::HTMLElement::font_info = { "HTMLFontElement", &KJS::HTMLElement::info, &HTMLFontElementTable, 0 };
const ClassInfo KJS::HTMLElement::hr_info = { "HTMLHRElement", &KJS::HTMLElement::info, &HTMLHRElementTable, 0 };
const ClassInfo KJS::HTMLElement::mod_info = { "HTMLModElement", &KJS::HTMLElement::info, &HTMLModElementTable, 0 };
const ClassInfo KJS::HTMLElement::a_info = { "HTMLAnchorElement", &KJS::HTMLElement::info, &HTMLAnchorElementTable, 0 };
const ClassInfo KJS::HTMLElement::canvas_info = { "HTMLCanvasElement", &KJS::HTMLElement::info, &HTMLCanvasElementTable, 0 };
const ClassInfo KJS::HTMLElement::img_info = { "HTMLImageElement", &KJS::HTMLElement::info, &HTMLImageElementTable, 0 };
const ClassInfo KJS::HTMLElement::object_info = { "HTMLObjectElement", &KJS::HTMLElement::info, &HTMLObjectElementTable, 0 };
const ClassInfo KJS::HTMLElement::param_info = { "HTMLParamElement", &KJS::HTMLElement::info, &HTMLParamElementTable, 0 };
const ClassInfo KJS::HTMLElement::applet_info = { "HTMLAppletElement", &KJS::HTMLElement::info, &HTMLAppletElementTable, 0 };
const ClassInfo KJS::HTMLElement::map_info = { "HTMLMapElement", &KJS::HTMLElement::info, &HTMLMapElementTable, 0 };
const ClassInfo KJS::HTMLElement::area_info = { "HTMLAreaElement", &KJS::HTMLElement::info, &HTMLAreaElementTable, 0 };
const ClassInfo KJS::HTMLElement::script_info = { "HTMLScriptElement", &KJS::HTMLElement::info, &HTMLScriptElementTable, 0 };
const ClassInfo KJS::HTMLElement::table_info = { "HTMLTableElement", &KJS::HTMLElement::info, &HTMLTableElementTable, 0 };
const ClassInfo KJS::HTMLElement::caption_info = { "HTMLTableCaptionElement", &KJS::HTMLElement::info, &HTMLTableCaptionElementTable, 0 };
const ClassInfo KJS::HTMLElement::col_info = { "HTMLTableColElement", &KJS::HTMLElement::info, &HTMLTableColElementTable, 0 };
const ClassInfo KJS::HTMLElement::tablesection_info = { "HTMLTableSectionElement", &KJS::HTMLElement::info, &HTMLTableSectionElementTable, 0 };
const ClassInfo KJS::HTMLElement::tr_info = { "HTMLTableRowElement", &KJS::HTMLElement::info, &HTMLTableRowElementTable, 0 };
const ClassInfo KJS::HTMLElement::tablecell_info = { "HTMLTableCellElement", &KJS::HTMLElement::info, &HTMLTableCellElementTable, 0 };
const ClassInfo KJS::HTMLElement::frameSet_info = { "HTMLFrameSetElement", &KJS::HTMLElement::info, &HTMLFrameSetElementTable, 0 };
const ClassInfo KJS::HTMLElement::frame_info = { "HTMLFrameElement", &KJS::HTMLElement::info, &HTMLFrameElementTable, 0 };
const ClassInfo KJS::HTMLElement::iFrame_info = { "HTMLIFrameElement", &KJS::HTMLElement::info, &HTMLIFrameElementTable, 0 };
const ClassInfo KJS::HTMLElement::marquee_info = { "HTMLMarqueeElement", &KJS::HTMLElement::info, &HTMLMarqueeElementTable, 0 };
const ClassInfo* KJS::HTMLElement::classInfo() const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
switch (element.elementId()) {
case ID_HTML:
return &html_info;
case ID_HEAD:
return &head_info;
case ID_LINK:
return &link_info;
case ID_TITLE:
return &title_info;
case ID_META:
return &meta_info;
case ID_BASE:
return &base_info;
case ID_ISINDEX:
return &isIndex_info;
case ID_STYLE:
return &style_info;
case ID_BODY:
return &body_info;
case ID_FORM:
return &form_info;
case ID_SELECT:
return &select_info;
case ID_OPTGROUP:
return &optGroup_info;
case ID_OPTION:
return &option_info;
case ID_INPUT:
return &input_info;
case ID_TEXTAREA:
return &textArea_info;
case ID_BUTTON:
return &button_info;
case ID_LABEL:
return &label_info;
case ID_FIELDSET:
return &fieldSet_info;
case ID_LEGEND:
return &legend_info;
case ID_UL:
return &ul_info;
case ID_OL:
return &ol_info;
case ID_DL:
return &dl_info;
case ID_DIR:
return &dir_info;
case ID_MENU:
return &menu_info;
case ID_LI:
return &li_info;
case ID_DIV:
return &div_info;
case ID_P:
return &p_info;
case ID_H1:
case ID_H2:
case ID_H3:
case ID_H4:
case ID_H5:
case ID_H6:
return &heading_info;
case ID_BLOCKQUOTE:
return &blockQuote_info;
case ID_Q:
return &q_info;
case ID_PRE:
return &pre_info;
case ID_BR:
return &br_info;
case ID_BASEFONT:
return &baseFont_info;
case ID_FONT:
return &font_info;
case ID_HR:
return &hr_info;
case ID_INS:
case ID_DEL:
return &mod_info;
case ID_A:
return &a_info;
case ID_CANVAS:
return &canvas_info;
case ID_IMG:
return &img_info;
case ID_OBJECT:
return &object_info;
case ID_PARAM:
return ¶m_info;
case ID_APPLET:
return &applet_info;
case ID_MAP:
return &map_info;
case ID_AREA:
return &area_info;
case ID_SCRIPT:
return &script_info;
case ID_TABLE:
return &table_info;
case ID_CAPTION:
return &caption_info;
case ID_COL:
return &col_info;
case ID_THEAD:
return &tablesection_info;
case ID_TBODY:
return &tablesection_info;
case ID_TFOOT:
return &tablesection_info;
case ID_TR:
return &tr_info;
case ID_TH:
return &tablecell_info;
case ID_TD:
return &tablecell_info;
case ID_FRAMESET:
return &frameSet_info;
case ID_FRAME:
return &frame_info;
case ID_IFRAME:
return &iFrame_info;
case ID_MARQUEE:
return &marquee_info;
default:
return &info;
}
}
Value KJS::HTMLElement::tryGet(ExecState *exec, const Identifier &propertyName) const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLElement::tryGet " << propertyName.qstring() << " thisTag=" << element.tagName().string() << endl;
#endif
switch (element.elementId()) {
case ID_FORM: {
DOM::HTMLFormElement form = element;
bool ok;
uint u = propertyName.toULong(&ok);
if (ok)
return getDOMNode(exec,form.elements().item(u));
KJS::HTMLCollection coll(exec,form.elements());
Value namedItems = coll.getNamedItems(exec, propertyName);
if (namedItems.type() != UndefinedType)
return namedItems;
}
break;
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
bool ok;
uint u = propertyName.toULong(&ok);
if (ok)
return getDOMNode(exec,select.options().item(u)); }
break;
case ID_FRAMESET: {
DOM::Node frame = element.children().namedItem(propertyName.string());
if (!frame.isNull() && frame.elementId() == ID_FRAME) {
DOM::DocumentImpl* doc = static_cast<DOM::HTMLFrameElementImpl *>(frame.handle())->contentDocument();
if (doc) {
KHTMLPart* part = doc->part();
if (part) {
Window *window = Window::retrieveWindow(part);
if (window) {
return Value(window);
}
}
}
}
}
break;
case ID_FRAME:
case ID_IFRAME: {
DOM::DocumentImpl* doc = static_cast<DOM::HTMLFrameElementImpl *>(element.handle())->contentDocument();
if ( doc ) {
KHTMLPart* part = doc->part();
if ( part ) {
Object globalObject = Object::dynamicCast( Window::retrieve( part ) );
if ( !globalObject.isNull() && static_cast<ObjectImp *>(globalObject.imp())->getDirect( propertyName ) )
return globalObject.get( exec, propertyName );
}
}
}
break;
#if APPLE_CHANGES
case ID_EMBED:
case ID_OBJECT:
case ID_APPLET: {
if (propertyName == "__apple_runtime_object") {
return getRuntimeObject(exec,element);
}
Value domValue = getDOMNode(exec,element);
Value runtimeObject = getRuntimeObject(exec,element);
if (!runtimeObject.isNull()) {
ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
if (imp->hasProperty(exec, propertyName)) {
return imp->get (exec, propertyName);
}
}
}
break;
#endif
default:
break;
}
const HashTable* table = classInfo()->propHashTable; const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
if (entry->attr & Function)
return lookupOrCreateFunction<KJS::HTMLElementFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
return getValueProperty(exec, entry->value);
}
return DOMObjectLookupGet<KJS::HTMLElementFunction, KJS::HTMLElement, DOMElement>(exec, propertyName, &KJS::HTMLElementTable, this);
}
#if APPLE_CHANGES
bool KJS::HTMLElement::implementsCall() const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
switch (element.elementId()) {
case ID_EMBED:
case ID_OBJECT:
case ID_APPLET: {
DOM::DocumentImpl* doc = element.handle()->getDocument();
KJSProxy *proxy = KJSProxy::proxy(doc->part());
ExecState *exec = proxy->interpreter()->globalExec();
Value domValue = getDOMNode(exec,element);
Value runtimeObject = getRuntimeObject(exec,element);
if (!runtimeObject.isNull()) {
ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
return imp->implementsCall ();
}
}
break;
default:
break;
}
return false;
}
Value KJS::HTMLElement::call(ExecState *exec, Object &thisObj, const List&args)
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
switch (element.elementId()) {
case ID_EMBED:
case ID_OBJECT:
case ID_APPLET: {
Value domValue = getDOMNode(exec,element);
Value runtimeObject = getRuntimeObject(exec,element);
if (!runtimeObject.isNull()) {
ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
return Object(imp).call (exec, thisObj, args);
}
}
break;
default:
break;
}
return Undefined();
}
#endif
static Value getInputSelectionStart(HTMLInputElement &input)
{
if (input.canHaveSelection()) {
return Number(input.selectionStart());
}
return Undefined();
}
static Value getInputSelectionEnd(HTMLInputElement &input)
{
if (input.canHaveSelection()) {
return Number(input.selectionEnd());
}
return Undefined();
}
Value KJS::HTMLElement::getValueProperty(ExecState *exec, int token) const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
switch (element.elementId()) {
case ID_HTML: {
DOM::HTMLHtmlElement html = element;
if (token == HtmlVersion) return String(html.version());
}
break;
case ID_HEAD: {
DOM::HTMLHeadElement head = element;
if (token == HeadProfile) return String(head.profile());
}
break;
case ID_LINK: {
DOM::HTMLLinkElement link = element;
switch (token) {
case LinkDisabled: return Boolean(link.disabled());
case LinkCharset: return String(link.charset());
case LinkHref: return String(link.href());
case LinkHrefLang: return String(link.hreflang());
case LinkMedia: return String(link.media());
case LinkRel: return String(link.rel());
case LinkRev: return String(link.rev());
case LinkTarget: return String(link.target());
case LinkType: return String(link.type());
case LinkSheet: return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
}
}
break;
case ID_TITLE: {
DOM::HTMLTitleElement title = element;
switch (token) {
case TitleText: return String(title.text());
}
}
break;
case ID_META: {
DOM::HTMLMetaElement meta = element;
switch (token) {
case MetaContent: return String(meta.content());
case MetaHttpEquiv: return String(meta.httpEquiv());
case MetaName: return String(meta.name());
case MetaScheme: return String(meta.scheme());
}
}
break;
case ID_BASE: {
DOM::HTMLBaseElement base = element;
switch (token) {
case BaseHref: return String(base.href());
case BaseTarget: return String(base.target());
}
}
break;
case ID_ISINDEX: {
DOM::HTMLIsIndexElement isindex = element;
switch (token) {
case IsIndexForm: return getDOMNode(exec,isindex.form()); case IsIndexPrompt: return String(isindex.prompt());
}
}
break;
case ID_STYLE: {
DOM::HTMLStyleElement style = element;
switch (token) {
case StyleDisabled: return Boolean(style.disabled());
case StyleMedia: return String(style.media());
case StyleType: return String(style.type());
case StyleSheet: return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
}
}
break;
case ID_BODY: {
DOM::HTMLBodyElement body = element;
switch (token) {
case BodyALink: return String(body.aLink());
case BodyBackground: return String(body.background());
case BodyBgColor: return String(body.bgColor());
case BodyLink: return String(body.link());
case BodyText: return String(body.text());
case BodyVLink: return String(body.vLink());
default:
DOM::DocumentImpl* docimpl = node.handle()->getDocument();
if (docimpl) {
docimpl->updateLayoutIgnorePendingStylesheets();
}
switch (token) {
case BodyScrollLeft:
return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsX() : 0);
case BodyScrollTop:
return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsY() : 0);
case BodyScrollHeight: return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsHeight() : 0);
case BodyScrollWidth: return Number(body.ownerDocument().view() ? body.ownerDocument().view()->contentsWidth() : 0);
}
}
}
break;
case ID_FORM: {
DOM::HTMLFormElement form = element;
switch (token) {
case FormElements: return getHTMLCollection(exec,form.elements());
case FormLength: return Number(form.length());
case FormName: return String(form.name());
case FormAcceptCharset: return String(form.acceptCharset());
case FormAction: return String(form.action());
case FormEncType: return String(form.enctype());
case FormMethod: return String(form.method());
case FormTarget: return String(form.target());
}
}
break;
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
switch (token) {
case SelectType: return String(select.type());
case SelectSelectedIndex: return Number(select.selectedIndex());
case SelectValue: return String(select.value());
case SelectLength: return Number(select.length());
case SelectForm: return getDOMNode(exec,select.form()); case SelectOptions: return getSelectHTMLCollection(exec, select.options(), select); case SelectDisabled: return Boolean(select.disabled());
case SelectMultiple: return Boolean(select.multiple());
case SelectName: return String(select.name());
case SelectSize: return Number(select.size());
case SelectTabIndex: return Number(select.tabIndex());
}
}
break;
case ID_OPTGROUP: {
DOM::HTMLOptGroupElement optgroup = element;
switch (token) {
case OptGroupDisabled: return Boolean(optgroup.disabled());
case OptGroupLabel: return String(optgroup.label());
}
}
break;
case ID_OPTION: {
DOM::HTMLOptionElement option = element;
switch (token) {
case OptionForm: return getDOMNode(exec,option.form()); case OptionDefaultSelected: return Boolean(option.defaultSelected());
case OptionText: return String(option.text());
case OptionIndex: return Number(option.index());
case OptionDisabled: return Boolean(option.disabled());
case OptionLabel: return String(option.label());
case OptionSelected: return Boolean(option.selected());
case OptionValue: return String(option.value());
}
}
break;
case ID_INPUT: {
DOM::HTMLInputElement input = element;
switch (token) {
case InputDefaultValue: return String(input.defaultValue());
case InputDefaultChecked: return Boolean(input.defaultChecked());
case InputForm: return getDOMNode(exec,input.form()); case InputAccept: return String(input.accept());
case InputAccessKey: return String(input.accessKey());
case InputAlign: return String(input.align());
case InputAlt: return String(input.alt());
case InputChecked: return Boolean(input.checked());
case InputDisabled: return Boolean(input.disabled());
case InputMaxLength: return Number(input.maxLength());
case InputName: return String(input.name());
case InputReadOnly: return Boolean(input.readOnly());
case InputSelectionStart: return getInputSelectionStart(input);
case InputSelectionEnd: return getInputSelectionEnd(input);
case InputSize: return String(input.size());
case InputSrc: return String(input.src());
case InputTabIndex: return Number(input.tabIndex());
case InputType: return String(input.type());
case InputUseMap: return String(input.useMap());
case InputValue: return String(input.value());
}
}
break;
case ID_TEXTAREA: {
DOM::HTMLTextAreaElement textarea = element;
switch (token) {
case TextAreaDefaultValue: return String(textarea.defaultValue());
case TextAreaForm: return getDOMNode(exec,textarea.form()); case TextAreaAccessKey: return String(textarea.accessKey());
case TextAreaCols: return Number(textarea.cols());
case TextAreaDisabled: return Boolean(textarea.disabled());
case TextAreaName: return String(textarea.name());
case TextAreaReadOnly: return Boolean(textarea.readOnly());
case TextAreaRows: return Number(textarea.rows());
case TextAreaSelectionStart: return Number(textarea.selectionStart());
case TextAreaSelectionEnd: return Number(textarea.selectionEnd());
case TextAreaTabIndex: return Number(textarea.tabIndex());
case TextAreaType: return String(textarea.type());
case TextAreaValue: return String(textarea.value());
}
}
break;
case ID_BUTTON: {
DOM::HTMLButtonElement button = element;
switch (token) {
case ButtonForm: return getDOMNode(exec,button.form()); case ButtonAccessKey: return String(button.accessKey());
case ButtonDisabled: return Boolean(button.disabled());
case ButtonName: return String(button.name());
case ButtonTabIndex: return Number(button.tabIndex());
case ButtonType: return String(button.type());
case ButtonValue: return String(button.value());
}
}
break;
case ID_LABEL: {
DOM::HTMLLabelElement label = element;
switch (token) {
case LabelForm: return getDOMNode(exec,label.form()); case LabelAccessKey: return String(label.accessKey());
case LabelHtmlFor: return String(label.htmlFor());
}
}
break;
case ID_FIELDSET: {
DOM::HTMLFieldSetElement fieldSet = element;
switch (token) {
case FieldSetForm: return getDOMNode(exec,fieldSet.form()); }
}
break;
case ID_LEGEND: {
DOM::HTMLLegendElement legend = element;
switch (token) {
case LegendForm: return getDOMNode(exec,legend.form()); case LegendAccessKey: return String(legend.accessKey());
case LegendAlign: return String(legend.align());
}
}
break;
case ID_UL: {
DOM::HTMLUListElement uList = element;
switch (token) {
case UListCompact: return Boolean(uList.compact());
case UListType: return String(uList.type());
}
}
break;
case ID_OL: {
DOM::HTMLOListElement oList = element;
switch (token) {
case OListCompact: return Boolean(oList.compact());
case OListStart: return Number(oList.start());
case OListType: return String(oList.type());
}
}
break;
case ID_DL: {
DOM::HTMLDListElement dList = element;
switch (token) {
case DListCompact: return Boolean(dList.compact());
}
}
break;
case ID_DIR: {
DOM::HTMLDirectoryElement directory = element;
switch (token) {
case DirectoryCompact: return Boolean(directory.compact());
}
}
break;
case ID_MENU: {
DOM::HTMLMenuElement menu = element;
switch (token) {
case MenuCompact: return Boolean(menu.compact());
}
}
break;
case ID_LI: {
DOM::HTMLLIElement li = element;
switch (token) {
case LIType: return String(li.type());
case LIValue: return Number(li.value());
}
}
break;
case ID_DIV: {
DOM::HTMLDivElement div = element;
switch (token) {
case DivAlign: return String(div.align());
}
}
break;
case ID_P: {
DOM::HTMLParagraphElement paragraph = element;
switch (token) {
case ParagraphAlign: return String(paragraph.align());
}
}
break;
case ID_H1:
case ID_H2:
case ID_H3:
case ID_H4:
case ID_H5:
case ID_H6: {
DOM::HTMLHeadingElement heading = element;
switch (token) {
case HeadingAlign: return String(heading.align());
}
}
break;
case ID_BLOCKQUOTE: {
DOM::HTMLBlockquoteElement blockquote = element;
switch (token) {
case BlockQuoteCite: return String(blockquote.cite());
}
}
case ID_Q: {
DOM::HTMLQuoteElement quote = element;
switch (token) {
case QuoteCite: return String(quote.cite());
}
}
case ID_PRE: {
DOM::HTMLPreElement pre = element;
switch (token) {
case PreWidth: return Number(pre.width());
}
}
break;
case ID_BR: {
DOM::HTMLBRElement br = element;
switch (token) {
case BRClear: return String(br.clear());
}
}
break;
case ID_BASEFONT: {
DOM::HTMLBaseFontElement baseFont = element;
switch (token) {
case BaseFontColor: return String(baseFont.color());
case BaseFontFace: return String(baseFont.face());
case BaseFontSize: return String(baseFont.size());
}
}
break;
case ID_FONT: {
DOM::HTMLFontElement font = element;
switch (token) {
case FontColor: return String(font.color());
case FontFace: return String(font.face());
case FontSize: return String(font.size());
}
}
break;
case ID_HR: {
DOM::HTMLHRElement hr = element;
switch (token) {
case HRAlign: return String(hr.align());
case HRNoShade: return Boolean(hr.noShade());
case HRSize: return String(hr.size());
case HRWidth: return String(hr.width());
}
}
break;
case ID_INS:
case ID_DEL: {
DOM::HTMLModElement mod = element;
switch (token) {
case ModCite: return String(mod.cite());
case ModDateTime: return String(mod.dateTime());
}
}
break;
case ID_A: {
DOM::HTMLAnchorElement anchor = element;
switch (token) {
case AnchorAccessKey: return String(anchor.accessKey());
case AnchorCharset: return String(anchor.charset());
case AnchorCoords: return String(anchor.coords());
case AnchorHref: return String(anchor.href());
case AnchorHrefLang: return String(anchor.hreflang());
case AnchorHash: return String('#'+KURL(anchor.href().string()).ref());
case AnchorHost: return String(KURL(anchor.href().string()).host());
case AnchorHostname: {
KURL url(anchor.href().string());
kdDebug(6070) << "anchor::hostname uses:" <<url.url()<<endl;
if (url.port()==0)
return String(url.host());
else
return String(url.host() + ":" + QString::number(url.port()));
}
case AnchorPathName: return String(KURL(anchor.href().string()).path());
case AnchorPort: return String(QString::number(KURL(anchor.href().string()).port()));
case AnchorProtocol: return String(KURL(anchor.href().string()).protocol()+":");
case AnchorSearch: return String(KURL(anchor.href().string()).query());
case AnchorName: return String(anchor.name());
case AnchorRel: return String(anchor.rel());
case AnchorRev: return String(anchor.rev());
case AnchorShape: return String(anchor.shape());
case AnchorTabIndex: return Number(anchor.tabIndex());
case AnchorTarget: return String(anchor.target());
case AnchorType: return String(anchor.type());
case AnchorText: {
DOM::DocumentImpl* docimpl = node.handle()->getDocument();
if (docimpl) {
docimpl->updateLayoutIgnorePendingStylesheets();
}
}
return String(anchor.innerText());
}
}
break;
case ID_IMG: {
DOM::HTMLImageElement image = element;
switch (token) {
case ImageName: return String(image.name());
case ImageAlign: return String(image.align());
case ImageAlt: return String(image.alt());
case ImageBorder: return Number(image.border());
case ImageHeight: return Number(static_cast<DOM::HTMLImageElementImpl *>(image.handle())->height(true));
case ImageHspace: return Number(image.hspace());
case ImageIsMap: return Boolean(image.isMap());
case ImageLongDesc: return String(image.longDesc());
case ImageSrc: return String(image.src());
case ImageUseMap: return String(image.useMap());
case ImageVspace: return Number(image.vspace());
case ImageWidth: return Number(static_cast<DOM::HTMLImageElementImpl *>(image.handle())->width(true));
case ImageX: return Number(image.x());
case ImageY: return Number(image.y());
}
}
break;
case ID_OBJECT: {
DOM::HTMLObjectElement object = element;
switch (token) {
case ObjectForm: return getDOMNode(exec,object.form()); case ObjectCode: return String(object.code());
case ObjectAlign: return String(object.align());
case ObjectArchive: return String(object.archive());
case ObjectBorder: return String(object.border());
case ObjectCodeBase: return String(object.codeBase());
case ObjectCodeType: return String(object.codeType());
case ObjectContentDocument: return checkNodeSecurity(exec,object.contentDocument()) ?
getDOMNode(exec, object.contentDocument()) : Undefined();
case ObjectData: return String(object.data());
case ObjectDeclare: return Boolean(object.declare());
case ObjectHeight: return String(object.height());
case ObjectHspace: return String(object.hspace());
case ObjectName: return String(object.name());
case ObjectStandby: return String(object.standby());
case ObjectTabIndex: return Number(object.tabIndex());
case ObjectType: return String(object.type());
case ObjectUseMap: return String(object.useMap());
case ObjectVspace: return String(object.vspace());
case ObjectWidth: return String(object.width());
}
}
break;
case ID_PARAM: {
DOM::HTMLParamElement param = element;
switch (token) {
case ParamName: return String(param.name());
case ParamType: return String(param.type());
case ParamValue: return String(param.value());
case ParamValueType: return String(param.valueType());
}
}
break;
case ID_APPLET: {
DOM::HTMLAppletElement applet = element;
switch (token) {
case AppletAlign: return String(applet.align());
case AppletAlt: return String(applet.alt());
case AppletArchive: return String(applet.archive());
case AppletCode: return String(applet.code());
case AppletCodeBase: return String(applet.codeBase());
case AppletHeight: return String(applet.height());
case AppletHspace: return String(applet.hspace());
case AppletName: return String(applet.name());
case AppletObject: return String(applet.object());
case AppletVspace: return String(applet.vspace());
case AppletWidth: return String(applet.width());
}
}
break;
case ID_MAP: {
DOM::HTMLMapElement map = element;
switch (token) {
case MapAreas: return getHTMLCollection(exec, map.areas()); case MapName: return String(map.name());
}
}
break;
case ID_AREA: {
DOM::HTMLAreaElement area = element;
switch (token) {
case AreaAccessKey: return String(area.accessKey());
case AreaAlt: return String(area.alt());
case AreaCoords: return String(area.coords());
case AreaHref: return String(area.href());
case AreaHash: return String('#'+KURL(area.href().string()).ref());
case AreaHost: return String(KURL(area.href().string()).host());
case AreaHostName: {
KURL url(area.href().string());
kdDebug(6070) << "link::hostname uses:" <<url.url()<<endl;
if (url.port()==0)
return String(url.host());
else
return String(url.host() + ":" + QString::number(url.port()));
}
case AreaPathName: return String(KURL(area.href().string()).path());
case AreaPort: return String(QString::number(KURL(area.href().string()).port()));
case AreaProtocol: return String(KURL(area.href().string()).protocol()+":");
case AreaSearch: return String(KURL(area.href().string()).query());
case AreaNoHref: return Boolean(area.noHref());
case AreaShape: return String(area.shape());
case AreaTabIndex: return Number(area.tabIndex());
case AreaTarget: return String(area.target());
}
}
break;
case ID_SCRIPT: {
DOM::HTMLScriptElement script = element;
switch (token) {
case ScriptText: return String(script.text());
case ScriptHtmlFor: return String(script.htmlFor());
case ScriptEvent: return String(script.event());
case ScriptCharset: return String(script.charset());
case ScriptDefer: return Boolean(script.defer());
case ScriptSrc: return String(script.src());
case ScriptType: return String(script.type());
}
}
break;
case ID_TABLE: {
DOM::HTMLTableElement table = element;
switch (token) {
case TableCaption: return getDOMNode(exec,table.caption()); case TableTHead: return getDOMNode(exec,table.tHead()); case TableTFoot: return getDOMNode(exec,table.tFoot()); case TableRows: return getHTMLCollection(exec,table.rows()); case TableTBodies: return getHTMLCollection(exec,table.tBodies()); case TableAlign: return String(table.align());
case TableBgColor: return String(table.bgColor());
case TableBorder: return String(table.border());
case TableCellPadding: return String(table.cellPadding());
case TableCellSpacing: return String(table.cellSpacing());
case TableFrame: return String(table.frame());
case TableRules: return String(table.rules());
case TableSummary: return String(table.summary());
case TableWidth: return String(table.width());
}
}
break;
case ID_CAPTION: {
DOM::HTMLTableCaptionElement tableCaption;
switch (token) {
case TableCaptionAlign: return String(tableCaption.align());
}
}
break;
case ID_COL: {
DOM::HTMLTableColElement tableCol = element;
switch (token) {
case TableColAlign: return String(tableCol.align());
case TableColCh: return String(tableCol.ch());
case TableColChOff: return String(tableCol.chOff());
case TableColSpan: return Number(tableCol.span());
case TableColVAlign: return String(tableCol.vAlign());
case TableColWidth: return String(tableCol.width());
}
}
break;
case ID_THEAD:
case ID_TBODY:
case ID_TFOOT: {
DOM::HTMLTableSectionElement tableSection = element;
switch (token) {
case TableSectionAlign: return String(tableSection.align());
case TableSectionCh: return String(tableSection.ch());
case TableSectionChOff: return String(tableSection.chOff());
case TableSectionVAlign: return String(tableSection.vAlign());
case TableSectionRows: return getHTMLCollection(exec,tableSection.rows()); }
}
break;
case ID_TR: {
DOM::HTMLTableRowElement tableRow = element;
switch (token) {
case TableRowRowIndex: return Number(tableRow.rowIndex());
case TableRowSectionRowIndex: return Number(tableRow.sectionRowIndex());
case TableRowCells: return getHTMLCollection(exec,tableRow.cells()); case TableRowAlign: return String(tableRow.align());
case TableRowBgColor: return String(tableRow.bgColor());
case TableRowCh: return String(tableRow.ch());
case TableRowChOff: return String(tableRow.chOff());
case TableRowVAlign: return String(tableRow.vAlign());
}
}
break;
case ID_TH:
case ID_TD: {
DOM::HTMLTableCellElement tableCell = element;
switch (token) {
case TableCellCellIndex: return Number(tableCell.cellIndex());
case TableCellAbbr: return String(tableCell.abbr());
case TableCellAlign: return String(tableCell.align());
case TableCellAxis: return String(tableCell.axis());
case TableCellBgColor: return String(tableCell.bgColor());
case TableCellCh: return String(tableCell.ch());
case TableCellChOff: return String(tableCell.chOff());
case TableCellColSpan: return Number(tableCell.colSpan());
case TableCellHeaders: return String(tableCell.headers());
case TableCellHeight: return String(tableCell.height());
case TableCellNoWrap: return Boolean(tableCell.noWrap());
case TableCellRowSpan: return Number(tableCell.rowSpan());
case TableCellScope: return String(tableCell.scope());
case TableCellVAlign: return String(tableCell.vAlign());
case TableCellWidth: return String(tableCell.width());
}
}
break;
case ID_FRAMESET: {
DOM::HTMLFrameSetElement frameSet = element;
switch (token) {
case FrameSetCols: return String(frameSet.cols());
case FrameSetRows: return String(frameSet.rows());
}
}
break;
case ID_FRAME: {
DOM::HTMLFrameElement frameElement = element;
switch (token) {
case FrameContentDocument: return checkNodeSecurity(exec,frameElement.contentDocument()) ?
getDOMNode(exec, frameElement.contentDocument()) : Undefined();
case FrameContentWindow: return checkNodeSecurity(exec,frameElement.contentDocument())
? Window::retrieve(static_cast<HTMLFrameElementImpl *>(frameElement.handle())->contentPart())
: Undefined();
case FrameFrameBorder: return String(frameElement.frameBorder());
case FrameLongDesc: return String(frameElement.longDesc());
case FrameMarginHeight: return String(frameElement.marginHeight());
case FrameMarginWidth: return String(frameElement.marginWidth());
case FrameName: return String(frameElement.name());
case FrameNoResize: return Boolean(frameElement.noResize());
case FrameScrolling: return String(frameElement.scrolling());
case FrameSrc:
case FrameLocation: return String(frameElement.src());
}
}
break;
case ID_IFRAME: {
DOM::HTMLIFrameElement iFrame = element;
switch (token) {
case IFrameAlign: return String(iFrame.align());
case IFrameDocument: case IFrameContentDocument: return checkNodeSecurity(exec,iFrame.contentDocument()) ?
getDOMNode(exec, iFrame.contentDocument()) : Undefined();
case IFrameContentWindow: return checkNodeSecurity(exec,iFrame.contentDocument())
? Window::retrieve(static_cast<HTMLIFrameElementImpl *>(iFrame.handle())->contentPart())
: Undefined();
case IFrameFrameBorder: return String(iFrame.frameBorder());
case IFrameHeight: return String(iFrame.height());
case IFrameLongDesc: return String(iFrame.longDesc());
case IFrameMarginHeight: return String(iFrame.marginHeight());
case IFrameMarginWidth: return String(iFrame.marginWidth());
case IFrameName: return String(iFrame.name());
case IFrameScrolling: return String(iFrame.scrolling());
case IFrameSrc: return String(iFrame.src());
case IFrameWidth: return String(iFrame.width());
}
break;
}
}
switch (token) {
case ElementId:
return String(element.id());
case ElementTitle:
return String(element.title());
case ElementLang:
return String(element.lang());
case ElementDir:
return String(element.dir());
case ElementClassName:
return String(element.className());
case ElementInnerHTML:
return String(element.innerHTML());
case ElementInnerText:
{
DOM::DocumentImpl* docimpl = node.handle()->getDocument();
if (docimpl) {
docimpl->updateLayoutIgnorePendingStylesheets();
}
}
return String(element.innerText());
case ElementOuterHTML:
return String(element.outerHTML());
case ElementOuterText:
return String(element.outerText());
case ElementDocument:
return getDOMNode(exec,element.ownerDocument());
case ElementChildren:
return getHTMLCollection(exec,element.children());
case ElementContentEditable:
return String(element.contentEditable());
case ElementIsContentEditable:
return Boolean(element.isContentEditable());
}
kdWarning() << "HTMLElement::getValueProperty unhandled token " << token << endl;
return Undefined();
}
bool KJS::HTMLElement::hasOwnProperty(ExecState *exec, const Identifier &propertyName) const
{
#ifdef KJS_VERBOSE
#endif
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
switch (element.elementId()) {
case ID_FORM: {
DOM::HTMLFormElement form = element;
bool ok;
uint u = propertyName.toULong(&ok);
if (ok && !(form.elements().item(u).isNull()))
return true;
DOM::Node testnode = form.elements().namedItem(propertyName.string());
if (!testnode.isNull())
return true;
}
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
bool ok;
uint u = propertyName.toULong(&ok);
if (ok && !(select.options().item(u).isNull()))
return true;
}
case ID_INPUT: {
HTMLInputElement input = static_cast<HTMLInputElement>(element);
const HashTable* table = classInfo()->propHashTable;
const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
switch(entry->value) {
case InputSelectionStart:
case InputSelectionEnd:
case InputSetSelectionRange:
return input.canHaveSelection();
default:
break;
}
}
break;
}
default:
break;
}
return DOMElement::hasOwnProperty(exec, propertyName);
}
UString KJS::HTMLElement::toString(ExecState *exec) const
{
if (node.elementId() == ID_A)
return UString(static_cast<const DOM::HTMLAnchorElement&>(node).href());
else
return DOMElement::toString(exec);
}
static void getForm(DOM::HTMLFormElement* form, const DOM::HTMLElement& element)
{
switch (element.elementId()) {
case ID_ISINDEX: {
DOM::HTMLIsIndexElement isindex = element;
*form = isindex.form();
break;
}
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
*form = select.form();
break;
}
case ID_OPTION: {
DOM::HTMLOptionElement option = element;
*form = option.form();
break;
}
case ID_INPUT: {
DOM::HTMLInputElement input = element;
*form = input.form();
break;
}
case ID_TEXTAREA: {
DOM::HTMLTextAreaElement textarea = element;
*form = textarea.form();
break;
}
case ID_LABEL: {
DOM::HTMLLabelElement label = element;
*form = label.form();
break;
}
case ID_FIELDSET: {
DOM::HTMLFieldSetElement fieldset = element;
*form = fieldset.form();
break;
}
case ID_LEGEND: {
DOM::HTMLLegendElement legend = element;
*form = legend.form();
break;
}
case ID_OBJECT: {
DOM::HTMLObjectElement object = element;
*form = object.form();
break;
}
default:
break;
}
}
void KJS::HTMLElement::pushEventHandlerScope(ExecState *exec, ScopeChain &scope) const
{
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element.ownerDocument()).imp()));
DOM::HTMLFormElement formElt;
getForm(&formElt, element);
if (!formElt.isNull())
scope.push(static_cast<ObjectImp *>(getDOMNode(exec, formElt).imp()));
else {
DOM::Node form = element.parentNode();
while (!form.isNull() && form.elementId() != ID_FORM)
form = form.parentNode();
if (!form.isNull())
scope.push(static_cast<ObjectImp *>(getDOMNode(exec, form).imp()));
}
scope.push(static_cast<ObjectImp *>(getDOMNode(exec, element).imp()));
}
HTMLElementFunction::HTMLElementFunction(ExecState *exec, int i, int len)
: DOMFunction(), id(i)
{
Value protect(this);
put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum);
}
Value KJS::HTMLElementFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&KJS::HTMLElement::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
kdDebug() << "KJS::HTMLElementFunction::tryCall " << endl;
DOM::HTMLElement element = static_cast<KJS::HTMLElement *>(thisObj.imp())->toElement();
switch (element.elementId()) {
case ID_FORM: {
DOM::HTMLFormElement form = element;
if (id == KJS::HTMLElement::FormSubmit) {
form.submit();
return Undefined();
}
else if (id == KJS::HTMLElement::FormReset) {
form.reset();
return Undefined();
}
}
break;
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
if (id == KJS::HTMLElement::SelectAdd) {
select.add(KJS::toNode(args[0]),KJS::toNode(args[1]));
return Undefined();
}
else if (id == KJS::HTMLElement::SelectRemove) {
select.remove(int(args[0].toNumber(exec)));
return Undefined();
}
else if (id == KJS::HTMLElement::SelectBlur) {
select.blur();
return Undefined();
}
else if (id == KJS::HTMLElement::SelectFocus) {
select.focus();
return Undefined();
}
}
break;
case ID_INPUT: {
DOM::HTMLInputElement input = element;
if (id == KJS::HTMLElement::InputBlur) {
input.blur();
return Undefined();
}
else if (id == KJS::HTMLElement::InputFocus) {
input.focus();
return Undefined();
}
else if (id == KJS::HTMLElement::InputSelect) {
input.select();
return Undefined();
}
else if (id == KJS::HTMLElement::InputClick) {
input.click();
return Undefined();
}
else if (id == KJS::HTMLElement::InputSetSelectionRange) {
input.setSelectionRange(args[0].toInt32(exec), args[1].toInt32(exec));
return Undefined();
}
}
break;
case ID_BUTTON: {
DOM::HTMLButtonElement button = element;
if (id == KJS::HTMLElement::ButtonBlur) {
button.blur();
return Undefined();
}
else if (id == KJS::HTMLElement::ButtonFocus) {
button.focus();
return Undefined();
}
}
break;
case ID_TEXTAREA: {
DOM::HTMLTextAreaElement textarea = element;
if (id == KJS::HTMLElement::TextAreaBlur) {
textarea.blur();
return Undefined();
}
else if (id == KJS::HTMLElement::TextAreaFocus) {
textarea.focus();
return Undefined();
}
else if (id == KJS::HTMLElement::TextAreaSelect) {
textarea.select();
return Undefined();
}
else if (id == KJS::HTMLElement::TextAreaSetSelectionRange) {
textarea.setSelectionRange(args[0].toInt32(exec), args[1].toInt32(exec));
return Undefined();
}
}
break;
case ID_A: {
DOM::HTMLAnchorElement anchor = element;
if (id == KJS::HTMLElement::AnchorBlur) {
anchor.blur();
return Undefined();
}
else if (id == KJS::HTMLElement::AnchorFocus) {
anchor.focus();
return Undefined();
}
else if (id == KJS::HTMLElement::AnchorToString) {
return String(thisObj.toString(exec));
}
}
break;
case ID_TABLE: {
DOM::HTMLTableElement table = element;
if (id == KJS::HTMLElement::TableCreateTHead)
return getDOMNode(exec,table.createTHead());
else if (id == KJS::HTMLElement::TableDeleteTHead) {
table.deleteTHead();
return Undefined();
}
else if (id == KJS::HTMLElement::TableCreateTFoot)
return getDOMNode(exec,table.createTFoot());
else if (id == KJS::HTMLElement::TableDeleteTFoot) {
table.deleteTFoot();
return Undefined();
}
else if (id == KJS::HTMLElement::TableCreateCaption)
return getDOMNode(exec,table.createCaption());
else if (id == KJS::HTMLElement::TableDeleteCaption) {
table.deleteCaption();
return Undefined();
}
else if (id == KJS::HTMLElement::TableInsertRow)
return getDOMNode(exec,table.insertRow(args[0].toInt32(exec)));
else if (id == KJS::HTMLElement::TableDeleteRow) {
table.deleteRow(args[0].toInt32(exec));
return Undefined();
}
}
break;
case ID_THEAD:
case ID_TBODY:
case ID_TFOOT: {
DOM::HTMLTableSectionElement tableSection = element;
if (id == KJS::HTMLElement::TableSectionInsertRow)
return getDOMNode(exec,tableSection.insertRow(args[0].toInt32(exec)));
else if (id == KJS::HTMLElement::TableSectionDeleteRow) {
tableSection.deleteRow(args[0].toInt32(exec));
return Undefined();
}
}
break;
case ID_TR: {
DOM::HTMLTableRowElement tableRow = element;
if (id == KJS::HTMLElement::TableRowInsertCell)
return getDOMNode(exec,tableRow.insertCell(args[0].toInt32(exec)));
else if (id == KJS::HTMLElement::TableRowDeleteCell) {
tableRow.deleteCell(args[0].toInt32(exec));
return Undefined();
}
}
case ID_MARQUEE: {
if (id == KJS::HTMLElement::MarqueeStart && element.handle()->renderer() &&
element.handle()->renderer()->layer() &&
element.handle()->renderer()->layer()->marquee()) {
element.handle()->renderer()->layer()->marquee()->start();
return Undefined();
}
else if (id == KJS::HTMLElement::MarqueeStop && element.handle()->renderer() &&
element.handle()->renderer()->layer() &&
element.handle()->renderer()->layer()->marquee()) {
element.handle()->renderer()->layer()->marquee()->stop();
return Undefined();
}
break;
}
case ID_CANVAS: {
if (id == KJS::HTMLElement::GetContext) {
if (args.size() == 0 || (args.size() == 1 && args[0].toString(exec).qstring().lower() == "2d")) {
return Object(new Context2D(element));
}
return Undefined();
}
}
break;
}
return Undefined();
}
void KJS::HTMLElement::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
#ifdef KJS_VERBOSE
DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
#endif
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLElement::tryPut " << propertyName.qstring()
<< " thisTag=" << element.tagName().string()
<< " str=" << str.string() << endl;
#endif
switch (element.elementId()) {
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
bool ok;
propertyName.toULong(&ok);
if (ok) {
Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
if ( !coll.isNull() )
coll.put(exec,propertyName,value);
return;
}
}
#if APPLE_CHANGES
case ID_EMBED:
case ID_OBJECT:
case ID_APPLET: {
Value domValue = getDOMNode(exec,element);
Value runtimeObject = getRuntimeObject(exec,element);
if (!runtimeObject.isNull()) {
ObjectImp *imp = static_cast<ObjectImp *>(runtimeObject.imp());
if (imp->canPut(exec, propertyName)) {
return imp->put (exec, propertyName, value);
}
}
}
break;
#endif
break;
default:
break;
}
const HashTable* table = classInfo()->propHashTable; const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
if (entry->attr & Function) {
ObjectImp::put(exec, propertyName, value, attr);
return;
}
else if ((entry->attr & ReadOnly) == 0) {
putValue(exec, entry->value, value, attr);
return;
}
}
DOMObjectLookupPut<KJS::HTMLElement, DOMElement>(exec, propertyName, value, attr, &KJS::HTMLElementTable, this);
}
void KJS::HTMLElement::putValue(ExecState *exec, int token, const Value& value, int)
{
DOM::DOMString str = value.isA(NullType) ? DOM::DOMString() : value.toString(exec).string();
DOMNode *kjsNode = new DOMNode(exec, KJS::toNode(value));
Value nodeValue(kjsNode);
DOM::Node n = kjsNode->toNode();
DOM::HTMLElement element = static_cast<DOM::HTMLElement>(node);
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLElement::putValue "
<< " thisTag=" << element.tagName().string()
<< " token=" << token << endl;
#endif
switch (element.elementId()) {
case ID_HTML: {
DOM::HTMLHtmlElement html = element;
switch (token) {
case HtmlVersion: { html.setVersion(str); return; }
}
}
break;
case ID_HEAD: {
DOM::HTMLHeadElement head = element;
switch (token) {
case HeadProfile: { head.setProfile(str); return; }
}
}
break;
case ID_LINK: {
DOM::HTMLLinkElement link = element;
switch (token) {
case LinkDisabled: { link.setDisabled(value.toBoolean(exec)); return; }
case LinkCharset: { link.setCharset(str); return; }
case LinkHref: { link.setHref(str); return; }
case LinkHrefLang: { link.setHreflang(str); return; }
case LinkMedia: { link.setMedia(str); return; }
case LinkRel: { link.setRel(str); return; }
case LinkRev: { link.setRev(str); return; }
case LinkTarget: { link.setTarget(str); return; }
case LinkType: { link.setType(str); return; }
}
}
break;
case ID_TITLE: {
DOM::HTMLTitleElement title = element;
switch (token) {
case TitleText: { title.setText(str); return; }
}
}
break;
case ID_META: {
DOM::HTMLMetaElement meta = element;
switch (token) {
case MetaContent: { meta.setContent(str); return; }
case MetaHttpEquiv: { meta.setHttpEquiv(str); return; }
case MetaName: { meta.setName(str); return; }
case MetaScheme: { meta.setScheme(str); return; }
}
}
break;
case ID_BASE: {
DOM::HTMLBaseElement base = element;
switch (token) {
case BaseHref: { base.setHref(str); return; }
case BaseTarget: { base.setTarget(str); return; }
}
}
break;
case ID_ISINDEX: {
DOM::HTMLIsIndexElement isindex = element;
switch (token) {
case IsIndexPrompt: { isindex.setPrompt(str); return; }
}
}
break;
case ID_STYLE: {
DOM::HTMLStyleElement style = element;
switch (token) {
case StyleDisabled: { style.setDisabled(value.toBoolean(exec)); return; }
case StyleMedia: { style.setMedia(str); return; }
case StyleType: { style.setType(str); return; }
}
}
break;
case ID_BODY: {
DOM::HTMLBodyElement body = element;
switch (token) {
case BodyALink: { body.setALink(str); return; }
case BodyBackground: { body.setBackground(str); return; }
case BodyBgColor: { body.setBgColor(str); return; }
case BodyLink: { body.setLink(str); return; }
case BodyText: { body.setText(str); return; }
case BodyVLink: { body.setVLink(str); return; }
case BodyScrollLeft:
case BodyScrollTop: {
QScrollView* sview = body.ownerDocument().view();
if (sview) {
DOM::DocumentImpl* docimpl = body.handle()->getDocument();
if (docimpl)
docimpl->updateLayoutIgnorePendingStylesheets();
if (token == BodyScrollLeft)
sview->setContentsPos(value.toInt32(exec), sview->contentsY());
else
sview->setContentsPos(sview->contentsX(), value.toInt32(exec));
}
return;
}
}
}
break;
case ID_FORM: {
DOM::HTMLFormElement form = element;
switch (token) {
case FormName: { form.setName(str); return; }
case FormAcceptCharset: { form.setAcceptCharset(str); return; }
case FormAction: { form.setAction(str.string()); return; }
case FormEncType: { form.setEnctype(str); return; }
case FormMethod: { form.setMethod(str); return; }
case FormTarget: { form.setTarget(str); return; }
}
}
break;
case ID_SELECT: {
DOM::HTMLSelectElement select = element;
switch (token) {
case SelectSelectedIndex: { select.setSelectedIndex(value.toInt32(exec)); return; }
case SelectValue: { select.setValue(str); return; }
case SelectLength: { Object coll = Object::dynamicCast( getSelectHTMLCollection(exec, select.options(), select) );
if ( !coll.isNull() )
coll.put(exec,lengthPropertyName,value);
return;
}
case SelectDisabled: { select.setDisabled(value.toBoolean(exec)); return; }
case SelectMultiple: { select.setMultiple(value.toBoolean(exec)); return; }
case SelectName: { select.setName(str); return; }
case SelectSize: { select.setSize(value.toInt32(exec)); return; }
case SelectTabIndex: { select.setTabIndex(value.toInt32(exec)); return; }
}
}
break;
case ID_OPTGROUP: {
DOM::HTMLOptGroupElement optgroup = element;
switch (token) {
case OptGroupDisabled: { optgroup.setDisabled(value.toBoolean(exec)); return; }
case OptGroupLabel: { optgroup.setLabel(str); return; }
}
}
break;
case ID_OPTION: {
DOM::HTMLOptionElement option = element;
switch (token) {
case OptionDefaultSelected: { option.setDefaultSelected(value.toBoolean(exec)); return; }
case OptionText: { DOM::NodeList nl(option.childNodes());
for (unsigned int i = 0; i < nl.length(); i++) {
if (nl.item(i).nodeType() == DOM::Node::TEXT_NODE) {
static_cast<DOM::Text>(nl.item(i)).setData(str);
return;
}
}
DOM::Text t = option.ownerDocument().createTextNode(str);
try { option.appendChild(t); }
catch(DOM::DOMException& e) {
}
return;
}
case OptionDisabled: { option.setDisabled(value.toBoolean(exec)); return; }
case OptionLabel: { option.setLabel(str); return; }
case OptionSelected: { option.setSelected(value.toBoolean(exec)); return; }
case OptionValue: { option.setValue(str); return; }
}
}
break;
case ID_INPUT: {
DOM::HTMLInputElement input = element;
switch (token) {
case InputDefaultValue: { input.setDefaultValue(str); return; }
case InputDefaultChecked: { input.setDefaultChecked(value.toBoolean(exec)); return; }
case InputAccept: { input.setAccept(str); return; }
case InputAccessKey: { input.setAccessKey(str); return; }
case InputAlign: { input.setAlign(str); return; }
case InputAlt: { input.setAlt(str); return; }
case InputChecked: { input.setChecked(value.toBoolean(exec)); return; }
case InputDisabled: { input.setDisabled(value.toBoolean(exec)); return; }
case InputMaxLength: { input.setMaxLength(value.toInt32(exec)); return; }
case InputName: { input.setName(str); return; }
case InputReadOnly: { input.setReadOnly(value.toBoolean(exec)); return; }
case InputSelectionStart: { input.setSelectionStart(value.toInt32(exec)); return; }
case InputSelectionEnd: { input.setSelectionEnd(value.toInt32(exec)); return; }
case InputSize: { input.setSize(str); return; }
case InputSrc: { input.setSrc(str); return; }
case InputTabIndex: { input.setTabIndex(value.toInt32(exec)); return; }
case InputType: { input.setType(str); return; }
case InputUseMap: { input.setUseMap(str); return; }
case InputValue: { input.setValue(str); return; }
}
}
break;
case ID_TEXTAREA: {
DOM::HTMLTextAreaElement textarea = element;
switch (token) {
case TextAreaDefaultValue: { textarea.setDefaultValue(str); return; }
case TextAreaAccessKey: { textarea.setAccessKey(str); return; }
case TextAreaCols: { textarea.setCols(value.toInt32(exec)); return; }
case TextAreaDisabled: { textarea.setDisabled(value.toBoolean(exec)); return; }
case TextAreaName: { textarea.setName(str); return; }
case TextAreaReadOnly: { textarea.setReadOnly(value.toBoolean(exec)); return; }
case TextAreaRows: { textarea.setRows(value.toInt32(exec)); return; }
case TextAreaSelectionStart: { textarea.setSelectionStart(value.toInt32(exec)); return; }
case TextAreaSelectionEnd: { textarea.setSelectionEnd(value.toInt32(exec)); return; }
case TextAreaTabIndex: { textarea.setTabIndex(value.toInt32(exec)); return; }
case TextAreaValue: { textarea.setValue(str); return; }
}
}
break;
case ID_BUTTON: {
DOM::HTMLButtonElement button = element;
switch (token) {
case ButtonAccessKey: { button.setAccessKey(str); return; }
case ButtonDisabled: { button.setDisabled(value.toBoolean(exec)); return; }
case ButtonName: { button.setName(str); return; }
case ButtonTabIndex: { button.setTabIndex(value.toInt32(exec)); return; }
case ButtonValue: { button.setValue(str); return; }
}
}
break;
case ID_LABEL: {
DOM::HTMLLabelElement label = element;
switch (token) {
case LabelAccessKey: { label.setAccessKey(str); return; }
case LabelHtmlFor: { label.setHtmlFor(str); return; }
}
}
break;
case ID_LEGEND: {
DOM::HTMLLegendElement legend = element;
switch (token) {
case LegendAccessKey: { legend.setAccessKey(str); return; }
case LegendAlign: { legend.setAlign(str); return; }
}
}
break;
case ID_UL: {
DOM::HTMLUListElement uList = element;
switch (token) {
case UListCompact: { uList.setCompact(value.toBoolean(exec)); return; }
case UListType: { uList.setType(str); return; }
}
}
break;
case ID_OL: {
DOM::HTMLOListElement oList = element;
switch (token) {
case OListCompact: { oList.setCompact(value.toBoolean(exec)); return; }
case OListStart: { oList.setStart(value.toInt32(exec)); return; }
case OListType: { oList.setType(str); return; }
}
}
break;
case ID_DL: {
DOM::HTMLDListElement dList = element;
switch (token) {
case DListCompact: { dList.setCompact(value.toBoolean(exec)); return; }
}
}
break;
case ID_DIR: {
DOM::HTMLDirectoryElement directory = element;
switch (token) {
case DirectoryCompact: { directory.setCompact(value.toBoolean(exec)); return; }
}
}
break;
case ID_MENU: {
DOM::HTMLMenuElement menu = element;
switch (token) {
case MenuCompact: { menu.setCompact(value.toBoolean(exec)); return; }
}
}
break;
case ID_LI: {
DOM::HTMLLIElement li = element;
switch (token) {
case LIType: { li.setType(str); return; }
case LIValue: { li.setValue(value.toInt32(exec)); return; }
}
}
break;
case ID_DIV: {
DOM::HTMLDivElement div = element;
switch (token) {
case DivAlign: { div.setAlign(str); return; }
}
}
break;
case ID_P: {
DOM::HTMLParagraphElement paragraph = element;
switch (token) {
case ParagraphAlign: { paragraph.setAlign(str); return; }
}
}
break;
case ID_H1:
case ID_H2:
case ID_H3:
case ID_H4:
case ID_H5:
case ID_H6: {
DOM::HTMLHeadingElement heading = element;
switch (token) {
case HeadingAlign: { heading.setAlign(str); return; }
}
}
break;
case ID_BLOCKQUOTE: {
DOM::HTMLBlockquoteElement blockquote = element;
switch (token) {
case BlockQuoteCite: { blockquote.setCite(str); return; }
}
}
break;
case ID_Q: {
DOM::HTMLQuoteElement quote = element;
switch (token) {
case QuoteCite: { quote.setCite(str); return; }
}
}
break;
case ID_PRE: {
DOM::HTMLPreElement pre = element;
switch (token) {
case PreWidth: { pre.setWidth(value.toInt32(exec)); return; }
}
}
break;
case ID_BR: {
DOM::HTMLBRElement br = element;
switch (token) {
case BRClear: { br.setClear(str); return; }
}
}
break;
case ID_BASEFONT: {
DOM::HTMLBaseFontElement baseFont = element;
switch (token) {
case BaseFontColor: { baseFont.setColor(str); return; }
case BaseFontFace: { baseFont.setFace(str); return; }
case BaseFontSize: { baseFont.setSize(str); return; }
}
}
break;
case ID_FONT: {
DOM::HTMLFontElement font = element;
switch (token) {
case FontColor: { font.setColor(str); return; }
case FontFace: { font.setFace(str); return; }
case FontSize: { font.setSize(str); return; }
}
}
break;
case ID_HR: {
DOM::HTMLHRElement hr = element;
switch (token) {
case HRAlign: { hr.setAlign(str); return; }
case HRNoShade: { hr.setNoShade(value.toBoolean(exec)); return; }
case HRSize: { hr.setSize(str); return; }
case HRWidth: { hr.setWidth(str); return; }
}
}
break;
case ID_INS:
case ID_DEL: {
DOM::HTMLModElement mod = element;
switch (token) {
case ModCite: { mod.setCite(str); return; }
case ModDateTime: { mod.setDateTime(str); return; }
}
}
break;
case ID_A: {
DOM::HTMLAnchorElement anchor = element;
switch (token) {
case AnchorAccessKey: { anchor.setAccessKey(str); return; }
case AnchorCharset: { anchor.setCharset(str); return; }
case AnchorCoords: { anchor.setCoords(str); return; }
case AnchorHref: { anchor.setHref(str); return; }
case AnchorHrefLang: { anchor.setHreflang(str); return; }
case AnchorName: { anchor.setName(str); return; }
case AnchorRel: { anchor.setRel(str); return; }
case AnchorRev: { anchor.setRev(str); return; }
case AnchorShape: { anchor.setShape(str); return; }
case AnchorTabIndex: { anchor.setTabIndex(value.toInt32(exec)); return; }
case AnchorTarget: { anchor.setTarget(str); return; }
case AnchorType: { anchor.setType(str); return; }
}
}
break;
case ID_IMG: {
DOM::HTMLImageElement image = element;
switch (token) {
case ImageName: { image.setName(str); return; }
case ImageAlign: { image.setAlign(str); return; }
case ImageAlt: { image.setAlt(str); return; }
case ImageBorder: { image.setBorder(value.toInt32(exec)); return; }
case ImageHeight: { image.setHeight(value.toInt32(exec)); return; }
case ImageHspace: { image.setHspace(value.toInt32(exec)); return; }
case ImageIsMap: { image.setIsMap(value.toBoolean(exec)); return; }
case ImageLongDesc: { image.setLongDesc(str); return; }
case ImageSrc: { image.setSrc(str); return; }
case ImageUseMap: { image.setUseMap(str); return; }
case ImageVspace: { image.setVspace(value.toInt32(exec)); return; }
case ImageWidth: { image.setWidth(value.toInt32(exec)); return; }
}
}
break;
case ID_OBJECT: {
DOM::HTMLObjectElement object = element;
switch (token) {
case ObjectCode: { object.setCode(str); return; }
case ObjectAlign: { object.setAlign(str); return; }
case ObjectArchive: { object.setArchive(str); return; }
case ObjectBorder: { object.setBorder(str); return; }
case ObjectCodeBase: { object.setCodeBase(str); return; }
case ObjectCodeType: { object.setCodeType(str); return; }
case ObjectData: { object.setData(str); return; }
case ObjectDeclare: { object.setDeclare(value.toBoolean(exec)); return; }
case ObjectHeight: { object.setHeight(str); return; }
case ObjectHspace: { object.setHspace(str); return; }
case ObjectName: { object.setName(str); return; }
case ObjectStandby: { object.setStandby(str); return; }
case ObjectTabIndex: { object.setTabIndex(value.toInt32(exec)); return; }
case ObjectType: { object.setType(str); return; }
case ObjectUseMap: { object.setUseMap(str); return; }
case ObjectVspace: { object.setVspace(str); return; }
case ObjectWidth: { object.setWidth(str); return; }
}
}
break;
case ID_PARAM: {
DOM::HTMLParamElement param = element;
switch (token) {
case ParamName: { param.setName(str); return; }
case ParamType: { param.setType(str); return; }
case ParamValue: { param.setValue(str); return; }
case ParamValueType: { param.setValueType(str); return; }
}
}
break;
case ID_APPLET: {
DOM::HTMLAppletElement applet = element;
switch (token) {
case AppletAlign: { applet.setAlign(str); return; }
case AppletAlt: { applet.setAlt(str); return; }
case AppletArchive: { applet.setArchive(str); return; }
case AppletCode: { applet.setCode(str); return; }
case AppletCodeBase: { applet.setCodeBase(str); return; }
case AppletHeight: { applet.setHeight(str); return; }
case AppletHspace: { applet.setHspace(str); return; }
case AppletName: { applet.setName(str); return; }
case AppletObject: { applet.setObject(str); return; }
case AppletVspace: { applet.setVspace(str); return; }
case AppletWidth: { applet.setWidth(str); return; }
}
}
break;
case ID_MAP: {
DOM::HTMLMapElement map = element;
switch (token) {
case MapName: { map.setName(str); return; }
}
}
break;
case ID_AREA: {
DOM::HTMLAreaElement area = element;
switch (token) {
case AreaAccessKey: { area.setAccessKey(str); return; }
case AreaAlt: { area.setAlt(str); return; }
case AreaCoords: { area.setCoords(str); return; }
case AreaHref: { area.setHref(str); return; }
case AreaNoHref: { area.setNoHref(value.toBoolean(exec)); return; }
case AreaShape: { area.setShape(str); return; }
case AreaTabIndex: { area.setTabIndex(value.toInt32(exec)); return; }
case AreaTarget: { area.setTarget(str); return; }
}
}
break;
case ID_SCRIPT: {
DOM::HTMLScriptElement script = element;
switch (token) {
case ScriptText: { script.setText(str); return; }
case ScriptHtmlFor: { script.setHtmlFor(str); return; }
case ScriptEvent: { script.setEvent(str); return; }
case ScriptCharset: { script.setCharset(str); return; }
case ScriptDefer: { script.setDefer(value.toBoolean(exec)); return; }
case ScriptSrc: { script.setSrc(str); return; }
case ScriptType: { script.setType(str); return; }
}
}
break;
case ID_TABLE: {
DOM::HTMLTableElement table = element;
switch (token) {
case TableCaption: { table.setCaption(n); return; } case TableTHead: { table.setTHead(n); return; } case TableTFoot: { table.setTFoot(n); return; } case TableAlign: { table.setAlign(str); return; }
case TableBgColor: { table.setBgColor(str); return; }
case TableBorder: { table.setBorder(str); return; }
case TableCellPadding: { table.setCellPadding(str); return; }
case TableCellSpacing: { table.setCellSpacing(str); return; }
case TableFrame: { table.setFrame(str); return; }
case TableRules: { table.setRules(str); return; }
case TableSummary: { table.setSummary(str); return; }
case TableWidth: { table.setWidth(str); return; }
}
}
break;
case ID_CAPTION: {
DOM::HTMLTableCaptionElement tableCaption;
switch (token) {
case TableAlign: { tableCaption.setAlign(str); return; }
}
}
break;
case ID_COL: {
DOM::HTMLTableColElement tableCol = element;
switch (token) {
case TableColAlign: { tableCol.setAlign(str); return; }
case TableColCh: { tableCol.setCh(str); return; }
case TableColChOff: { tableCol.setChOff(str); return; }
case TableColSpan: { tableCol.setSpan(value.toInt32(exec)); return; }
case TableColVAlign: { tableCol.setVAlign(str); return; }
case TableColWidth: { tableCol.setWidth(str); return; }
}
}
break;
case ID_THEAD:
case ID_TBODY:
case ID_TFOOT: {
DOM::HTMLTableSectionElement tableSection = element;
switch (token) {
case TableSectionAlign: { tableSection.setAlign(str); return; }
case TableSectionCh: { tableSection.setCh(str); return; }
case TableSectionChOff: { tableSection.setChOff(str); return; }
case TableSectionVAlign: { tableSection.setVAlign(str); return; }
}
}
break;
case ID_TR: {
DOM::HTMLTableRowElement tableRow = element;
switch (token) {
case TableRowAlign: { tableRow.setAlign(str); return; }
case TableRowBgColor: { tableRow.setBgColor(str); return; }
case TableRowCh: { tableRow.setCh(str); return; }
case TableRowChOff: { tableRow.setChOff(str); return; }
case TableRowVAlign: { tableRow.setVAlign(str); return; }
}
}
break;
case ID_TH:
case ID_TD: {
DOM::HTMLTableCellElement tableCell = element;
switch (token) {
case TableCellAbbr: { tableCell.setAbbr(str); return; }
case TableCellAlign: { tableCell.setAlign(str); return; }
case TableCellAxis: { tableCell.setAxis(str); return; }
case TableCellBgColor: { tableCell.setBgColor(str); return; }
case TableCellCh: { tableCell.setCh(str); return; }
case TableCellChOff: { tableCell.setChOff(str); return; }
case TableCellColSpan: { tableCell.setColSpan(value.toInt32(exec)); return; }
case TableCellHeaders: { tableCell.setHeaders(str); return; }
case TableCellHeight: { tableCell.setHeight(str); return; }
case TableCellNoWrap: { tableCell.setNoWrap(value.toBoolean(exec)); return; }
case TableCellRowSpan: { tableCell.setRowSpan(value.toInt32(exec)); return; }
case TableCellScope: { tableCell.setScope(str); return; }
case TableCellVAlign: { tableCell.setVAlign(str); return; }
case TableCellWidth: { tableCell.setWidth(str); return; }
}
}
break;
case ID_FRAMESET: {
DOM::HTMLFrameSetElement frameSet = element;
switch (token) {
case FrameSetCols: { frameSet.setCols(str); return; }
case FrameSetRows: { frameSet.setRows(str); return; }
}
}
break;
case ID_FRAME: {
DOM::HTMLFrameElement frameElement = element;
switch (token) {
case FrameFrameBorder: { frameElement.setFrameBorder(str); return; }
case FrameLongDesc: { frameElement.setLongDesc(str); return; }
case FrameMarginHeight: { frameElement.setMarginHeight(str); return; }
case FrameMarginWidth: { frameElement.setMarginWidth(str); return; }
case FrameName: { frameElement.setName(str); return; }
case FrameNoResize: { frameElement.setNoResize(value.toBoolean(exec)); return; }
case FrameScrolling: { frameElement.setScrolling(str); return; }
case FrameSrc: { frameElement.setSrc(str); return; }
case FrameLocation: {
static_cast<DOM::HTMLFrameElementImpl *>(frameElement.handle())->setLocation(str);
return;
}
}
}
break;
case ID_IFRAME: {
DOM::HTMLIFrameElement iFrame = element;
switch (token) {
case IFrameAlign: { iFrame.setAlign(str); return; }
case IFrameFrameBorder: { iFrame.setFrameBorder(str); return; }
case IFrameHeight: { iFrame.setHeight(str); return; }
case IFrameLongDesc: { iFrame.setLongDesc(str); return; }
case IFrameMarginHeight: { iFrame.setMarginHeight(str); return; }
case IFrameMarginWidth: { iFrame.setMarginWidth(str); return; }
case IFrameName: { iFrame.setName(str); return; }
case IFrameScrolling: { iFrame.setScrolling(str); return; }
case IFrameSrc: { iFrame.setSrc(str); return; }
case IFrameWidth: { iFrame.setWidth(str); return; }
}
break;
}
}
switch (token) {
case ElementId:
element.setId(str);
return;
case ElementTitle:
element.setTitle(str);
return;
case ElementLang:
element.setLang(str);
return;
case ElementDir:
element.setDir(str);
return;
case ElementClassName:
element.setClassName(str);
return;
case ElementInnerHTML:
element.setInnerHTML(str);
return;
case ElementInnerText:
element.setInnerText(str);
return;
case ElementOuterHTML:
element.setOuterHTML(str);
return;
case ElementOuterText:
element.setOuterText(str);
return;
case ElementContentEditable:
element.setContentEditable(str);
return;
default:
kdWarning() << "KJS::HTMLElement::putValue unhandled token " << token << " thisTag=" << element.tagName().string() << " str=" << str.string() << endl;
}
}
DEFINE_PROTOTYPE("HTMLCollection", HTMLCollectionProto)
IMPLEMENT_PROTOFUNC(HTMLCollectionProtoFunc)
IMPLEMENT_PROTOTYPE(HTMLCollectionProto,HTMLCollectionProtoFunc)
const ClassInfo HTMLCollection::info = { "HTMLCollection", 0, 0, 0 };
HTMLCollection::HTMLCollection(ExecState *exec, const DOM::HTMLCollection &c)
: collection(c)
{
setPrototype(HTMLCollectionProto::self(exec));
}
HTMLCollection::~HTMLCollection()
{
ScriptInterpreter::forgetDOMObject(collection.handle());
}
bool KJS::HTMLCollection::hasOwnProperty(ExecState *exec, const Identifier &p) const
{
if (p == "selectedIndex" || p == lengthPropertyName)
return true;
return DOMObject::hasOwnProperty(exec, p);
}
Value KJS::HTMLCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
{
#ifdef KJS_VERBOSE
kdDebug() << "KJS::HTMLCollection::tryGet " << propertyName.ascii() << endl;
#endif
if (propertyName == lengthPropertyName)
return Number(collection.length());
else if (propertyName == "selectedIndex" &&
collection.item(0).elementId() == ID_OPTION) {
DOM::Node node = collection.item(0).parentNode();
while(!node.isNull()) {
if(node.elementId() == ID_SELECT) {
DOM::HTMLSelectElement sel = static_cast<DOM::HTMLSelectElement>(node);
return Number(sel.selectedIndex());
}
node = node.parentNode();
}
return Undefined();
} else {
Object proto = Object::dynamicCast(prototype());
if (!proto.isNull() && proto.hasProperty(exec,propertyName))
return proto.get(exec,propertyName);
bool ok;
unsigned int u = propertyName.toULong(&ok);
if (ok) {
DOM::Node node = collection.item(u);
return getDOMNode(exec,node);
}
else
return getNamedItems(exec,propertyName);
}
return Undefined();
}
Value KJS::HTMLCollection::call(ExecState *exec, Object &thisObj, const List &args)
{
Value val;
try {
val = tryCall(exec, thisObj, args);
}
catch (...) {
Object err = Error::create(exec, GeneralError, "Exception from HTMLCollection");
exec->setException(err);
}
return val;
}
Value KJS::HTMLCollection::tryCall(ExecState *exec, Object &, const List &args)
{
if (args.size() == 1) {
bool ok;
UString s = args[0].toString(exec);
unsigned int u = s.toULong(&ok);
if (ok) {
DOM::Element element = collection.item(u);
return getDOMNode(exec,element);
}
return getNamedItems(exec, Identifier(s));
}
else if (args.size() >= 1) {
bool ok;
UString s = args[0].toString(exec);
unsigned int u = args[1].toString(exec).toULong(&ok);
if (ok)
{
DOM::DOMString pstr = s.string();
DOM::Node node = collection.namedItem(pstr);
while (!node.isNull()) {
if (!u)
return getDOMNode(exec,node);
node = collection.nextNamedItem(pstr);
--u;
}
}
}
return Undefined();
}
Value KJS::HTMLCollection::getNamedItems(ExecState *exec, const Identifier &propertyName) const
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLCollection::getNamedItems " << propertyName.ascii() << endl;
#endif
DOM::DOMString pstr = propertyName.string();
QValueList<DOM::Node> namedItems = collection.namedItems(pstr);
if (namedItems.isEmpty()) {
#ifdef KJS_VERBOSE
kdDebug(6070) << "not found" << endl;
#endif
return Undefined();
}
if (namedItems.count() == 1) {
DOM::Node node = namedItems[0];
return getDOMNode(exec,node);
}
return Value(new DOMNamedNodesCollection(exec,namedItems));
}
Value KJS::HTMLCollectionProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&KJS::HTMLCollection::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
DOM::HTMLCollection coll = static_cast<KJS::HTMLCollection *>(thisObj.imp())->toCollection();
switch (id) {
case KJS::HTMLCollection::Item:
return getDOMNode(exec,coll.item(args[0].toUInt32(exec)));
case KJS::HTMLCollection::Tags:
{
DOM::DOMString tagName = args[0].toString(exec).string();
DOM::NodeList list;
if ( coll.base().nodeType() == DOM::Node::DOCUMENT_NODE )
{
DOM::Document doc = coll.base();
list = doc.getElementsByTagName(tagName);
#ifdef KJS_VERBOSE
kdDebug() << "KJS::HTMLCollectionProtoFunc::tryCall document.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
#endif
} else
{
DOM::Element e = coll.base();
list = e.getElementsByTagName(tagName);
#ifdef KJS_VERBOSE
kdDebug() << "KJS::HTMLCollectionProtoFunc::tryCall element.tags(" << tagName.string() << ") -> " << list.length() << " items in node list" << endl;
#endif
}
return getDOMNodeList(exec, list);
}
case KJS::HTMLCollection::NamedItem:
return static_cast<HTMLCollection *>(thisObj.imp())->getNamedItems(exec, Identifier(args[0].toString(exec)));
default:
return Undefined();
}
}
Value KJS::HTMLSelectCollection::tryGet(ExecState *exec, const Identifier &p) const
{
if (p == "selectedIndex")
return Number(element.selectedIndex());
return HTMLCollection::tryGet(exec, p);
}
void KJS::HTMLSelectCollection::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int)
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KJS::HTMLSelectCollection::tryPut " << propertyName.qstring() << endl;
#endif
if ( propertyName == "selectedIndex" ) {
element.setSelectedIndex( value.toInt32( exec ) );
return;
}
else if (propertyName == lengthPropertyName) {
unsigned newLen;
bool converted = value.toUInt32(newLen);
if (!converted) {
return;
}
long diff = element.length() - newLen;
if (diff < 0) { do {
element.add(element.ownerDocument().createElement("option"), DOM::HTMLElement());
} while (++diff);
}
else while (diff-- > 0)
element.remove(newLen);
return;
}
bool ok;
unsigned int u = propertyName.toULong(&ok);
if (!ok)
return;
if (value.isA(NullType) || value.isA(UndefinedType)) {
element.remove(u);
return;
}
DOM::Node node = KJS::toNode(value);
if (node.isNull() || node.elementId() != ID_OPTION)
return;
DOM::HTMLOptionElement option = static_cast<DOM::HTMLOptionElement>(node);
long diff = long(u) - element.length();
DOM::HTMLElement before;
if (diff > 0) {
while (diff--) {
element.add(element.ownerDocument().createElement("option"), before);
}
} else if (diff < 0) {
before = element.options().item(u+1);
element.remove(u);
}
element.add(option, before);
}
OptionConstructorImp::OptionConstructorImp(ExecState *exec, const DOM::Document &d)
: ObjectImp(), doc(d)
{
put(exec,lengthPropertyName, Number(4), ReadOnly|DontDelete|DontEnum);
}
bool OptionConstructorImp::implementsConstruct() const
{
return true;
}
Object OptionConstructorImp::construct(ExecState *exec, const List &args)
{
DOM::Element el = doc.createElement("option");
DOM::HTMLOptionElement opt = static_cast<DOM::HTMLOptionElement>(el);
int sz = args.size();
DOM::Text t = doc.createTextNode("");
try { opt.appendChild(t); }
catch(DOM::DOMException& e) {
}
if (sz > 0)
t.setData(args[0].toString(exec).string()); if (sz > 1)
opt.setValue(args[1].toString(exec).string());
if (sz > 2)
opt.setDefaultSelected(args[2].toBoolean(exec));
if (sz > 3)
opt.setSelected(args[3].toBoolean(exec));
return Object::dynamicCast(getDOMNode(exec,opt));
}
ImageConstructorImp::ImageConstructorImp(ExecState *, const DOM::Document &d)
: ObjectImp(), doc(d)
{
}
bool ImageConstructorImp::implementsConstruct() const
{
return true;
}
Object ImageConstructorImp::construct(ExecState * exec, const List & list)
{
bool widthSet = false, heightSet = false;
int width = 0, height = 0;
if (list.size() > 0) {
widthSet = true;
Value w = list.at(0);
width = w.toInt32(exec);
}
if (list.size() > 1) {
heightSet = true;
Value h = list.at(1);
height = h.toInt32(exec);
}
Object result(new Image(doc, widthSet, width, heightSet, height));
return result;
}
const ClassInfo KJS::Image::info = { "Image", 0, &ImageTable, 0 };
Value Image::tryGet(ExecState *exec, const Identifier &propertyName) const
{
return DOMObjectLookupGetValue<Image,DOMObject>(exec, propertyName, &ImageTable, this);
}
Value Image::getValueProperty(ExecState *, int token) const
{
switch (token) {
case Src:
return String(doc ? doc->completeURL(src.qstring()) : src);
case Complete:
return Boolean(!img || img->status() >= khtml::CachedObject::Persistent);
case OnLoad:
if (onLoadListener && onLoadListener->listenerObjImp()) {
return onLoadListener->listenerObj();
} else {
return Null();
}
case Width: {
if (widthSet)
return Number(width);
int w = 0;
if (img) {
QSize size = img->pixmap_size();
if (size.isValid())
w = size.width();
}
return Number(w);
}
case Height: {
if (heightSet)
return Number(height);
int h = 0;
if (img) {
QSize size = img->pixmap_size();
if (size.isValid())
h = size.height();
}
return Number(h);
}
default:
kdWarning() << "Image::getValueProperty unhandled token " << token << endl;
return Value();
}
}
void Image::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
DOMObjectLookupPut<Image,DOMObject>(exec, propertyName, value, attr, &ImageTable, this );
}
void Image::putValue(ExecState *exec, int token, const Value& value, int )
{
switch(token) {
case Src:
{
String str = value.toString(exec);
src = str.value();
if ( img ) img->deref(this);
img = doc ? doc->docLoader()->requestImage( src.string() ) : 0;
if ( img ) img->ref(this);
break;
}
case OnLoad:
onLoadListener = Window::retrieveActive(exec)->getJSEventListener(value, true);
if (onLoadListener) onLoadListener->ref();
break;
case Width:
widthSet = true;
width = value.toInt32(exec);
break;
case Height:
heightSet = true;
height = value.toInt32(exec);
break;
default:
kdWarning() << "HTMLDocument::putValue unhandled token " << token << endl;
}
}
void Image::notifyFinished(khtml::CachedObject *)
{
if (onLoadListener && doc->part()) {
DOM::Event ev = doc->part()->document().createEvent("HTMLEvents");
ev.initEvent("load", true, true);
onLoadListener->handleEvent(ev, true);
}
}
Image::Image(const DOM::Document &d, bool ws, int w, bool hs, int h)
: doc(static_cast<DOM::DocumentImpl*>(d.handle())), img(0), onLoadListener(0)
{
widthSet = ws;
width = w;
heightSet = hs;
height = h;
}
Image::~Image()
{
if ( img ) img->deref(this);
if ( onLoadListener ) onLoadListener->deref();
}
IMPLEMENT_PROTOFUNC(Context2DFunction)
static bool isGradient(const Value &value)
{
ObjectImp *o = static_cast<ObjectImp*>(value.imp());
if (o->type() == ObjectType && o->inherits(&Gradient::info))
return true;
return false;
}
static bool isImagePattern(const Value &value)
{
ObjectImp *o = static_cast<ObjectImp*>(value.imp());
if (o->type() == ObjectType && o->inherits(&ImagePattern::info))
return true;
return false;
}
#define BITS_PER_COMPONENT 8
#define BYTES_PER_ROW(width,bitsPerComponent,numComponents) ((width * bitsPerComponent * numComponents + 7)/8)
Value KJS::Context2DFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&Context2D::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
Context2D *contextObject = static_cast<KJS::Context2D *>(thisObj.imp());
khtml::RenderCanvasImage *renderer = static_cast<khtml::RenderCanvasImage*>(contextObject->_element->renderer());
if (!renderer)
return Undefined();
CGContextRef drawingContext = renderer->drawingContext();
if (!drawingContext)
return Undefined();
switch (id) {
case Context2D::Save: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextSaveGState(drawingContext);
contextObject->save();
break;
}
case Context2D::Restore: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextRestoreGState(drawingContext);
contextObject->restore();
break;
}
case Context2D::BeginPath: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextBeginPath(drawingContext);
break;
}
case Context2D::ClosePath: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextClosePath(drawingContext);
break;
}
case Context2D::SetStrokeColor: {
int numArgs = args.size();
switch (numArgs) {
case 1: {
if (args[0].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
QColor qc(color);
CGContextSetRGBStrokeColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
}
else {
float g = (float)args[0].toNumber(exec);
CGContextSetGrayStrokeColor(drawingContext, g, 1.);
}
}
break;
case 2: {
float a = args[1].toNumber(exec);
if (args[0].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
QColor qc(color);
CGContextSetRGBStrokeColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., a);
}
else {
float g = (float)args[0].toNumber(exec);
CGContextSetGrayStrokeColor(drawingContext, g, a);
}
}
break;
case 4: {
float r = (float)args[0].toNumber(exec);
float g = (float)args[1].toNumber(exec);
float b = (float)args[2].toNumber(exec);
float a = (float)args[3].toNumber(exec);
CGContextSetRGBStrokeColor(drawingContext, r, g, b, a);
}
break;
case 5: {
float c = (float)args[0].toNumber(exec);
float m = (float)args[1].toNumber(exec);
float y = (float)args[2].toNumber(exec);
float k = (float)args[3].toNumber(exec);
float a = (float)args[4].toNumber(exec);
CGContextSetCMYKStrokeColor(drawingContext, c, m, y, k, a);
}
break;
default: {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
}
break;
}
case Context2D::SetFillColor: {
int numArgs = args.size();
switch (numArgs) {
case 1: {
if (args[0].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
QColor qc(color);
CGContextSetRGBFillColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
}
else {
float g = (float)args[0].toNumber(exec);
CGContextSetGrayFillColor(drawingContext, g, 1.);
}
}
break;
case 2: {
float a = args[1].toNumber(exec);
if (args[0].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[0].toString(exec).string());
QColor qc(color);
CGContextSetRGBFillColor(drawingContext, qc.red()/255., qc.green()/255., qc.blue()/255., a);
}
else {
float g = (float)args[0].toNumber(exec);
CGContextSetGrayFillColor(drawingContext, g, a);
}
}
break;
case 4: {
float r = (float)args[0].toNumber(exec);
float g = (float)args[1].toNumber(exec);
float b = (float)args[2].toNumber(exec);
float a = (float)args[3].toNumber(exec);
CGContextSetRGBFillColor(drawingContext, r, g, b, a);
}
break;
case 5: {
float c = (float)args[0].toNumber(exec);
float m = (float)args[1].toNumber(exec);
float y = (float)args[2].toNumber(exec);
float k = (float)args[3].toNumber(exec);
float a = (float)args[4].toNumber(exec);
CGContextSetCMYKStrokeColor(drawingContext, c, m, y, k, a);
}
break;
default: {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
}
break;
}
case Context2D::SetLineWidth: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float w = (float)args[0].toNumber(exec);
CGContextSetLineWidth (drawingContext, w);
break;
}
case Context2D::SetLineCap: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGLineCap cap = kCGLineCapButt;
QString capString = args[0].toString(exec).qstring().lower();
if (capString == "round")
cap = kCGLineCapRound;
else if (capString == "square")
cap = kCGLineCapSquare;
CGContextSetLineCap (drawingContext, cap);
break;
}
case Context2D::SetLineJoin: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGLineJoin join = kCGLineJoinMiter;
QString joinString = args[0].toString(exec).qstring().lower();
if (joinString == "round")
join = kCGLineJoinRound;
else if (joinString == "bevel")
join = kCGLineJoinBevel;
CGContextSetLineJoin (drawingContext, join);
break;
}
case Context2D::SetMiterLimit: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float l = (float)args[0].toNumber(exec);
CGContextSetMiterLimit (drawingContext, l);
break;
}
case Context2D::Fill: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
if (isGradient(contextObject->_fillStyle)) {
CGContextSaveGState(drawingContext);
CGContextClip(drawingContext);
ObjectImp *o = static_cast<ObjectImp*>(contextObject->_fillStyle.imp());
Gradient *gradient = static_cast<Gradient*>(o);
CGShadingRef shading = gradient->getShading();
CGContextDrawShading(drawingContext, shading);
CGContextRestoreGState(drawingContext);
}
else
CGContextFillPath (drawingContext);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::Stroke: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
if (isGradient(contextObject->_strokeStyle)) {
CGContextSaveGState(drawingContext);
CGContextReplacePathWithStrokedPath(drawingContext);
CGContextClip(drawingContext);
ObjectImp *o = static_cast<ObjectImp*>(contextObject->_strokeStyle.imp());
Gradient *gradient = static_cast<Gradient*>(o);
CGShadingRef shading = gradient->getShading();
CGContextDrawShading(drawingContext, shading);
CGContextRestoreGState(drawingContext);
}
else
CGContextStrokePath (drawingContext);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::Scale: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float sx = (float)args[0].toNumber(exec);
float sy = (float)args[1].toNumber(exec);
CGContextScaleCTM (drawingContext, sx, sy);
contextObject->_needsFlushRasterCache = true;
break;
}
case Context2D::Rotate: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float angle = (float)args[0].toNumber(exec);
CGContextRotateCTM (drawingContext, angle);
contextObject->_needsFlushRasterCache = true;
break;
}
case Context2D::Translate: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float tx = (float)args[0].toNumber(exec);
float ty = (float)args[1].toNumber(exec);
CGContextTranslateCTM (drawingContext, tx, ty);
break;
}
case Context2D::MoveTo: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
CGContextMoveToPoint (drawingContext, x, y);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::LineTo: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
CGContextAddLineToPoint (drawingContext, x, y);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::QuadraticCurveTo: {
if (args.size() != 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float cpx = (float)args[0].toNumber(exec);
float cpy = (float)args[1].toNumber(exec);
float x = (float)args[2].toNumber(exec);
float y = (float)args[3].toNumber(exec);
CGContextAddQuadCurveToPoint (drawingContext, cpx, cpy, x, y);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::BezierCurveTo: {
if (args.size() != 6) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float cp1x = (float)args[0].toNumber(exec);
float cp1y = (float)args[1].toNumber(exec);
float cp2x = (float)args[2].toNumber(exec);
float cp2y = (float)args[3].toNumber(exec);
float x = (float)args[4].toNumber(exec);
float y = (float)args[5].toNumber(exec);
CGContextAddCurveToPoint (drawingContext, cp1x, cp1y, cp2x, cp2y, x, y);
renderer->setNeedsImageUpdate();
break;
}
case Context2D::ArcTo: {
if (args.size() != 5) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x1 = (float)args[0].toNumber(exec);
float y1 = (float)args[1].toNumber(exec);
float x2 = (float)args[2].toNumber(exec);
float y2 = (float)args[3].toNumber(exec);
float r = (float)args[4].toNumber(exec);
CGContextAddArcToPoint (drawingContext, x1, y1, x2, y2, r);
break;
}
case Context2D::Arc: {
if (args.size() != 6) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
float r = (float)args[2].toNumber(exec);
float sa = (float)args[3].toNumber(exec);
float ea = (float)args[4].toNumber(exec);
bool clockwise = args[5].toBoolean(exec);
CGContextAddArc (drawingContext, x, y, r, sa, ea, clockwise);
break;
}
case Context2D::Rect: {
if (args.size() != 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
float w = (float)args[2].toNumber(exec);
float h = (float)args[3].toNumber(exec);
CGContextAddRect (drawingContext, CGRectMake(x,y,w,h));
break;
}
case Context2D::Clip: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextClip (drawingContext);
break;
}
case Context2D::ClearRect: {
if (args.size() != 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
float w = (float)args[2].toNumber(exec);
float h = (float)args[3].toNumber(exec);
CGContextClearRect (drawingContext, CGRectMake(x,y,w,h));
renderer->setNeedsImageUpdate();
break;
}
case Context2D::FillRect: {
if (args.size() != 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
float w = (float)args[2].toNumber(exec);
float h = (float)args[3].toNumber(exec);
CGContextFillRect (drawingContext, CGRectMake(x,y,w,h));
renderer->setNeedsImageUpdate();
break;
}
case Context2D::StrokeRect: {
int size = args.size();
if (size < 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x = (float)args[0].toNumber(exec);
float y = (float)args[1].toNumber(exec);
float w = (float)args[2].toNumber(exec);
float h = (float)args[3].toNumber(exec);
if (size > 4)
CGContextStrokeRectWithWidth (drawingContext, CGRectMake(x,y,w,h), (float)args[4].toNumber(exec));
else
CGContextStrokeRect (drawingContext, CGRectMake(x,y,w,h));
renderer->setNeedsImageUpdate();
break;
}
case Context2D::SetShadow: {
int numArgs = args.size();
if (numArgs < 3) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGSize offset;
offset.width = (float)args[0].toNumber(exec);
offset.height = (float)args[1].toNumber(exec);
float blur = (float)args[2].toNumber(exec);
QColor color = QColor(args[3].toString(exec).ascii());
if (numArgs == 3) {
CGContextSetShadow (drawingContext, offset, blur);
} else {
CGColorSpaceRef colorSpace;
float components[5];
switch (numArgs - 3) {
case 1: {
if (args[3].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[3].toString(exec).string());
QColor qc(color);
components[0] = qc.red()/255.;
components[1] = qc.green()/255.;
components[2] = qc.blue()/255.;
components[3] = 1.0f;
colorSpace = QPainter::rgbColorSpace();
}
else {
components[0] = (float)args[3].toNumber(exec);
components[1] = 1.0f;
colorSpace = QPainter::grayColorSpace();
}
}
break;
case 2: {
float a = args[4].toNumber(exec);
if (args[3].type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(args[3].toString(exec).string());
QColor qc(color);
components[0] = qc.red()/255.;
components[1] = qc.green()/255.;
components[2] = qc.blue()/255.;
components[3] = a;
colorSpace = QPainter::rgbColorSpace();
}
else {
components[0] = (float)args[3].toNumber(exec);
components[1] = a;
colorSpace = QPainter::grayColorSpace();
}
}
break;
case 4: {
components[0] = (float)args[3].toNumber(exec); components[1] = (float)args[4].toNumber(exec); components[2] = (float)args[5].toNumber(exec); components[3] = (float)args[6].toNumber(exec); colorSpace = QPainter::rgbColorSpace();
}
break;
case 5: {
components[0] = (float)args[3].toNumber(exec); components[1] = (float)args[4].toNumber(exec); components[2] = (float)args[5].toNumber(exec); components[3] = (float)args[6].toNumber(exec); components[4] = (float)args[7].toNumber(exec);
colorSpace = QPainter::cmykColorSpace();
}
break;
default: {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
}
CGColorRef colorRef = CGColorCreate (colorSpace, components);
CGContextSetShadowWithColor (drawingContext, offset, blur, colorRef);
CFRelease (colorRef);
CFRelease (colorSpace);
}
break;
}
case Context2D::ClearShadow: {
if (args.size() != 0) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
CGContextSetShadowWithColor (drawingContext, CGSizeMake(0, 0), 0, nil);
break;
}
case Context2D::DrawImage: {
if (args.size() < 3) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
ObjectImp *o = static_cast<ObjectImp*>(args[0].imp());
if (o->type() != ObjectType) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
float w = 0; float h = 0; QPixmap pixmap;
CGContextRef sourceContext = 0;
if (o->inherits(&Image::info)) {
Image *i = static_cast<Image*>(o);
khtml::CachedImage *ci = i->image();
if (ci) {
pixmap = ci->pixmap();
}
else {
return Undefined();
}
w = pixmap.width();
h = pixmap.height();
}
else if (o->inherits(&KJS::HTMLElement::img_info)){
DOM::HTMLElement element = static_cast<KJS::HTMLElement *>(args[0].imp())->toElement();
DOM::HTMLImageElementImpl *e = static_cast<DOM::HTMLImageElementImpl*>(element.handle());
pixmap = e->pixmap();
w = pixmap.width();
h = pixmap.height();
}
else if (o->inherits(&KJS::HTMLElement::canvas_info)){
DOM::HTMLElement element = static_cast<KJS::HTMLElement *>(args[0].imp())->toElement();
DOM::HTMLCanvasElementImpl *e = static_cast<DOM::HTMLCanvasElementImpl*>(element.handle());
khtml::RenderCanvasImage *renderer = static_cast<khtml::RenderCanvasImage*>(e->renderer());
if (!renderer) {
return Undefined();
}
sourceContext = renderer->drawingContext();
w = (float)CGBitmapContextGetWidth(sourceContext);
h = (float)CGBitmapContextGetHeight(sourceContext);
}
else {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
float dx, dy, dw = w, dh = h;
float sx = 0.f, sy = 0.f, sw = w, sh = h;
if (args.size() == 3) {
dx = args[1].toNumber(exec);
dy = args[2].toNumber(exec);
}
else if (args.size() == 5) {
dx = args[1].toNumber(exec);
dy = args[2].toNumber(exec);
dw = args[3].toNumber(exec);
dh = args[4].toNumber(exec);
}
else if (args.size() == 9) {
sx = args[1].toNumber(exec);
sy = args[2].toNumber(exec);
sw = args[3].toNumber(exec);
sh = args[4].toNumber(exec);
dx = args[5].toNumber(exec);
dy = args[6].toNumber(exec);
dw = args[7].toNumber(exec);
dh = args[8].toNumber(exec);
}
else {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
if (!sourceContext) {
QPainter p;
p.drawFloatPixmap (dx, dy, dw, dh, pixmap, sx, sy, sw, sh,
QPainter::compositeOperatorFromString(contextObject->_globalComposite.toString(exec).qstring().lower()), drawingContext);
}
else {
CGImageRef sourceImage = CGBitmapContextCreateImage(sourceContext);
if (sx == 0 && sy == 0 && sw == w && sh == h) {
CGContextDrawImage (drawingContext, CGRectMake(dx, dy, dw, dh), sourceImage);
}
else {
CGContextRef clippedSourceContext;
CGImageRef clippedSourceImage;
size_t csw = (size_t)sw;
size_t csh = (size_t)sh;
CGColorSpaceRef colorSpace = QPainter::rgbColorSpace();
size_t numComponents = CGColorSpaceGetNumberOfComponents(colorSpace);
size_t bytesPerRow = BYTES_PER_ROW(csw,BITS_PER_COMPONENT,(numComponents+1)); void *_drawingContextData = malloc(csh * bytesPerRow);
clippedSourceContext = CGBitmapContextCreate(_drawingContextData, csw, csh, BITS_PER_COMPONENT, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM (clippedSourceContext, -sx, -sy);
CGContextDrawImage (clippedSourceContext, CGRectMake(0,0,w,h), sourceImage);
clippedSourceImage = CGBitmapContextCreateImage(clippedSourceContext);
CGContextDrawImage (drawingContext, CGRectMake(dx, dy, dw, dh), clippedSourceImage);
CGImageRelease (clippedSourceImage);
CGContextRelease (clippedSourceContext);
free (_drawingContextData);
}
CGImageRelease (sourceImage);
}
if (contextObject->_needsFlushRasterCache)
pixmap.flushRasterCache();
renderer->setNeedsImageUpdate();
break;
}
case Context2D::DrawImageFromRect: {
if (args.size() != 10) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
ObjectImp *o = static_cast<ObjectImp*>(args[0].imp());
if (o->type() != ObjectType || !o->inherits(&Image::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
Image *i = static_cast<Image*>(o);
float sx = args[1].toNumber(exec);
float sy = args[2].toNumber(exec);
float sw = args[3].toNumber(exec);
float sh = args[4].toNumber(exec);
float dx = args[5].toNumber(exec);
float dy = args[6].toNumber(exec);
float dw = args[7].toNumber(exec);
float dh = args[8].toNumber(exec);
QString compositeOperator = args[9].toString(exec).qstring().lower();
khtml::CachedImage *ci = i->image();
if (ci) {
QPixmap pixmap = ci->pixmap();
QPainter p;
p.drawFloatPixmap (dx, dy, dw, dh, pixmap, sx, sy, sw, sh, QPainter::compositeOperatorFromString(compositeOperator), drawingContext);
if (contextObject->_needsFlushRasterCache)
pixmap.flushRasterCache();
renderer->setNeedsImageUpdate();
}
break;
}
case Context2D::SetAlpha: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float a = (float)args[0].toNumber(exec);
CGContextSetAlpha (drawingContext, a);
break;
}
case Context2D::SetCompositeOperation: {
if (args.size() != 1) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
QString compositeOperator = args[0].toString(exec).qstring().lower();
QPainter::setCompositeOperation (drawingContext,compositeOperator);
break;
}
case Context2D::CreateLinearGradient: {
if (args.size() != 4) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x0 = args[0].toNumber(exec);
float y0 = args[1].toNumber(exec);
float x1 = args[2].toNumber(exec);
float y1 = args[3].toNumber(exec);
return Object(new Gradient(x0, y0, x1, y1));
}
case Context2D::CreateRadialGradient: {
if (args.size() != 6) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
float x0 = args[0].toNumber(exec);
float y0 = args[1].toNumber(exec);
float r0 = args[2].toNumber(exec);
float x1 = args[3].toNumber(exec);
float y1 = args[4].toNumber(exec);
float r1 = args[5].toNumber(exec);
return Object(new Gradient(x0, y0, r0, x1, y1, r1));
}
case Context2D::CreatePattern: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
ObjectImp *o = static_cast<ObjectImp*>(args[0].imp());
if (o->type() != ObjectType || !o->inherits(&Image::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
int repetitionType = ImagePattern::Repeat;
QString repetitionString = args[1].toString(exec).qstring().lower();
if (repetitionString == "repeat-x")
repetitionType = ImagePattern::RepeatX;
else if (repetitionString == "repeat-y")
repetitionType = ImagePattern::RepeatY;
else if (repetitionString == "no-repeat")
repetitionType = ImagePattern::NoRepeat;
return Object(new ImagePattern(static_cast<Image*>(o), repetitionType));
}
}
return Undefined();
}
const ClassInfo KJS::Context2D::info = { "Context2D", 0, &Context2DTable, 0 };
Value Context2D::tryGet(ExecState *exec, const Identifier &propertyName) const
{
const HashTable* table = classInfo()->propHashTable; const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
if (entry->attr & Function)
return lookupOrCreateFunction<KJS::Context2DFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
return getValueProperty(exec, entry->value);
}
return DOMObjectLookupGetValue<Context2D,DOMObject>(exec, propertyName, &Context2DTable, this);
}
Value Context2D::getValueProperty(ExecState *, int token) const
{
switch(token) {
case StrokeStyle: {
return _strokeStyle;
}
case FillStyle: {
return _fillStyle;
}
case LineWidth: {
return _lineWidth;
}
case LineCap: {
return _lineCap;
}
case LineJoin: {
return _lineJoin;
}
case MiterLimit: {
return _miterLimit;
}
case ShadowOffsetX: {
return _shadowOffsetX;
}
case ShadowOffsetY: {
return _shadowOffsetY;
}
case ShadowBlur: {
return _shadowBlur;
}
case ShadowColor: {
return _shadowColor;
}
case GlobalAlpha: {
return _globalAlpha;
}
case GlobalCompositeOperation: {
return _globalComposite;
}
default: {
}
}
return Undefined();
}
void Context2D::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
DOMObjectLookupPut<Context2D,DOMObject>(exec, propertyName, value, attr, &Context2DTable, this );
}
CGContextRef Context2D::drawingContext()
{
khtml::RenderCanvasImage *renderer = static_cast<khtml::RenderCanvasImage*>(_element->renderer());
if (!renderer)
return 0;
CGContextRef context = renderer->drawingContext();
if (!context)
return 0;
return context;
}
CGColorRef Context2D::colorRefFromValue(ExecState *exec, const Value &value)
{
CGColorSpaceRef colorSpace;
float components[4];
if (value.type() == StringType) {
QRgb color = DOM::CSSParser::parseColor(value.toString(exec).string());
QColor qc(color);
components[0] = qc.red()/255.;
components[1] = qc.green()/255.;
components[2] = qc.blue()/255.;
components[3] = qc.alpha();
colorSpace = QPainter::rgbColorSpace();
}
else
return 0;
CGColorRef colorRef = CGColorCreate (colorSpace, components);
CFRelease (colorSpace);
return colorRef;
}
QColor Context2D::colorFromValue(ExecState *exec, const Value &value)
{
QRgb color = DOM::CSSParser::parseColor(value.toString(exec).string());
return QColor(color);
}
void Context2D::setShadow(ExecState *exec)
{
CGContextRef context = drawingContext();
if (!context)
return;
CGSize offset;
offset.width = (float)_shadowOffsetX.toNumber(exec);
offset.height = (float)_shadowOffsetY.toNumber(exec);
float blur = (float)_shadowBlur.toNumber(exec);
CGColorRef colorRef = colorRefFromValue(exec, _shadowColor);
CGContextSetShadowWithColor (context, offset, blur, colorRef);
CFRelease (colorRef);
}
void Context2D::putValue(ExecState *exec, int token, const Value& value, int )
{
CGContextRef context = drawingContext();
if (!context)
return;
switch(token) {
case StrokeStyle: {
_strokeStyle = value;
if (value.type() == StringType) {
QColor qc = Context2D::colorFromValue(exec, value);
CGContextSetRGBStrokeColor(context, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
}
else {
ObjectImp *o = static_cast<ObjectImp*>(value.imp());
if (o->type() != ObjectType ||
(!(o->inherits(&Gradient::info) || o->inherits(&ImagePattern::info)))) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return;
}
if (isImagePattern(value)) {
float patternAlpha = 1;
ImagePattern *imagePattern = static_cast<ImagePattern*>(o);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetStrokeColorSpace(context, patternSpace);
CGContextSetStrokePattern(context, imagePattern->getPattern(), &patternAlpha);
CGColorSpaceRelease(patternSpace);
}
}
break;
}
case FillStyle: {
_fillStyle = value;
if (value.type() == StringType) {
QColor qc = colorFromValue(exec, value);
CGContextSetRGBFillColor(context, qc.red()/255., qc.green()/255., qc.blue()/255., qc.alpha()/255.);
}
else {
ObjectImp *o = static_cast<ObjectImp*>(value.imp());
if (o->type() != ObjectType ||
(!(o->inherits(&Gradient::info) || o->inherits(&ImagePattern::info)))) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return;
}
if (isImagePattern(value)) {
float patternAlpha = 1;
ImagePattern *imagePattern = static_cast<ImagePattern*>(o);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetFillColorSpace(context, patternSpace);
CGContextSetFillPattern(context, imagePattern->getPattern(), &patternAlpha);
CGColorSpaceRelease(patternSpace);
}
}
break;
}
case LineWidth: {
_lineWidth = value;
float w = (float)value.toNumber(exec);
CGContextSetLineWidth (context, w);
break;
}
case LineCap: {
_lineCap = value;
CGLineCap cap = kCGLineCapButt;
QString capString = value.toString(exec).qstring().lower();
if (capString == "round")
cap = kCGLineCapRound;
else if (capString == "square")
cap = kCGLineCapSquare;
CGContextSetLineCap (context, cap);
break;
}
case LineJoin: {
_lineJoin = value;
CGLineJoin join = kCGLineJoinMiter;
QString joinString = value.toString(exec).qstring().lower();
if (joinString == "round")
join = kCGLineJoinRound;
else if (joinString == "bevel")
join = kCGLineJoinBevel;
CGContextSetLineJoin (context, join);
break;
}
case MiterLimit: {
_miterLimit = value;
float l = (float)value.toNumber(exec);
CGContextSetMiterLimit (context, l);
break;
}
case ShadowOffsetX: {
_shadowOffsetX = value;
setShadow(exec);
break;
}
case ShadowOffsetY: {
_shadowOffsetY = value;
setShadow(exec);
break;
}
case ShadowBlur: {
_shadowBlur = value;
setShadow(exec);
break;
}
case ShadowColor: {
_shadowColor = value;
setShadow(exec);
break;
}
case GlobalAlpha: {
_globalAlpha = value;
float a = (float)value.toNumber(exec);
CGContextSetAlpha (context, a);
break;
}
case GlobalCompositeOperation: {
_globalComposite = value;
QString compositeOperator = value.toString(exec).qstring().lower();
QPainter::setCompositeOperation (context, compositeOperator);
break;
}
default: {
}
}
}
void Context2D::save()
{
List *list = new List();
list->append(_strokeStyle);
list->append(_fillStyle);
list->append(_lineWidth);
list->append(_lineCap);
list->append(_lineJoin);
list->append(_miterLimit);
list->append(_shadowOffsetX);
list->append(_shadowOffsetY);
list->append(_shadowBlur);
list->append(_shadowColor);
list->append(_globalAlpha);
list->append(_globalComposite);
stateStack.append(list);
}
void Context2D::restore()
{
if (stateStack.count() < 1) {
return;
}
List *list = stateStack.last();
int pos = 0;
_strokeStyle = list->at(pos++);
_fillStyle = list->at(pos++);
_lineWidth = list->at(pos++);
_lineCap = list->at(pos++);
_lineJoin = list->at(pos++);
_miterLimit = list->at(pos++);
_shadowOffsetX = list->at(pos++);
_shadowOffsetY = list->at(pos++);
_shadowBlur = list->at(pos++);
_shadowColor = list->at(pos++);
_globalAlpha = list->at(pos++);
_globalComposite = list->at(pos++);
stateStack.removeLast();
}
Context2D::Context2D(const DOM::HTMLElement &e)
: _element(static_cast<DOM::HTMLElementImpl*>(e.handle())), _needsFlushRasterCache(0)
{
_lineWidth = Number (1.);
_strokeStyle = String ("black");
_fillStyle = String ("black");
_lineCap = String("butt");
_lineJoin = String("miter");
_miterLimit = Number(10.0);
_shadowOffsetX = Number(0.);
_shadowOffsetY = Number(0.);
_shadowBlur = Number(0.);
_shadowColor = String("black");
_globalAlpha = Number(1.);
_globalComposite = String("source-over");
stateStack.setAutoDelete(true);
}
Context2D::~Context2D()
{
}
const ClassInfo KJS::Gradient::info = { "Gradient", 0, &GradientTable, 0 };
IMPLEMENT_PROTOFUNC(GradientFunction)
Value KJS::GradientFunction::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&Gradient::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
Gradient *gradient = static_cast<KJS::Gradient *>(thisObj.imp());
switch (id) {
case Gradient::AddColorStop: {
if (args.size() != 2) {
Object err = Error::create(exec,SyntaxError);
exec->setException(err);
return err;
}
QColor color = Context2D::colorFromValue(exec, args[1]);
gradient->addColorStop ((float)args[0].toNumber(exec), color.red()/255.f, color.green()/255.f, color.blue()/255.f, color.alpha()/255.f);
}
}
return Undefined();
}
void gradientCallback (void *info, const float *in, float *out)
{
Gradient *gradient = static_cast<Gradient*>(info);
int numStops;
const ColorStop *stops = gradient->colorStops(&numStops);
float current = *in;
assert (numStops >= 2);
if (current == 0) {
gradient->lastStop = 0;
gradient->nextStop = 1;
const ColorStop *thisStop = &stops[0];
*out++ = thisStop->red;
*out++ = thisStop->green;
*out++ = thisStop->blue;
*out = thisStop->alpha;
}
else if (current == 1) {
const ColorStop *thisStop = &stops[numStops-1];
*out++ = thisStop->red;
*out++ = thisStop->green;
*out++ = thisStop->blue;
*out = thisStop->alpha;
}
else {
if (current >= stops[gradient->nextStop].stop) {
gradient->lastStop = gradient->nextStop;
gradient->nextStop = gradient->lastStop+1;
}
const ColorStop *nextStop = &stops[gradient->nextStop];
const ColorStop *lastStop = &stops[gradient->lastStop];
float stopDelta = nextStop->stop - lastStop->stop;
float stopOffset = current - lastStop->stop;
float stopPercent = stopOffset/stopDelta;
*out++ = lastStop->red + (nextStop->red - lastStop->red) * stopPercent;
*out++ = lastStop->green + (nextStop->green - lastStop->green) * stopPercent;
*out++ = lastStop->blue + (nextStop->blue - lastStop->blue) * stopPercent;
*out = lastStop->alpha + (nextStop->alpha - lastStop->alpha) * stopPercent;
}
}
static float intervalRangeDomin[] = { 0.f, 1.f };
static float colorComponentRangeDomains[] = { 0.f, 1.f, 0.f, 1.f, 0.f, 1.f, 0.f, 1.f };
CGFunctionCallbacks gradientCallbacks = {
0, gradientCallback, NULL
};
void Gradient::commonInit()
{
stops = 0;
stopCount = 0;
maxStops = 0;
stopsNeedAdjusting = false;
adjustedStopCount = 0;
adjustedStops = 0;
_shadingRef = 0;
regenerateShading = true;
}
Gradient::Gradient(float x0, float y0, float x1, float y1)
{
_gradientType = Gradient::Linear;
_x0 = x0;
_y0 = y0;
_x1 = x1;
_y1 = y1;
commonInit();
}
Gradient::Gradient(float x0, float y0, float r0, float x1, float y1, float r1)
{
_gradientType = Gradient::Radial;
_x0 = x0;
_y0 = y0;
_r0 = r0;
_x1 = x1;
_y1 = y1;
_r1 = r1;
commonInit();
}
Value Gradient::tryGet(ExecState *exec, const Identifier &propertyName) const
{
const HashTable* table = classInfo()->propHashTable; const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
if (entry->attr & Function)
return lookupOrCreateFunction<KJS::GradientFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
return getValueProperty(exec, entry->value);
}
return DOMObjectLookupGetValue<Gradient,DOMObject>(exec, propertyName, &GradientTable, this);
}
Value Gradient::getValueProperty(ExecState *, int token) const
{
return Undefined();
}
void Gradient::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
DOMObjectLookupPut<Gradient,DOMObject>(exec, propertyName, value, attr, &GradientTable, this );
}
void Gradient::putValue(ExecState *exec, int token, const Value& value, int )
{
}
Gradient::~Gradient()
{
if (_shadingRef) {
CGShadingRelease(_shadingRef);
_shadingRef = 0;
}
free (stops);
stops = 0;
free (adjustedStops);
adjustedStops = 0;
}
CGShadingRef Gradient::getShading()
{
if (!regenerateShading)
return _shadingRef;
if (_shadingRef)
CGShadingRelease (_shadingRef);
CGFunctionRef _colorFunction = CGFunctionCreate((void *)this, 1, intervalRangeDomin, 4, colorComponentRangeDomains, &gradientCallbacks);
CGColorSpaceRef colorSpace = QPainter::rgbColorSpace();
if (_gradientType == Gradient::Radial) {
_shadingRef = CGShadingCreateRadial(colorSpace, CGPointMake(_x0,_y0), _r0, CGPointMake(_x1,_y1), _r1, _colorFunction, true, true);
}
else {
_shadingRef = CGShadingCreateAxial(colorSpace, CGPointMake(_x0,_y0), CGPointMake(_x1,_y1), _colorFunction, true, true);
}
CGColorSpaceRelease (colorSpace);
CGFunctionRelease (_colorFunction);
regenerateShading = false;
return _shadingRef;
}
void Gradient::addColorStop (float s, float r, float g, float b, float a)
{
if (stopCount == 0) {
maxStops = 4;
stops = (ColorStop *)malloc(maxStops * sizeof(ColorStop));
}
else if (stopCount+1 > maxStops) {
maxStops *= 2;
stops = (ColorStop *)realloc(stops, maxStops * sizeof(ColorStop));
}
stops[stopCount++] = ColorStop (s, r, g, b, a);
stopsNeedAdjusting = true;
}
static int sortStops(const ColorStop *a, const ColorStop *b)
{
if (a->stop > b->stop)
return 1;
else if (a->stop < b->stop)
return -1;
return 0;
}
const ColorStop *Gradient::colorStops(int *count) const
{
if (stopsNeedAdjusting || !stops) {
stopsNeedAdjusting = false;
bool haveZeroStop = false;
bool haveOneStop = false;
if (stops) {
qsort (stops, stopCount, sizeof(ColorStop), (int (*)(const void*, const void*))sortStops);
haveZeroStop = (stops[0].stop == 0.f);
haveOneStop = (stopCount > 0 && stops[stopCount-1].stop == 1.f);
}
adjustedStopCount = stopCount;
if (!haveZeroStop)
adjustedStopCount++;
if (!haveOneStop)
adjustedStopCount++;
if (adjustedStopCount != stopCount) {
adjustedStops = (ColorStop *)malloc(adjustedStopCount * sizeof(ColorStop));
memcpy (haveZeroStop ? adjustedStops : adjustedStops+1,
stops, stopCount*sizeof(ColorStop));
if (!haveZeroStop) {
adjustedStops[0] = ColorStop(0.f, 0.f, 0.f, 0.f, 1.f);
}
if (!haveOneStop) {
adjustedStops[adjustedStopCount-1] = ColorStop(1.f, 0.f, 0.f, 0.f, 1.f);
}
}
regenerateShading = true;
}
if (adjustedStops) {
*count = adjustedStopCount;
return adjustedStops;
}
*count = stopCount;
return stops;
}
const ClassInfo KJS::ImagePattern::info = { "ImagePattern", 0, &ImagePatternTable, 0 };
static void drawPattern (void * info, CGContextRef context)
{
ImagePattern *pattern = static_cast<ImagePattern*>(info);
QPainter p;
QPixmap pixmap = pattern->pixmap();
float w = pixmap.width();
float h = pixmap.height();
CGImageRef ref = pixmap.imageRef();
if (ref) {
CGContextDrawImage (context, CGRectMake(0, 0, w, h), ref);
}
else
p.drawFloatPixmap (0, 0, w, h, pixmap, 0.f, 0.f, w, h,
QPainter::compositeOperatorFromString(QString("source-over")), context);
}
CGPatternCallbacks patternCallbacks = { 0, drawPattern, NULL };
ImagePattern::ImagePattern(Image *i, int repetitionType)
{
_repetitionType = repetitionType;
khtml::CachedImage *ci = i->image();
if (ci) {
_pixmap = ci->pixmap();
float w = _pixmap.width(), rw = 0;
float h = _pixmap.height(), rh = 0;
CGRect bounds = CGRectMake (0, 0, w, h);
if (repetitionType == Repeat) {
rw = w; rh = h;
}
else if (repetitionType == RepeatX) {
rw = w; rh = 0;
}
else if (repetitionType == RepeatY) {
rw = 0; rh = h;
}
else if (repetitionType == NoRepeat) {
rw = 0; rh = 0;
}
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale (transform, 1, -1);
transform = CGAffineTransformTranslate (transform, 0, -h);
_patternRef = CGPatternCreate(this, bounds, transform, rw, rh,
kCGPatternTilingConstantSpacing, true, &patternCallbacks);
}
}
Value ImagePattern::tryGet(ExecState *exec, const Identifier &propertyName) const
{
const HashTable* table = classInfo()->propHashTable; const HashEntry* entry = Lookup::findEntry(table, propertyName);
if (entry) {
if (entry->attr & Function)
return lookupOrCreateFunction<KJS::GradientFunction>(exec, propertyName, this, entry->value, entry->params, entry->attr);
return getValueProperty(exec, entry->value);
}
return DOMObjectLookupGetValue<ImagePattern,DOMObject>(exec, propertyName, &ImagePatternTable, this);
}
Value ImagePattern::getValueProperty(ExecState *, int token) const
{
return Undefined();
}
void ImagePattern::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
{
DOMObjectLookupPut<ImagePattern,DOMObject>(exec, propertyName, value, attr, &ImagePatternTable, this );
}
void ImagePattern::putValue(ExecState *exec, int token, const Value& value, int )
{
}
ImagePattern::~ImagePattern()
{
if (_patternRef) {
CGPatternRelease (_patternRef);
_patternRef = 0;
}
}
Value KJS::getHTMLCollection(ExecState *exec, const DOM::HTMLCollection &c)
{
return cacheDOMObject<DOM::HTMLCollection, KJS::HTMLCollection>(exec, c);
}
Value KJS::getSelectHTMLCollection(ExecState *exec, const DOM::HTMLCollection &c, const DOM::HTMLSelectElement &e)
{
DOMObject *ret;
if (c.isNull())
return Null();
ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
if ((ret = interp->getDOMObject(c.handle())))
return Value(ret);
else {
ret = new HTMLSelectCollection(exec, c, e);
interp->putDOMObject(c.handle(),ret);
return Value(ret);
}
}