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