2 * This file is part of the DOM implementation for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 1999 Antti Koivisto (koivisto@kde.org)
6 * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
7 * Copyright (C) 2004 Apple Computer, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
24 #include "html/html_objectimpl.h"
26 #include "khtml_part.h"
27 #include "dom/dom_string.h"
28 #include "misc/htmlhashes.h"
29 #include "khtmlview.h"
34 #include "xml/dom_docimpl.h"
35 #include "css/cssstyleselector.h"
36 #include "css/csshelper.h"
37 #include "css/cssproperties.h"
38 #include "css/cssvalues.h"
39 #include "rendering/render_applet.h"
40 #include "rendering/render_frames.h"
41 #include "rendering/render_image.h"
42 #include "xml/dom2_eventsimpl.h"
44 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
45 #include "java/kjavaappletwidget.h"
46 #include "java/kjavaappletcontext.h"
50 #include "KWQKHTMLPart.h"
54 using namespace khtml;
56 // -------------------------------------------------------------------------
58 HTMLAppletElementImpl::HTMLAppletElementImpl(DocumentPtr *doc)
59 : HTMLElementImpl(doc)
62 m_allParamsAvailable = false;
65 HTMLAppletElementImpl::~HTMLAppletElementImpl()
67 delete appletInstance;
70 NodeImpl::Id HTMLAppletElementImpl::id() const
75 bool HTMLAppletElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
83 result = eReplaced; // Share with <img> since the alignment behavior is the same.
89 return HTMLElementImpl::mapToEntry(attr, result);
92 void HTMLAppletElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
104 addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
107 addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
110 addHTMLAlignment(attr);
113 HTMLElementImpl::parseHTMLAttribute(attr);
117 bool HTMLAppletElementImpl::rendererIsNeeded(RenderStyle *style)
119 return !getAttribute(ATTR_CODE).isNull();
122 RenderObject *HTMLAppletElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
124 #ifndef Q_WS_QWS // FIXME(E)? I don't think this is possible with Qt Embedded...
125 KHTMLPart *part = getDocument()->part();
127 if( part && part->javaEnabled() )
129 QMap<QString, QString> args;
131 args.insert( "code", getAttribute(ATTR_CODE).string());
132 DOMString codeBase = getAttribute(ATTR_CODEBASE);
133 if(!codeBase.isNull())
134 args.insert( "codeBase", codeBase.string() );
135 DOMString name = getDocument()->htmlMode() != DocumentImpl::XHtml ?
136 getAttribute(ATTR_NAME) : getAttribute(ATTR_ID);
138 args.insert( "name", name.string() );
139 DOMString archive = getAttribute(ATTR_ARCHIVE);
140 if(!archive.isNull())
141 args.insert( "archive", archive.string() );
143 args.insert( "baseURL", getDocument()->baseURL() );
145 DOMString mayScript = getAttribute(ATTR_MAYSCRIPT);
146 if (!mayScript.isNull())
147 args.insert("mayScript", mayScript.string());
149 // Other arguments (from <PARAM> tags) are added later.
151 return new (getDocument()->renderArena()) RenderApplet(this, args);
154 // ### remove me. we should never show an empty applet, instead
155 // render the alternative content given by the webpage
156 return new (getDocument()->renderArena()) RenderEmptyApplet(this);
162 bool HTMLAppletElementImpl::getMember(const QString & name, JType & type, QString & val) {
166 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
167 if ( !m_render || !m_render->isApplet() )
169 KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(static_cast<RenderApplet*>(m_render)->widget());
170 return (w && w->applet() && w->applet()->getMember(name, type, val));
177 bool HTMLAppletElementImpl::callMember(const QString & name, const QStringList & args, JType & type, QString & val) {
181 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
182 if ( !m_render || !m_render->isApplet() )
184 KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(static_cast<RenderApplet*>(m_render)->widget());
185 return (w && w->applet() && w->applet()->callMember(name, args, type, val));
193 KJS::Bindings::Instance *HTMLAppletElementImpl::getAppletInstance() const
195 KHTMLPart* part = getDocument()->part();
196 if (!part || !part->javaEnabled())
200 return appletInstance;
202 RenderApplet *r = static_cast<RenderApplet*>(m_render);
204 r->createWidgetIfNecessary();
206 // Call into the part (and over the bridge) to pull the Bindings::Instance
207 // from the guts of the plugin.
208 void *_view = r->widget()->getView();
209 appletInstance = KWQ(part)->getAppletInstanceForView((NSView *)_view);
212 return appletInstance;
215 void HTMLAppletElementImpl::setAllParamsAvailable()
217 // The parser just reached </applet>, so all the params are available now.
218 m_allParamsAvailable = true;
220 m_render->setNeedsLayout(true); // This will cause it to create its widget & the Java applet
223 bool HTMLAppletElementImpl::allParamsAvailable()
225 return m_allParamsAvailable;
229 // -------------------------------------------------------------------------
231 HTMLEmbedElementImpl::HTMLEmbedElementImpl(DocumentPtr *doc)
232 : HTMLElementImpl(doc), embedInstance(0)
235 HTMLEmbedElementImpl::~HTMLEmbedElementImpl()
239 NodeImpl::Id HTMLEmbedElementImpl::id() const
245 KJS::Bindings::Instance *HTMLEmbedElementImpl::getEmbedInstance() const
247 KHTMLPart* part = getDocument()->part();
252 return embedInstance;
254 RenderPartObject *r = static_cast<RenderPartObject*>(m_render);
257 // Call into the part (and over the bridge) to pull the Bindings::Instance
258 // from the guts of the Java VM.
259 void *_view = r->widget()->getView();
260 embedInstance = KWQ(part)->getEmbedInstanceForView((NSView *)_view);
261 // Applet may specified with <embed> tag.
263 embedInstance = KWQ(part)->getAppletInstanceForView((NSView *)_view);
266 return embedInstance;
270 bool HTMLEmbedElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
283 result = eReplaced; // Share with <img> since the alignment behavior is the same.
289 return HTMLElementImpl::mapToEntry(attr, result);
292 void HTMLEmbedElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
294 QString val = attr->value().string();
297 switch ( attr->id() )
300 serviceType = val.lower();
301 pos = serviceType.find( ";" );
303 serviceType = serviceType.left( pos );
307 url = khtml::parseURL(attr->value()).string();
310 addCSSLength( attr, CSS_PROP_WIDTH, attr->value() );
313 addCSSLength( attr, CSS_PROP_HEIGHT, attr->value());
316 addCSSLength(attr, CSS_PROP_BORDER_WIDTH, attr->value());
317 addCSSProperty( attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID );
318 addCSSProperty( attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID );
319 addCSSProperty( attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID );
320 addCSSProperty( attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID );
323 addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
324 addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
327 addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
328 addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
331 addHTMLAlignment(attr);
334 addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
336 case ATTR_PLUGINPAGE:
337 case ATTR_PLUGINSPAGE:
341 if (val.lower()=="yes" || val.lower()=="true") {
342 // FIXME: Not dynamic, but it's not really important that such a rarely-used
343 // feature work dynamically.
344 addCSSLength( attr, CSS_PROP_WIDTH, "0" );
345 addCSSLength( attr, CSS_PROP_HEIGHT, "0" );
349 HTMLElementImpl::parseHTMLAttribute( attr );
353 bool HTMLEmbedElementImpl::rendererIsNeeded(RenderStyle *style)
355 KHTMLPart *part = getDocument()->part();
358 return part->pluginsEnabled() && parentNode()->id() != ID_OBJECT;
361 RenderObject *HTMLEmbedElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
363 return new (arena) RenderPartObject(this);
366 void HTMLEmbedElementImpl::attach()
368 HTMLElementImpl::attach();
370 static_cast<RenderPartObject*>(m_render)->updateWidget();
374 bool HTMLEmbedElementImpl::isURLAttribute(AttributeImpl *attr) const
376 return attr->id() == ATTR_SRC;
379 // -------------------------------------------------------------------------
381 HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentPtr *doc)
383 : HTMLElementImpl(doc), m_imageLoader(0), objectInstance(0)
385 : HTMLElementImpl(doc), m_imageLoader(0)
388 needWidgetUpdate = false;
391 HTMLObjectElementImpl::~HTMLObjectElementImpl()
393 delete m_imageLoader;
396 NodeImpl::Id HTMLObjectElementImpl::id() const
402 KJS::Bindings::Instance *HTMLObjectElementImpl::getObjectInstance() const
404 KHTMLPart* part = getDocument()->part();
409 return objectInstance;
411 RenderPartObject *r = static_cast<RenderPartObject*>(m_render);
414 // Call into the part (and over the bridge) to pull the Bindings::Instance
415 // from the guts of the plugin.
416 void *_view = r->widget()->getView();
417 objectInstance = KWQ(part)->getObjectInstanceForView((NSView *)_view);
418 // Applet may specified with <object> tag.
420 objectInstance = KWQ(part)->getAppletInstanceForView((NSView *)_view);
423 return objectInstance;
427 HTMLFormElementImpl *HTMLObjectElementImpl::form() const
432 bool HTMLObjectElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
443 return HTMLElementImpl::mapToEntry(attr, result);
446 void HTMLObjectElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
448 QString val = attr->value().string();
450 switch ( attr->id() )
453 serviceType = val.lower();
454 pos = serviceType.find( ";" );
456 serviceType = serviceType.left( pos );
458 needWidgetUpdate = true;
459 if (!canRenderImageType(serviceType) && m_imageLoader) {
460 delete m_imageLoader;
465 url = khtml::parseURL( val ).string();
467 needWidgetUpdate = true;
468 if (m_render && canRenderImageType(serviceType)) {
470 m_imageLoader = new HTMLImageLoader(this);
471 m_imageLoader->updateFromElement();
475 addCSSLength( attr, CSS_PROP_WIDTH, attr->value());
478 addCSSLength( attr, CSS_PROP_HEIGHT, attr->value());
483 needWidgetUpdate = true;
485 case ATTR_ONLOAD: // ### support load/unload on object elements
486 setHTMLEventListener(EventImpl::LOAD_EVENT,
487 getDocument()->createHTMLEventListener(attr->value().string(), this));
490 setHTMLEventListener(EventImpl::UNLOAD_EVENT,
491 getDocument()->createHTMLEventListener(attr->value().string(), this));
494 HTMLElementImpl::parseHTMLAttribute( attr );
498 DocumentImpl* HTMLObjectElementImpl::contentDocument() const
504 bool HTMLObjectElementImpl::rendererIsNeeded(RenderStyle *style)
506 if (canRenderImageType(serviceType)) {
507 return HTMLElementImpl::rendererIsNeeded(style);
510 KHTMLPart* part = getDocument()->part();
511 if (!part || !part->pluginsEnabled()) {
515 // Eventually we will merge with the better version of this check on the tip of tree.
516 // Until then, just leave it out.
518 KURL u = getDocument()->completeURL(url);
519 for (KHTMLPart* part = w->part()->parentPart(); part; part = part->parentPart())
520 if (part->url() == u) {
527 RenderObject *HTMLObjectElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
529 if (canRenderImageType(serviceType)) {
530 return new (arena) RenderImage(this);
532 return new (arena) RenderPartObject(this);
535 void HTMLObjectElementImpl::attach()
537 HTMLElementImpl::attach();
540 if (canRenderImageType(serviceType)) {
542 m_imageLoader = new HTMLImageLoader(this);
543 m_imageLoader->updateFromElement();
545 RenderImage* imageObj = static_cast<RenderImage*>(renderer());
546 imageObj->setImage(m_imageLoader->image());
549 if (needWidgetUpdate) {
550 // Set needWidgetUpdate to false before calling updateWidget because updateWidget may cause
551 // this method or recalcStyle (which also calls updateWidget) to be called.
552 needWidgetUpdate = false;
553 static_cast<RenderPartObject*>(m_render)->updateWidget();
554 dispatchHTMLEvent(EventImpl::LOAD_EVENT,false,false);
556 needWidgetUpdate = true;
563 void HTMLObjectElementImpl::detach()
565 // Only bother with an unload event if we had a render object. - dwh
566 if (attached() && m_render)
567 // ### do this when we are actualy removed from document instead
568 dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
570 HTMLElementImpl::detach();
573 void HTMLObjectElementImpl::recalcStyle(StyleChange ch)
575 if (needWidgetUpdate && m_render && !canRenderImageType(serviceType)) {
576 // Set needWidgetUpdate to false before calling updateWidget because updateWidget may cause
577 // this method or attach (which also calls updateWidget) to be called.
578 needWidgetUpdate = false;
579 static_cast<RenderPartObject*>(m_render)->updateWidget();
580 dispatchHTMLEvent(EventImpl::LOAD_EVENT,false,false);
582 HTMLElementImpl::recalcStyle(ch);
585 void HTMLObjectElementImpl::childrenChanged()
588 needWidgetUpdate = true;
593 bool HTMLObjectElementImpl::isURLAttribute(AttributeImpl *attr) const
595 return (attr->id() == ATTR_DATA || (attr->id() == ATTR_USEMAP && attr->value().domString()[0] != '#'));
598 // -------------------------------------------------------------------------
600 HTMLParamElementImpl::HTMLParamElementImpl(DocumentPtr *doc)
601 : HTMLElementImpl(doc)
605 HTMLParamElementImpl::~HTMLParamElementImpl()
609 NodeImpl::Id HTMLParamElementImpl::id() const
614 void HTMLParamElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
619 // Must call base class so that hasID bit gets set.
620 HTMLElementImpl::parseHTMLAttribute(attr);
621 if (getDocument()->htmlMode() != DocumentImpl::XHtml) break;
624 m_name = attr->value();
627 m_value = attr->value();
632 bool HTMLParamElementImpl::isURLAttribute(AttributeImpl *attr) const
634 if (attr->id() == ATTR_VALUE) {
635 AttributeImpl *attr = attributes()->getAttributeItem(ATTR_NAME);
637 DOMString value = attr->value().string().lower();
638 if (value == "src" || value == "movie" || value == "data") {