Patch by Anders Carlsson <andersca@mac.com>
[WebKit-https.git] / WebCore / khtml / html / html_objectimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  */
24 #include "html/html_objectimpl.h"
25
26 #include "khtml_part.h"
27 #include "dom/dom_string.h"
28 #include "misc/htmlhashes.h"
29 #include "khtmlview.h"
30 #include <qstring.h>
31 #include <qmap.h>
32 #include <kdebug.h>
33
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 "html/html_formimpl.h"
40 #include "rendering/render_applet.h"
41 #include "rendering/render_frames.h"
42 #include "rendering/render_image.h"
43 #include "xml/dom2_eventsimpl.h"
44
45 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
46 #include "java/kjavaappletwidget.h"
47 #include "java/kjavaappletcontext.h"
48 #endif
49
50 #if APPLE_CHANGES
51 #include "KWQKHTMLPart.h"
52 #endif
53
54 using namespace khtml;
55
56 namespace DOM {
57
58 // -------------------------------------------------------------------------
59
60 HTMLAppletElementImpl::HTMLAppletElementImpl(DocumentPtr *doc)
61   : HTMLElementImpl(doc)
62 {
63     appletInstance = 0;
64     m_allParamsAvailable = false;
65 }
66
67 HTMLAppletElementImpl::~HTMLAppletElementImpl()
68 {
69     delete appletInstance;
70 }
71
72 NodeImpl::Id HTMLAppletElementImpl::id() const
73 {
74     return ID_APPLET;
75 }
76
77 bool HTMLAppletElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
78 {
79     switch (attr) {
80         case ATTR_WIDTH:
81         case ATTR_HEIGHT:
82         case ATTR_VSPACE:
83         case ATTR_HSPACE:
84             result = eUniversal;
85             return false;
86         case ATTR_ALIGN:
87             result = eReplaced; // Share with <img> since the alignment behavior is the same.
88             return false;
89         default:
90             break;
91     }
92     
93     return HTMLElementImpl::mapToEntry(attr, result);
94 }
95
96 void HTMLAppletElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
97 {
98     switch (attr->id()) {
99     case ATTR_ALT:
100     case ATTR_ARCHIVE:
101     case ATTR_CODE:
102     case ATTR_CODEBASE:
103     case ATTR_MAYSCRIPT:
104     case ATTR_NAME:
105     case ATTR_OBJECT:
106         break;
107     case ATTR_WIDTH:
108         addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
109         break;
110     case ATTR_HEIGHT:
111         addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
112         break;
113     case ATTR_VSPACE:
114         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
115         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
116         break;
117     case ATTR_HSPACE:
118         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
119         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
120         break;
121     case ATTR_ALIGN:
122         addHTMLAlignment(attr);
123         break;
124     default:
125         HTMLElementImpl::parseMappedAttribute(attr);
126     }
127 }
128
129 bool HTMLAppletElementImpl::rendererIsNeeded(RenderStyle *style)
130 {
131     return !getAttribute(ATTR_CODE).isNull();
132 }
133
134 RenderObject *HTMLAppletElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
135 {
136 #ifndef Q_WS_QWS // FIXME(E)? I don't think this is possible with Qt Embedded...
137     KHTMLPart *part = getDocument()->part();
138
139     if( part && part->javaEnabled() )
140     {
141         QMap<QString, QString> args;
142
143         args.insert( "code", getAttribute(ATTR_CODE).string());
144         DOMString codeBase = getAttribute(ATTR_CODEBASE);
145         if(!codeBase.isNull())
146             args.insert( "codeBase", codeBase.string() );
147         DOMString name = getDocument()->htmlMode() != DocumentImpl::XHtml ?
148                          getAttribute(ATTR_NAME) : getAttribute(ATTR_ID);
149         if(!name.isNull())
150             args.insert( "name", name.string() );
151         DOMString archive = getAttribute(ATTR_ARCHIVE);
152         if(!archive.isNull())
153             args.insert( "archive", archive.string() );
154
155         args.insert( "baseURL", getDocument()->baseURL() );
156
157         DOMString mayScript = getAttribute(ATTR_MAYSCRIPT);
158         if (!mayScript.isNull())
159             args.insert("mayScript", mayScript.string());
160
161         // Other arguments (from <PARAM> tags) are added later.
162         
163         return new (getDocument()->renderArena()) RenderApplet(this, args);
164     }
165
166     // ### remove me. we should never show an empty applet, instead
167     // render the alternative content given by the webpage
168     return new (getDocument()->renderArena()) RenderEmptyApplet(this);
169 #else
170     return 0;
171 #endif
172 }
173
174 bool HTMLAppletElementImpl::getMember(const QString & name, JType & type, QString & val) {
175 #if APPLE_CHANGES
176     return false;
177 #else
178 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
179     if ( !m_render || !m_render->isApplet() )
180         return false;
181     KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(static_cast<RenderApplet*>(m_render)->widget());
182     return (w && w->applet() && w->applet()->getMember(name, type, val));
183 #else
184     return false;
185 #endif
186 #endif
187 }
188
189 bool HTMLAppletElementImpl::callMember(const QString & name, const QStringList & args, JType & type, QString & val) {
190 #if APPLE_CHANGES
191     return false;
192 #else
193 #ifndef Q_WS_QWS // We don't have Java in Qt Embedded
194     if ( !m_render || !m_render->isApplet() )
195         return false;
196     KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(static_cast<RenderApplet*>(m_render)->widget());
197     return (w && w->applet() && w->applet()->callMember(name, args, type, val));
198 #else
199     return false;
200 #endif
201 #endif
202 }
203
204 #if APPLE_CHANGES
205 KJS::Bindings::Instance *HTMLAppletElementImpl::getAppletInstance() const
206 {
207     KHTMLPart* part = getDocument()->part();
208     if (!part || !part->javaEnabled())
209         return 0;
210
211     if (appletInstance)
212         return appletInstance;
213     
214     RenderApplet *r = static_cast<RenderApplet*>(m_render);
215     if (r) {
216         r->createWidgetIfNecessary();
217         if (r->widget()){
218             // Call into the part (and over the bridge) to pull the Bindings::Instance
219             // from the guts of the plugin.
220             void *_view = r->widget()->getView();
221             appletInstance = KWQ(part)->getAppletInstanceForView((NSView *)_view);
222         }
223     }
224     return appletInstance;
225 }
226
227 void HTMLAppletElementImpl::closeRenderer()
228 {
229     // The parser just reached </applet>, so all the params are available now.
230     m_allParamsAvailable = true;
231     if( m_render )
232         m_render->setNeedsLayout(true); // This will cause it to create its widget & the Java applet
233     
234     HTMLElementImpl::closeRenderer();
235 }
236
237 bool HTMLAppletElementImpl::allParamsAvailable()
238 {
239     return m_allParamsAvailable;
240 }
241 #endif
242
243 DOMString HTMLAppletElementImpl::align() const
244 {
245     return getAttribute(ATTR_ALIGN);
246 }
247
248 void HTMLAppletElementImpl::setAlign(const DOMString &value)
249 {
250     setAttribute(ATTR_ALIGN, value);
251 }
252
253 DOMString HTMLAppletElementImpl::alt() const
254 {
255     return getAttribute(ATTR_ALT);
256 }
257
258 void HTMLAppletElementImpl::setAlt(const DOMString &value)
259 {
260     setAttribute(ATTR_ALT, value);
261 }
262
263 DOMString HTMLAppletElementImpl::archive() const
264 {
265     return getAttribute(ATTR_ARCHIVE);
266 }
267
268 void HTMLAppletElementImpl::setArchive(const DOMString &value)
269 {
270     setAttribute(ATTR_ARCHIVE, value);
271 }
272
273 DOMString HTMLAppletElementImpl::code() const
274 {
275     return getAttribute(ATTR_CODE);
276 }
277
278 void HTMLAppletElementImpl::setCode(const DOMString &value)
279 {
280     setAttribute(ATTR_CODE, value);
281 }
282
283 DOMString HTMLAppletElementImpl::codeBase() const
284 {
285     return getAttribute(ATTR_CODEBASE);
286 }
287
288 void HTMLAppletElementImpl::setCodeBase(const DOMString &value)
289 {
290     setAttribute(ATTR_CODEBASE, value);
291 }
292
293 DOMString HTMLAppletElementImpl::height() const
294 {
295     return getAttribute(ATTR_HEIGHT);
296 }
297
298 void HTMLAppletElementImpl::setHeight(const DOMString &value)
299 {
300     setAttribute(ATTR_HEIGHT, value);
301 }
302
303 DOMString HTMLAppletElementImpl::hspace() const
304 {
305     return getAttribute(ATTR_HSPACE);
306 }
307
308 void HTMLAppletElementImpl::setHspace(const DOMString &value)
309 {
310     setAttribute(ATTR_HSPACE, value);
311 }
312
313 DOMString HTMLAppletElementImpl::name() const
314 {
315     return getAttribute(ATTR_NAME);
316 }
317
318 void HTMLAppletElementImpl::setName(const DOMString &value)
319 {
320     setAttribute(ATTR_NAME, value);
321 }
322
323 DOMString HTMLAppletElementImpl::object() const
324 {
325     return getAttribute(ATTR_OBJECT);
326 }
327
328 void HTMLAppletElementImpl::setObject(const DOMString &value)
329 {
330     setAttribute(ATTR_OBJECT, value);
331 }
332
333 DOMString HTMLAppletElementImpl::vspace() const
334 {
335     return getAttribute(ATTR_VSPACE);
336 }
337
338 void HTMLAppletElementImpl::setVspace(const DOMString &value)
339 {
340     setAttribute(ATTR_VSPACE, value);
341 }
342
343 DOMString HTMLAppletElementImpl::width() const
344 {
345     return getAttribute(ATTR_WIDTH);
346 }
347
348 void HTMLAppletElementImpl::setWidth(const DOMString &value)
349 {
350     setAttribute(ATTR_WIDTH, value);
351 }
352
353 // -------------------------------------------------------------------------
354
355 HTMLEmbedElementImpl::HTMLEmbedElementImpl(DocumentPtr *doc)
356     : HTMLElementImpl(doc), embedInstance(0)
357 {}
358
359 HTMLEmbedElementImpl::~HTMLEmbedElementImpl()
360 {
361 }
362
363 NodeImpl::Id HTMLEmbedElementImpl::id() const
364 {
365     return ID_EMBED;
366 }
367
368 #if APPLE_CHANGES
369 KJS::Bindings::Instance *HTMLEmbedElementImpl::getEmbedInstance() const
370 {
371     KHTMLPart* part = getDocument()->part();
372     if (!part)
373         return 0;
374
375     if (embedInstance)
376         return embedInstance;
377     
378     RenderPartObject *r = static_cast<RenderPartObject*>(m_render);
379     if (r) {
380         if (r->widget()){
381             // Call into the part (and over the bridge) to pull the Bindings::Instance
382             // from the guts of the Java VM.
383             void *_view = r->widget()->getView();
384             embedInstance = KWQ(part)->getEmbedInstanceForView((NSView *)_view);
385             // Applet may specified with <embed> tag.
386             if (!embedInstance)
387                 embedInstance = KWQ(part)->getAppletInstanceForView((NSView *)_view);
388         }
389     }
390     return embedInstance;
391 }
392 #endif
393
394 bool HTMLEmbedElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
395 {
396     switch (attr) {
397         case ATTR_WIDTH:
398         case ATTR_HEIGHT:
399         case ATTR_BORDER:
400         case ATTR_VSPACE:
401         case ATTR_HSPACE:
402         case ATTR_VALIGN:
403         case ATTR_HIDDEN:
404             result = eUniversal;
405             return false;
406         case ATTR_ALIGN:
407             result = eReplaced; // Share with <img> since the alignment behavior is the same.
408             return false;
409         default:
410             break;
411     }
412     
413     return HTMLElementImpl::mapToEntry(attr, result);
414 }
415
416 void HTMLEmbedElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
417 {
418   QString val = attr->value().string();
419   
420   int pos;
421   switch ( attr->id() )
422   {
423      case ATTR_TYPE:
424         serviceType = val.lower();
425         pos = serviceType.find( ";" );
426         if ( pos!=-1 )
427             serviceType = serviceType.left( pos );
428         break;
429      case ATTR_CODE:
430      case ATTR_SRC:
431          url = khtml::parseURL(attr->value()).string();
432          break;
433      case ATTR_WIDTH:
434         addCSSLength( attr, CSS_PROP_WIDTH, attr->value() );
435         break;
436      case ATTR_HEIGHT:
437         addCSSLength( attr, CSS_PROP_HEIGHT, attr->value());
438         break;
439      case ATTR_BORDER:
440         addCSSLength(attr, CSS_PROP_BORDER_WIDTH, attr->value());
441         addCSSProperty( attr, CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID );
442         addCSSProperty( attr, CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID );
443         addCSSProperty( attr, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID );
444         addCSSProperty( attr, CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID );
445         break;
446      case ATTR_VSPACE:
447         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
448         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
449         break;
450      case ATTR_HSPACE:
451         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
452         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
453         break;
454      case ATTR_ALIGN:
455         addHTMLAlignment(attr);
456         break;
457      case ATTR_VALIGN:
458         addCSSProperty(attr, CSS_PROP_VERTICAL_ALIGN, attr->value());
459         break;
460      case ATTR_PLUGINPAGE:
461      case ATTR_PLUGINSPAGE:
462         pluginPage = val;
463         break;
464      case ATTR_HIDDEN:
465         if (val.lower()=="yes" || val.lower()=="true") {
466             // FIXME: Not dynamic, but it's not really important that such a rarely-used
467             // feature work dynamically.
468             addCSSLength( attr, CSS_PROP_WIDTH, "0" );
469             addCSSLength( attr, CSS_PROP_HEIGHT, "0" );
470         }
471         break;
472      default:
473         HTMLElementImpl::parseMappedAttribute( attr );
474   }
475 }
476
477 bool HTMLEmbedElementImpl::rendererIsNeeded(RenderStyle *style)
478 {
479     KHTMLPart *part = getDocument()->part();
480     if (!part)
481         return false;
482     return part->pluginsEnabled() && parentNode()->id() != ID_OBJECT;
483 }
484
485 RenderObject *HTMLEmbedElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
486 {
487     return new (arena) RenderPartObject(this);
488 }
489
490 void HTMLEmbedElementImpl::attach()
491 {
492     HTMLElementImpl::attach();
493     if (m_render) {
494         static_cast<RenderPartObject*>(m_render)->updateWidget();
495     }
496 }
497
498 bool HTMLEmbedElementImpl::isURLAttribute(AttributeImpl *attr) const
499 {
500     return attr->id() == ATTR_SRC;
501 }
502
503 // -------------------------------------------------------------------------
504
505 HTMLObjectElementImpl::HTMLObjectElementImpl(DocumentPtr *doc) 
506 #if APPLE_CHANGES
507 : HTMLElementImpl(doc), m_imageLoader(0), objectInstance(0)
508 #else
509 : HTMLElementImpl(doc), m_imageLoader(0)
510 #endif
511 {
512     needWidgetUpdate = false;
513     m_useFallbackContent = false;
514 }
515
516 HTMLObjectElementImpl::~HTMLObjectElementImpl()
517 {
518     delete m_imageLoader;
519 }
520
521 NodeImpl::Id HTMLObjectElementImpl::id() const
522 {
523     return ID_OBJECT;
524 }
525
526 #if APPLE_CHANGES
527 KJS::Bindings::Instance *HTMLObjectElementImpl::getObjectInstance() const
528 {
529     KHTMLPart* part = getDocument()->part();
530     if (!part)
531         return 0;
532
533     if (objectInstance)
534         return objectInstance;
535
536     if (RenderObject *r = m_render) {
537         if (r->isWidget()) {
538             if (QWidget *widget = static_cast<RenderWidget *>(r)->widget()) {
539                 if (NSView *view = widget->getView())  {
540                     // Call into the part (and over the bridge) to pull the Bindings::Instance
541                     // from the guts of the plugin.
542                     objectInstance = KWQ(part)->getObjectInstanceForView(view);
543                     // Applet may specified with <object> tag.
544                     if (!objectInstance)
545                         objectInstance = KWQ(part)->getAppletInstanceForView(view);
546                 }
547             }
548         }
549     }
550
551     return objectInstance;
552 }
553 #endif
554
555 HTMLFormElementImpl *HTMLObjectElementImpl::form() const
556 {
557     for (NodeImpl *p = parentNode(); p != 0; p = p->parentNode()) {
558         if (p->id() == ID_FORM)
559             return static_cast<HTMLFormElementImpl *>(p);
560     }
561     
562     return 0;
563 }
564
565 bool HTMLObjectElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
566 {
567     switch (attr) {
568         case ATTR_WIDTH:
569         case ATTR_HEIGHT:
570         case ATTR_VSPACE:
571         case ATTR_HSPACE:
572             result = eUniversal;
573             return false;
574         case ATTR_ALIGN:
575             result = eReplaced; // Share with <img> since the alignment behavior is the same.
576             return false;
577         default:
578             break;
579     }
580     
581     return HTMLElementImpl::mapToEntry(attr, result);
582 }
583
584 void HTMLObjectElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
585 {
586   QString val = attr->value().string();
587   int pos;
588   switch ( attr->id() )
589   {
590     case ATTR_TYPE:
591       serviceType = val.lower();
592       pos = serviceType.find( ";" );
593       if ( pos!=-1 )
594           serviceType = serviceType.left( pos );
595       if (m_render)
596           needWidgetUpdate = true;
597       if (!isImageType() && m_imageLoader) {
598           delete m_imageLoader;
599           m_imageLoader = 0;
600       }
601       break;
602     case ATTR_DATA:
603       url = khtml::parseURL(  val ).string();
604       if (m_render)
605           needWidgetUpdate = true;
606       if (m_render && isImageType()) {
607           if (!m_imageLoader)
608               m_imageLoader = new HTMLImageLoader(this);
609           m_imageLoader->updateFromElement();
610       }
611       break;
612     case ATTR_WIDTH:
613       addCSSLength( attr, CSS_PROP_WIDTH, attr->value());
614       break;
615     case ATTR_HEIGHT:
616       addCSSLength( attr, CSS_PROP_HEIGHT, attr->value());
617       break;
618     case ATTR_VSPACE:
619         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
620         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
621         break;
622     case ATTR_HSPACE:
623         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
624         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
625         break;
626     case ATTR_ALIGN:
627         addHTMLAlignment(attr);
628         break;
629     case ATTR_CLASSID:
630       classId = val;
631       if (m_render)
632           needWidgetUpdate = true;
633       break;
634     case ATTR_ONLOAD: // ### support load/unload on object elements
635         setHTMLEventListener(EventImpl::LOAD_EVENT,
636             getDocument()->createHTMLEventListener(attr->value().string(), this));
637         break;
638     case ATTR_ONUNLOAD:
639         setHTMLEventListener(EventImpl::UNLOAD_EVENT,
640             getDocument()->createHTMLEventListener(attr->value().string(), this));
641         break;
642     default:
643       HTMLElementImpl::parseMappedAttribute( attr );
644   }
645 }
646
647 DocumentImpl* HTMLObjectElementImpl::contentDocument() const
648 {
649     // ###
650     return 0;
651 }
652
653 bool HTMLObjectElementImpl::rendererIsNeeded(RenderStyle *style)
654 {
655     if (m_useFallbackContent || isImageType())
656         return HTMLElementImpl::rendererIsNeeded(style);
657
658     KHTMLPart* part = getDocument()->part();
659     if (!part || !part->pluginsEnabled()) {
660         return false;
661     }
662 #if APPLE_CHANGES
663     // Eventually we will merge with the better version of this check on the tip of tree.
664     // Until then, just leave it out.
665 #else
666     KURL u = getDocument()->completeURL(url);
667     for (KHTMLPart* part = w->part()->parentPart(); part; part = part->parentPart())
668         if (part->url() == u) {
669             return false;
670         }
671 #endif
672     return true;
673 }
674
675 RenderObject *HTMLObjectElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
676 {
677     if (m_useFallbackContent)
678         return RenderObject::createObject(this, style);
679     if (isImageType())
680         return new (arena) RenderImage(this);
681     return new (arena) RenderPartObject(this);
682 }
683
684 void HTMLObjectElementImpl::attach()
685 {
686     HTMLElementImpl::attach();
687
688     if (m_render && !m_useFallbackContent) {
689         if (isImageType()) {
690             if (!m_imageLoader)
691                 m_imageLoader = new HTMLImageLoader(this);
692             m_imageLoader->updateFromElement();
693             if (renderer()) {
694                 RenderImage* imageObj = static_cast<RenderImage*>(renderer());
695                 imageObj->setImage(m_imageLoader->image());
696             }
697         } else {
698             if (needWidgetUpdate) {
699                 // Set needWidgetUpdate to false before calling updateWidget because updateWidget may cause
700                 // this method or recalcStyle (which also calls updateWidget) to be called.
701                 needWidgetUpdate = false;
702                 static_cast<RenderPartObject*>(m_render)->updateWidget();
703                 dispatchHTMLEvent(EventImpl::LOAD_EVENT,false,false);
704             } else {
705                 needWidgetUpdate = true;
706                 setChanged();
707             }
708         }
709     }
710 }
711
712 void HTMLObjectElementImpl::detach()
713 {
714     // Only bother with an unload event if we had a render object.  - dwh
715     if (attached() && m_render && !m_useFallbackContent)
716         // ### do this when we are actualy removed from document instead
717         dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
718
719   HTMLElementImpl::detach();
720 }
721
722 void HTMLObjectElementImpl::recalcStyle(StyleChange ch)
723 {
724     if (!m_useFallbackContent && needWidgetUpdate && m_render && !isImageType()) {
725         // Set needWidgetUpdate to false before calling updateWidget because updateWidget may cause
726         // this method or attach (which also calls updateWidget) to be called.
727         needWidgetUpdate = false;
728         static_cast<RenderPartObject*>(m_render)->updateWidget();
729         dispatchHTMLEvent(EventImpl::LOAD_EVENT,false,false);
730     }
731     HTMLElementImpl::recalcStyle(ch);
732 }
733
734 void HTMLObjectElementImpl::childrenChanged()
735 {
736     if (inDocument() && !m_useFallbackContent) {
737         needWidgetUpdate = true;
738         setChanged();
739     }
740 }
741
742 bool HTMLObjectElementImpl::isURLAttribute(AttributeImpl *attr) const
743 {
744     return (attr->id() == ATTR_DATA || (attr->id() == ATTR_USEMAP && attr->value().domString()[0] != '#'));
745 }
746
747 bool HTMLObjectElementImpl::isImageType()
748 {
749     if (serviceType.isEmpty() && url.startsWith("data:")) {
750         // Extract the MIME type from the data URL.
751         int index = url.find(';');
752         if (index == -1)
753             index = url.find(',');
754         if (index != -1) {
755             int len = index - 5;
756             if (len > 0)
757                 serviceType = url.mid(5, len);
758             else
759                 serviceType = "text/plain"; // Data URLs with no MIME type are considered text/plain.
760         }
761     }
762
763     return canRenderImageType(serviceType);
764 }
765
766 void HTMLObjectElementImpl::renderFallbackContent()
767 {
768     if (m_useFallbackContent)
769         return;
770
771     // Mark ourselves as using the fallback content.
772     m_useFallbackContent = true;
773
774     // Now do a detach and reattach.    
775     // FIXME: Style gets recalculated which is suboptimal.
776     detach();
777     attach();
778 }
779
780 DOMString HTMLObjectElementImpl::code() const
781 {
782     return getAttribute(ATTR_CODE);
783 }
784
785 void HTMLObjectElementImpl::setCode(const DOMString &value)
786 {
787     setAttribute(ATTR_CODE, value);
788 }
789
790 DOMString HTMLObjectElementImpl::align() const
791 {
792     return getAttribute(ATTR_ALIGN);
793 }
794
795 void HTMLObjectElementImpl::setAlign(const DOMString &value)
796 {
797     setAttribute(ATTR_ALIGN, value);
798 }
799
800 DOMString HTMLObjectElementImpl::archive() const
801 {
802     return getAttribute(ATTR_ARCHIVE);
803 }
804
805 void HTMLObjectElementImpl::setArchive(const DOMString &value)
806 {
807     setAttribute(ATTR_ARCHIVE, value);
808 }
809
810 DOMString HTMLObjectElementImpl::border() const
811 {
812     return getAttribute(ATTR_BORDER);
813 }
814
815 void HTMLObjectElementImpl::setBorder(const DOMString &value)
816 {
817     setAttribute(ATTR_BORDER, value);
818 }
819
820 DOMString HTMLObjectElementImpl::codeBase() const
821 {
822     return getAttribute(ATTR_CODEBASE);
823 }
824
825 void HTMLObjectElementImpl::setCodeBase(const DOMString &value)
826 {
827     setAttribute(ATTR_CODEBASE, value);
828 }
829
830 DOMString HTMLObjectElementImpl::codeType() const
831 {
832     return getAttribute(ATTR_CODETYPE);
833 }
834
835 void HTMLObjectElementImpl::setCodeType(const DOMString &value)
836 {
837     setAttribute(ATTR_CODETYPE, value);
838 }
839
840 DOMString HTMLObjectElementImpl::data() const
841 {
842     return getAttribute(ATTR_DATA);
843 }
844
845 void HTMLObjectElementImpl::setData(const DOMString &value)
846 {
847     setAttribute(ATTR_DATA, value);
848 }
849
850 bool HTMLObjectElementImpl::declare() const
851 {
852     return !getAttribute(ATTR_DECLARE).isNull();
853 }
854
855 void HTMLObjectElementImpl::setDeclare(bool declare)
856 {
857     setAttribute(ATTR_DECLARE, declare ? "" : 0);
858 }
859
860 DOMString HTMLObjectElementImpl::height() const
861 {
862     return getAttribute(ATTR_HEIGHT);
863 }
864
865 void HTMLObjectElementImpl::setHeight(const DOMString &value)
866 {
867     setAttribute(ATTR_HEIGHT, value);
868 }
869
870 DOMString HTMLObjectElementImpl::hspace() const
871 {
872     return getAttribute(ATTR_HSPACE);
873 }
874
875 void HTMLObjectElementImpl::setHspace(const DOMString &value)
876 {
877     setAttribute(ATTR_HSPACE, value);
878 }
879
880 DOMString HTMLObjectElementImpl::name() const
881 {
882     return getAttribute(ATTR_NAME);
883 }
884
885 void HTMLObjectElementImpl::setName(const DOMString &value)
886 {
887     setAttribute(ATTR_NAME, value);
888 }
889
890 DOMString HTMLObjectElementImpl::standby() const
891 {
892     return getAttribute(ATTR_STANDBY);
893 }
894
895 void HTMLObjectElementImpl::setStandby(const DOMString &value)
896 {
897     setAttribute(ATTR_STANDBY, value);
898 }
899
900 long HTMLObjectElementImpl::tabIndex() const
901 {
902     return getAttribute(ATTR_TABINDEX).toInt();
903 }
904
905 void HTMLObjectElementImpl::setTabIndex(long tabIndex)
906 {
907     setAttribute(ATTR_TABINDEX, QString::number(tabIndex));
908 }
909
910 DOMString HTMLObjectElementImpl::type() const
911 {
912     return getAttribute(ATTR_TYPE);
913 }
914
915 void HTMLObjectElementImpl::setType(const DOMString &value)
916 {
917     setAttribute(ATTR_TYPE, value);
918 }
919
920 DOMString HTMLObjectElementImpl::useMap() const
921 {
922     return getAttribute(ATTR_USEMAP);
923 }
924
925 void HTMLObjectElementImpl::setUseMap(const DOMString &value)
926 {
927     setAttribute(ATTR_USEMAP, value);
928 }
929
930 DOMString HTMLObjectElementImpl::vspace() const
931 {
932     return getAttribute(ATTR_VSPACE);
933 }
934
935 void HTMLObjectElementImpl::setVspace(const DOMString &value)
936 {
937     setAttribute(ATTR_VSPACE, value);
938 }
939
940 DOMString HTMLObjectElementImpl::width() const
941 {
942     return getAttribute(ATTR_WIDTH);
943 }
944
945 void HTMLObjectElementImpl::setWidth(const DOMString &value)
946 {
947     setAttribute(ATTR_WIDTH, value);
948 }
949
950 // -------------------------------------------------------------------------
951
952 HTMLParamElementImpl::HTMLParamElementImpl(DocumentPtr *doc)
953     : HTMLElementImpl(doc)
954 {
955 }
956
957 HTMLParamElementImpl::~HTMLParamElementImpl()
958 {
959 }
960
961 NodeImpl::Id HTMLParamElementImpl::id() const
962 {
963     return ID_PARAM;
964 }
965
966 void HTMLParamElementImpl::parseMappedAttribute(MappedAttributeImpl *attr)
967 {
968     switch( attr->id() )
969     {
970     case ATTR_ID:
971         // Must call base class so that hasID bit gets set.
972         HTMLElementImpl::parseMappedAttribute(attr);
973         if (getDocument()->htmlMode() != DocumentImpl::XHtml) break;
974         // fall through
975     case ATTR_NAME:
976         m_name = attr->value();
977         break;
978     case ATTR_VALUE:
979         m_value = attr->value();
980         break;
981     }
982 }
983
984 bool HTMLParamElementImpl::isURLAttribute(AttributeImpl *attr) const
985 {
986     if (attr->id() == ATTR_VALUE) {
987         AttributeImpl *attr = attributes()->getAttributeItem(ATTR_NAME);
988         if (attr) {
989             DOMString value = attr->value().string().lower();
990             if (value == "src" || value == "movie" || value == "data") {
991                 return true;
992             }
993         }
994     }
995     return false;
996 }
997
998 void HTMLParamElementImpl::setName(const DOMString &value)
999 {
1000     setAttribute(ATTR_NAME, value);
1001 }
1002
1003 DOMString HTMLParamElementImpl::type() const
1004 {
1005     return getAttribute(ATTR_TYPE);
1006 }
1007
1008 void HTMLParamElementImpl::setType(const DOMString &value)
1009 {
1010     setAttribute(ATTR_TYPE, value);
1011 }
1012
1013 void HTMLParamElementImpl::setValue(const DOMString &value)
1014 {
1015     setAttribute(ATTR_VALUE, value);
1016 }
1017
1018 DOMString HTMLParamElementImpl::valueType() const
1019 {
1020     return getAttribute(ATTR_VALUETYPE);
1021 }
1022
1023 void HTMLParamElementImpl::setValueType(const DOMString &value)
1024 {
1025     setAttribute(ATTR_VALUETYPE, value);
1026 }
1027
1028 }