da633c9795499f6f49103116c9b11a62dc767dc9
[WebKit-https.git] / WebCore / khtml / html / html_baseimpl.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 Simon Hausmann (hausmann@kde.org)
7  *           (C) 2001 Dirk Mueller (mueller@kde.org)
8  * Copyright (C) 2004 Apple Computer, Inc.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25 // -------------------------------------------------------------------------
26
27 #include "html/html_baseimpl.h"
28 #include "html/html_documentimpl.h"
29
30 #include "khtmlview.h"
31 #include "khtml_part.h"
32
33 #include "rendering/render_frames.h"
34 #include "css/cssstyleselector.h"
35 #include "css/css_stylesheetimpl.h"
36 #include "css/cssproperties.h"
37 #include "css/cssvalues.h"
38 #include "css/csshelper.h"
39 #include "misc/loader.h"
40 #include "misc/htmlhashes.h"
41 #include "dom/dom_string.h"
42 #include "dom/dom_doc.h"
43 #include "xml/dom2_eventsimpl.h"
44
45 #include <kurl.h>
46 #include <kdebug.h>
47
48 using namespace DOM;
49 using namespace khtml;
50
51 HTMLBodyElementImpl::HTMLBodyElementImpl(DocumentPtr *doc)
52     : HTMLElementImpl(doc), m_linkDecl(0)
53 {
54 }
55
56 HTMLBodyElementImpl::~HTMLBodyElementImpl()
57 {
58     if (m_linkDecl) {
59         m_linkDecl->setNode(0);
60         m_linkDecl->setParent(0);
61         m_linkDecl->deref();
62     }
63 }
64
65 NodeImpl::Id HTMLBodyElementImpl::id() const
66 {
67     return ID_BODY;
68 }
69
70 void HTMLBodyElementImpl::createLinkDecl()
71 {
72     m_linkDecl = new CSSMutableStyleDeclarationImpl;
73     m_linkDecl->ref();
74     m_linkDecl->setParent(getDocument()->elementSheet());
75     m_linkDecl->setNode(this);
76     m_linkDecl->setStrictParsing(!getDocument()->inCompatMode());
77 }
78
79 bool HTMLBodyElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
80 {
81     switch(attr)
82     {
83         case ATTR_BACKGROUND:
84         case ATTR_BGCOLOR:
85         case ATTR_TEXT:
86         case ATTR_MARGINWIDTH:
87         case ATTR_LEFTMARGIN:
88         case ATTR_MARGINHEIGHT:
89         case ATTR_TOPMARGIN:
90         case ATTR_BGPROPERTIES:
91             result = eUniversal;
92             return false;
93         default:
94             break;
95     }
96     
97     return HTMLElementImpl::mapToEntry(attr, result);
98 }
99
100 void HTMLBodyElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
101 {
102     switch(attr->id())
103     {
104     case ATTR_BACKGROUND:
105     {
106         QString url = khtml::parseURL( attr->value() ).string();
107         if (!url.isEmpty())
108             addCSSImageProperty(attr, CSS_PROP_BACKGROUND_IMAGE, getDocument()->completeURL(url));
109         break;
110     }
111     case ATTR_MARGINWIDTH:
112         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value() );
113         /* nobreak; */
114     case ATTR_LEFTMARGIN:
115         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value() );
116         break;
117     case ATTR_MARGINHEIGHT:
118         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
119         /* nobreak */
120     case ATTR_TOPMARGIN:
121         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
122         break;
123     case ATTR_BGCOLOR:
124         addHTMLColor(attr, CSS_PROP_BACKGROUND_COLOR, attr->value());
125         break;
126     case ATTR_TEXT:
127         addHTMLColor(attr, CSS_PROP_COLOR, attr->value());
128         break;
129     case ATTR_BGPROPERTIES:
130         if ( strcasecmp( attr->value(), "fixed" ) == 0)
131             addCSSProperty(attr, CSS_PROP_BACKGROUND_ATTACHMENT, CSS_VAL_FIXED);
132         break;
133     case ATTR_VLINK:
134     case ATTR_ALINK:
135     case ATTR_LINK:
136     {
137         if (attr->isNull()) {
138             if (attr->id() == ATTR_LINK)
139                 getDocument()->resetLinkColor();
140             else if (attr->id() == ATTR_VLINK)
141                 getDocument()->resetVisitedLinkColor();
142             else
143                 getDocument()->resetActiveLinkColor();
144         }
145         else {
146             if (!m_linkDecl)
147                 createLinkDecl();
148             m_linkDecl->setProperty(CSS_PROP_COLOR, attr->value(), false, false);
149             CSSValueImpl* val = m_linkDecl->getPropertyCSSValue(CSS_PROP_COLOR);
150             if (val) {
151                 val->ref();
152                 if (val->isPrimitiveValue()) {
153                     QColor col = getDocument()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValueImpl*>(val));
154                     if (attr->id() == ATTR_LINK)
155                         getDocument()->setLinkColor(col);
156                     else if (attr->id() == ATTR_VLINK)
157                         getDocument()->setVisitedLinkColor(col);
158                     else
159                         getDocument()->setActiveLinkColor(col);
160                 }
161                 val->deref();
162             }
163         }
164         
165         if (attached())
166             getDocument()->recalcStyle(Force);
167         break;
168     }
169     case ATTR_ONLOAD:
170         getDocument()->setHTMLWindowEventListener(EventImpl::LOAD_EVENT,
171             getDocument()->createHTMLEventListener(attr->value().string(), this));
172         break;
173     case ATTR_ONUNLOAD:
174         getDocument()->setHTMLWindowEventListener(EventImpl::UNLOAD_EVENT,
175             getDocument()->createHTMLEventListener(attr->value().string(), this));
176         break;
177     case ATTR_ONBLUR:
178         getDocument()->setHTMLWindowEventListener(EventImpl::BLUR_EVENT,
179             getDocument()->createHTMLEventListener(attr->value().string(), this));
180         break;
181     case ATTR_ONFOCUS:
182         getDocument()->setHTMLWindowEventListener(EventImpl::FOCUS_EVENT,
183             getDocument()->createHTMLEventListener(attr->value().string(), this));
184         break;
185     case ATTR_ONRESIZE:
186         getDocument()->setHTMLWindowEventListener(EventImpl::RESIZE_EVENT,
187             getDocument()->createHTMLEventListener(attr->value().string(), this));
188         break;
189     case ATTR_ONSCROLL:
190         getDocument()->setHTMLWindowEventListener(EventImpl::SCROLL_EVENT,
191                                                   getDocument()->createHTMLEventListener(attr->value().string(), this));
192         break;
193     case ATTR_NOSAVE:
194         break;
195     default:
196         HTMLElementImpl::parseHTMLAttribute(attr);
197     }
198 }
199
200 void HTMLBodyElementImpl::insertedIntoDocument()
201 {
202     HTMLElementImpl::insertedIntoDocument();
203
204     // FIXME: perhaps this code should be in attach() instead of here
205
206     DocumentImpl *d = getDocument();
207     KHTMLView *w = d ? d->view() : 0;
208     if (w && w->marginWidth() != -1) {
209         QString s;
210         s.sprintf( "%d", w->marginWidth() );
211         setAttribute(ATTR_MARGINWIDTH, s);
212     }
213     if (w && w->marginHeight() != -1) {
214         QString s;
215         s.sprintf( "%d", w->marginHeight() );
216         setAttribute(ATTR_MARGINHEIGHT, s);
217     }
218
219     if (w)
220         w->scheduleRelayout();
221 }
222
223 bool HTMLBodyElementImpl::isURLAttribute(AttributeImpl *attr) const
224 {
225     return attr->id() == ATTR_BACKGROUND;
226 }
227
228 // -------------------------------------------------------------------------
229
230 HTMLFrameElementImpl::HTMLFrameElementImpl(DocumentPtr *doc)
231     : HTMLElementImpl(doc)
232 {
233     frameBorder = true;
234     frameBorderSet = false;
235     marginWidth = -1;
236     marginHeight = -1;
237     scrolling = QScrollView::Auto;
238     noresize = false;
239 }
240
241 HTMLFrameElementImpl::~HTMLFrameElementImpl()
242 {
243 }
244
245 NodeImpl::Id HTMLFrameElementImpl::id() const
246 {
247     return ID_FRAME;
248 }
249
250 bool HTMLFrameElementImpl::isURLAllowed(const AtomicString &URLString) const
251 {
252     if (URLString.isEmpty()) {
253         return true;
254     }
255     
256     DocumentImpl *d = getDocument();
257     KHTMLView *w = d ? d->view() : 0;
258
259     if (!w) {
260         return false;
261     }
262
263     KURL newURL(getDocument()->completeURL(URLString.string()));
264     newURL.setRef(QString::null);
265
266     // Don't allow more than 1000 total frames in a set. This seems
267     // like a reasonable upper bound, and otherwise mutually recursive
268     // frameset pages can quickly bring the program to its knees with
269     // exponential growth in the number of frames.
270
271     // FIXME: This limit could be higher, but WebKit has some
272     // algorithms that happen while loading which appear to be N^2 or
273     // worse in the number of frames
274     if (w->part()->topLevelFrameCount() >= 200) {
275         return false;
276     }
277
278     // Prohibit non-file URLs if we are asked to.
279     if (w->part()->onlyLocalReferences() && newURL.protocol().lower() != "file") {
280         return false;
281     }
282
283     // We allow one level of self-reference because some sites depend on that.
284     // But we don't allow more than one.
285     bool foundSelfReference = false;
286     for (KHTMLPart *part = w->part(); part; part = part->parentPart()) {
287         KURL partURL = part->url();
288         partURL.setRef(QString::null);
289         if (partURL == newURL) {
290             if (foundSelfReference) {
291                 return false;
292             }
293             foundSelfReference = true;
294         }
295     }
296     
297     return true;
298 }
299
300 void HTMLFrameElementImpl::updateForNewURL()
301 {
302     if (!attached()) {
303         return;
304     }
305     
306     // Handle the common case where we decided not to make a frame the first time.
307     // Detach and the let attach() decide again whether to make the frame for this URL.
308     if (!m_render) {
309         detach();
310         attach();
311         return;
312     }
313     
314     if (!isURLAllowed(url)) {
315         return;
316     }
317
318     openURL();
319 }
320
321 void HTMLFrameElementImpl::openURL()
322 {
323     DocumentImpl *d = getDocument();
324     KHTMLView *w = d ? d->view() : 0;
325     if (!w) {
326         return;
327     }
328     
329     AtomicString relativeURL = url;
330     if (relativeURL.isEmpty()) {
331         relativeURL = "about:blank";
332     }
333
334     // Load the frame contents.
335     KHTMLPart *part = w->part();
336     KHTMLPart *framePart = part->findFrame(name.string());
337     if (framePart) {
338         framePart->openURL(getDocument()->completeURL(relativeURL.string()));
339     } else {
340         part->requestFrame(static_cast<RenderFrame *>(m_render), relativeURL.string(), name.string());
341     }
342 }
343
344
345 void HTMLFrameElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
346 {
347     switch(attr->id())
348     {
349     case ATTR_SRC:
350         setLocation(khtml::parseURL(attr->value()));
351         break;
352     case ATTR_ID:
353         // Important to call through to base for ATTR_ID so the hasID bit gets set.
354         HTMLElementImpl::parseHTMLAttribute(attr);
355         // fall through
356     case ATTR_NAME:
357         name = attr->value();
358         // FIXME: If we are already attached, this doesn't actually change the frame's name.
359         // FIXME: If we are already attached, this doesn't check for frame name
360         // conflicts and generate a unique frame name.
361         break;
362     case ATTR_FRAMEBORDER:
363         frameBorder = attr->value().toInt();
364         frameBorderSet = !attr->isNull();
365         // FIXME: If we are already attached, this has no effect.
366         break;
367     case ATTR_MARGINWIDTH:
368         marginWidth = attr->value().toInt();
369         // FIXME: If we are already attached, this has no effect.
370         break;
371     case ATTR_MARGINHEIGHT:
372         marginHeight = attr->value().toInt();
373         // FIXME: If we are already attached, this has no effect.
374         break;
375     case ATTR_NORESIZE:
376         noresize = true;
377         // FIXME: If we are already attached, this has no effect.
378         break;
379     case ATTR_SCROLLING:
380         kdDebug( 6031 ) << "set scroll mode" << endl;
381         // Auto and yes both simply mean "allow scrolling."  No means
382         // "don't allow scrolling."
383         if( strcasecmp( attr->value(), "auto" ) == 0 ||
384             strcasecmp( attr->value(), "yes" ) == 0 )
385             scrolling = QScrollView::Auto;
386         else if( strcasecmp( attr->value(), "no" ) == 0 )
387             scrolling = QScrollView::AlwaysOff;
388         // FIXME: If we are already attached, this has no effect.
389         break;
390     case ATTR_ONLOAD:
391         setHTMLEventListener(EventImpl::LOAD_EVENT,
392                                 getDocument()->createHTMLEventListener(attr->value().string(), this));
393         break;
394     case ATTR_ONUNLOAD:
395         setHTMLEventListener(EventImpl::UNLOAD_EVENT,
396                                 getDocument()->createHTMLEventListener(attr->value().string(), this));
397         break;
398     default:
399         HTMLElementImpl::parseHTMLAttribute(attr);
400     }
401 }
402
403 bool HTMLFrameElementImpl::rendererIsNeeded(RenderStyle *style)
404 {
405     // Ignore display: none.
406     return isURLAllowed(url);
407 }
408
409 RenderObject *HTMLFrameElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
410 {
411     return new (arena) RenderFrame(this);
412 }
413
414 void HTMLFrameElementImpl::attach()
415 {
416     // we should first look up via id, then via name.
417     // this shortterm hack fixes the ugly case. ### rewrite needed for next release
418     name = getAttribute(ATTR_NAME);
419     if (name.isNull())
420         name = getAttribute(ATTR_ID);
421
422     // inherit default settings from parent frameset
423     HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
424     while(node)
425     {
426         if(node->id() == ID_FRAMESET)
427         {
428             HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
429             if(!frameBorderSet)  frameBorder = frameset->frameBorder();
430             if(!noresize)  noresize = frameset->noResize();
431             break;
432         }
433         node = static_cast<HTMLElementImpl*>(node->parentNode());
434     }
435
436     HTMLElementImpl::attach();
437
438     if (!m_render)
439         return;
440
441     KHTMLPart *part = getDocument()->part();
442
443     if (!part)
444         return;
445
446     part->incrementFrameCount();
447     
448     AtomicString relativeURL = url;
449     if (relativeURL.isEmpty()) {
450         relativeURL = "about:blank";
451     }
452
453     // we need a unique name for every frame in the frameset. Hope that's unique enough.
454     if (name.isEmpty() || part->frameExists( name.string() ) )
455       name = AtomicString(part->requestFrameName());
456
457     // load the frame contents
458     part->requestFrame( static_cast<RenderFrame*>(m_render), relativeURL.string(), name.string() );
459 }
460
461 void HTMLFrameElementImpl::detach()
462 {
463     KHTMLPart *part = getDocument()->part();
464
465     if (m_render && part) {
466         part->decrementFrameCount();
467         KHTMLPart *framePart = part->findFrame( name.string() );
468         if (framePart)
469             framePart->frameDetached();
470     }
471
472     HTMLElementImpl::detach();
473 }
474
475 void HTMLFrameElementImpl::setLocation( const DOMString& str )
476 {
477     if (url == str) return;
478     url = AtomicString(str);
479     updateForNewURL();
480 }
481
482 bool HTMLFrameElementImpl::isFocusable() const
483 {
484     return m_render!=0;
485 }
486
487 void HTMLFrameElementImpl::setFocus(bool received)
488 {
489     HTMLElementImpl::setFocus(received);
490     khtml::RenderFrame *renderFrame = static_cast<khtml::RenderFrame *>(m_render);
491     if (!renderFrame || !renderFrame->widget())
492         return;
493     if (received)
494         renderFrame->widget()->setFocus();
495     else
496         renderFrame->widget()->clearFocus();
497 }
498
499 KHTMLPart* HTMLFrameElementImpl::contentPart() const
500 {
501     // Start with the part that contains this element, our ownerDocument.
502     KHTMLPart* ownerDocumentPart = getDocument()->part();
503     if (!ownerDocumentPart) {
504         return 0;
505     }
506
507     // Find the part for the subframe that this element represents.
508     return ownerDocumentPart->findFrame(name.string());
509 }
510
511 DocumentImpl* HTMLFrameElementImpl::contentDocument() const
512 {
513     KHTMLPart* part = contentPart();
514     if (!part) {
515         return 0;
516     }
517
518     // Return the document for that part, which is our contentDocument.
519     return part->xmlDocImpl();
520 }
521
522 bool HTMLFrameElementImpl::isURLAttribute(AttributeImpl *attr) const
523 {
524     return attr->id() == ATTR_SRC;
525 }
526
527 // -------------------------------------------------------------------------
528
529 HTMLFrameSetElementImpl::HTMLFrameSetElementImpl(DocumentPtr *doc)
530     : HTMLElementImpl(doc)
531 {
532     // default value for rows and cols...
533     m_totalRows = 1;
534     m_totalCols = 1;
535
536     m_rows = m_cols = 0;
537
538     frameborder = true;
539     frameBorderSet = false;
540     m_border = 4;
541     noresize = false;
542
543     m_resizing = false;
544 }
545
546 HTMLFrameSetElementImpl::~HTMLFrameSetElementImpl()
547 {
548     if (m_rows)
549         delete [] m_rows;
550     if (m_cols)
551         delete [] m_cols;
552 }
553
554 NodeImpl::Id HTMLFrameSetElementImpl::id() const
555 {
556     return ID_FRAMESET;
557 }
558
559 void HTMLFrameSetElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr)
560 {
561     switch(attr->id())
562     {
563     case ATTR_ROWS:
564         if (attr->isNull()) break;
565         if (m_rows) delete [] m_rows;
566         m_rows = attr->value().toLengthArray(m_totalRows);
567         setChanged();
568     break;
569     case ATTR_COLS:
570         if (attr->isNull()) break;
571         delete [] m_cols;
572         m_cols = attr->value().toLengthArray(m_totalCols);
573         setChanged();
574     break;
575     case ATTR_FRAMEBORDER:
576         // false or "no" or "0"..
577         if ( attr->value().toInt() == 0 ) {
578             frameborder = false;
579             m_border = 0;
580         }
581         frameBorderSet = true;
582         break;
583     case ATTR_NORESIZE:
584         noresize = true;
585         break;
586     case ATTR_BORDER:
587         m_border = attr->value().toInt();
588         if(!m_border)
589             frameborder = false;
590         break;
591     case ATTR_ONLOAD:
592         setHTMLEventListener(EventImpl::LOAD_EVENT,
593             getDocument()->createHTMLEventListener(attr->value().string(), this));
594         break;
595     case ATTR_ONUNLOAD:
596         setHTMLEventListener(EventImpl::UNLOAD_EVENT,
597             getDocument()->createHTMLEventListener(attr->value().string(), this));
598         break;
599     default:
600         HTMLElementImpl::parseHTMLAttribute(attr);
601     }
602 }
603
604 bool HTMLFrameSetElementImpl::rendererIsNeeded(RenderStyle *style)
605 {
606     // Ignore display: none but do pay attention if a stylesheet has caused us to delay our loading.
607     return style->isStyleAvailable();
608 }
609
610 RenderObject *HTMLFrameSetElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
611 {
612     return new (arena) RenderFrameSet(this);
613 }
614
615 void HTMLFrameSetElementImpl::attach()
616 {
617     // inherit default settings from parent frameset
618     HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
619     while(node)
620     {
621         if(node->id() == ID_FRAMESET)
622         {
623             HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
624             if(!frameBorderSet)  frameborder = frameset->frameBorder();
625             if(!noresize)  noresize = frameset->noResize();
626             break;
627         }
628         node = static_cast<HTMLElementImpl*>(node->parentNode());
629     }
630
631     HTMLElementImpl::attach();
632 }
633
634 void HTMLFrameSetElementImpl::defaultEventHandler(EventImpl *evt)
635 {
636     if (evt->isMouseEvent() && !noresize && m_render) {
637         static_cast<khtml::RenderFrameSet *>(m_render)->userResize(static_cast<MouseEventImpl*>(evt));
638         evt->setDefaultHandled();
639     }
640
641     HTMLElementImpl::defaultEventHandler(evt);
642 }
643
644 void HTMLFrameSetElementImpl::detach()
645 {
646     if(attached())
647         // ### send the event when we actually get removed from the doc instead of here
648         dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
649
650     HTMLElementImpl::detach();
651 }
652
653 void HTMLFrameSetElementImpl::recalcStyle( StyleChange ch )
654 {
655     if (changed() && m_render) {
656         m_render->setNeedsLayout(true);
657 //         m_render->layout();
658         setChanged(false);
659     }
660     HTMLElementImpl::recalcStyle( ch );
661 }
662
663 // -------------------------------------------------------------------------
664
665 HTMLHeadElementImpl::HTMLHeadElementImpl(DocumentPtr *doc)
666     : HTMLElementImpl(doc)
667 {
668 }
669
670 HTMLHeadElementImpl::~HTMLHeadElementImpl()
671 {
672 }
673
674 NodeImpl::Id HTMLHeadElementImpl::id() const
675 {
676     return ID_HEAD;
677 }
678
679 // -------------------------------------------------------------------------
680
681 HTMLHtmlElementImpl::HTMLHtmlElementImpl(DocumentPtr *doc)
682     : HTMLElementImpl(doc)
683 {
684 }
685
686 HTMLHtmlElementImpl::~HTMLHtmlElementImpl()
687 {
688 }
689
690 NodeImpl::Id HTMLHtmlElementImpl::id() const
691 {
692     return ID_HTML;
693 }
694
695 // -------------------------------------------------------------------------
696
697 HTMLIFrameElementImpl::HTMLIFrameElementImpl(DocumentPtr *doc) : HTMLFrameElementImpl(doc)
698 {
699     frameBorder = false;
700     marginWidth = -1;
701     marginHeight = -1;
702     needWidgetUpdate = false;
703 }
704
705 HTMLIFrameElementImpl::~HTMLIFrameElementImpl()
706 {
707 }
708
709 NodeImpl::Id HTMLIFrameElementImpl::id() const
710 {
711     return ID_IFRAME;
712 }
713
714 bool HTMLIFrameElementImpl::mapToEntry(NodeImpl::Id attr, MappedAttributeEntry& result) const
715 {
716     switch (attr) {
717         case ATTR_WIDTH:
718         case ATTR_HEIGHT:
719             result = eUniversal;
720             return false;
721         case ATTR_ALIGN:
722             result = eReplaced; // Share with <img> since the alignment behavior is the same.
723             return false;
724         default:
725             break;
726     }
727     
728     return HTMLElementImpl::mapToEntry(attr, result);
729 }
730
731 void HTMLIFrameElementImpl::parseHTMLAttribute(HTMLAttributeImpl *attr )
732 {
733   switch (  attr->id() )
734   {
735     case ATTR_WIDTH:
736       addCSSLength( attr, CSS_PROP_WIDTH, attr->value());
737       break;
738     case ATTR_HEIGHT:
739       addCSSLength( attr, CSS_PROP_HEIGHT, attr->value() );
740       break;
741     case ATTR_ALIGN:
742       addHTMLAlignment( attr );
743       break;
744     default:
745       HTMLFrameElementImpl::parseHTMLAttribute( attr );
746   }
747 }
748
749 bool HTMLIFrameElementImpl::rendererIsNeeded(RenderStyle *style)
750 {
751     // Don't ignore display: none the way frame does.
752     return isURLAllowed(url) && style->display() != NONE;
753 }
754
755 RenderObject *HTMLIFrameElementImpl::createRenderer(RenderArena *arena, RenderStyle *style)
756 {
757     return new (arena) RenderPartObject(this);
758 }
759
760 void HTMLIFrameElementImpl::attach()
761 {
762     HTMLElementImpl::attach();
763
764     KHTMLPart *part = getDocument()->part();
765     if (m_render && part) {
766         // we need a unique name for every frame in the frameset. Hope that's unique enough.
767         part->incrementFrameCount();
768         if(name.isEmpty() || part->frameExists( name.string() ))
769             name = AtomicString(part->requestFrameName());
770
771         static_cast<RenderPartObject*>(m_render)->updateWidget();
772         needWidgetUpdate = false;
773     }
774 }
775
776 void HTMLIFrameElementImpl::recalcStyle( StyleChange ch )
777 {
778     if (needWidgetUpdate) {
779         if(m_render)  static_cast<RenderPartObject*>(m_render)->updateWidget();
780         needWidgetUpdate = false;
781     }
782     HTMLElementImpl::recalcStyle( ch );
783 }
784
785 void HTMLIFrameElementImpl::openURL()
786 {
787     needWidgetUpdate = true;
788     setChanged();
789 }
790
791 bool HTMLIFrameElementImpl::isURLAttribute(AttributeImpl *attr) const
792 {
793     return attr->id() == ATTR_SRC;
794 }