khtml Library API Documentation

html_baseimpl.cpp

00001 
00024 // -------------------------------------------------------------------------
00025 
00026 #include "html/html_baseimpl.h"
00027 #include "html/html_documentimpl.h"
00028 
00029 #include "khtmlview.h"
00030 #include "khtml_part.h"
00031 
00032 #include "rendering/render_frames.h"
00033 #include "rendering/render_html.h"
00034 #include "rendering/render_body.h"
00035 #include "css/cssstyleselector.h"
00036 #include "css/css_stylesheetimpl.h"
00037 #include "css/cssproperties.h"
00038 #include "css/cssvalues.h"
00039 #include "css/csshelper.h"
00040 #include "misc/loader.h"
00041 #include "misc/htmlhashes.h"
00042 #include "dom/dom_string.h"
00043 #include "dom/dom_doc.h"
00044 #include "xml/dom2_eventsimpl.h"
00045 
00046 #include <kurl.h>
00047 #include <kdebug.h>
00048 
00049 using namespace DOM;
00050 using namespace khtml;
00051 
00052 HTMLBodyElementImpl::HTMLBodyElementImpl(DocumentPtr *doc)
00053     : HTMLElementImpl(doc),
00054     m_bgSet( false ), m_fgSet( false )
00055 {
00056     m_styleSheet = 0;
00057 }
00058 
00059 HTMLBodyElementImpl::~HTMLBodyElementImpl()
00060 {
00061     if(m_styleSheet) m_styleSheet->deref();
00062 }
00063 
00064 NodeImpl::Id HTMLBodyElementImpl::id() const
00065 {
00066     return ID_BODY;
00067 }
00068 
00069 void HTMLBodyElementImpl::parseAttribute(AttributeImpl *attr)
00070 {
00071     switch(attr->id())
00072     {
00073 
00074     case ATTR_BACKGROUND:
00075     {
00076         QString url = khtml::parseURL( attr->value() ).string();
00077         if (!url.isEmpty()) {
00078             url = getDocument()->completeURL( url );
00079             addCSSProperty(CSS_PROP_BACKGROUND_IMAGE, "url('"+url+"')" );
00080             m_bgSet = true;
00081         }
00082         else
00083             m_bgSet = false;
00084         break;
00085     }
00086     case ATTR_MARGINWIDTH: {
00087     KHTMLView* w = getDocument()->view();
00088     w->setMarginWidth( -1 ); // unset this, so it doesn't override the setting here
00089         addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value() );
00090     }
00091         /* nobreak; */
00092     case ATTR_LEFTMARGIN:
00093         addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value() );
00094         break;
00095     case ATTR_MARGINHEIGHT: {
00096     KHTMLView* w = getDocument()->view();
00097     w->setMarginHeight( -1 ); // unset this, so it doesn't override the setting here
00098         addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
00099     }
00100         /* nobreak */
00101     case ATTR_TOPMARGIN:
00102         addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
00103         break;
00104     case ATTR_BGCOLOR:
00105         addCSSProperty(CSS_PROP_BACKGROUND_COLOR, attr->value());
00106         m_bgSet = !attr->value().isNull();
00107         break;
00108     case ATTR_TEXT:
00109         addCSSProperty(CSS_PROP_COLOR, attr->value());
00110         m_fgSet = !attr->value().isNull();
00111         break;
00112     case ATTR_BGPROPERTIES:
00113         if ( strcasecmp( attr->value(), "fixed" ) == 0)
00114             addCSSProperty(CSS_PROP_BACKGROUND_ATTACHMENT, CSS_VAL_FIXED);
00115         break;
00116     case ATTR_VLINK:
00117     case ATTR_ALINK:
00118     case ATTR_LINK:
00119     {
00120         if(!m_styleSheet) {
00121             m_styleSheet = new CSSStyleSheetImpl(this,DOMString(),true);
00122             m_styleSheet->ref();
00123         }
00124         QString aStr;
00125     if ( attr->id() == ATTR_LINK )
00126         aStr = "a:link";
00127     else if ( attr->id() == ATTR_VLINK )
00128         aStr = "a:visited";
00129     else if ( attr->id() == ATTR_ALINK )
00130         aStr = "a:active";
00131     aStr += " { color: " + attr->value().string() + "; }";
00132         m_styleSheet->parseString(aStr);
00133         m_styleSheet->setNonCSSHints();
00134         break;
00135     }
00136     case ATTR_ONLOAD:
00137         getDocument()->setWindowEventListener(EventImpl::LOAD_EVENT,
00138         getDocument()->createHTMLEventListener(attr->value().string()));
00139         break;
00140     case ATTR_ONUNLOAD:
00141         getDocument()->setWindowEventListener(EventImpl::UNLOAD_EVENT,
00142         getDocument()->createHTMLEventListener(attr->value().string()));
00143         break;
00144     case ATTR_ONBLUR:
00145         getDocument()->setWindowEventListener(EventImpl::BLUR_EVENT,
00146         getDocument()->createHTMLEventListener(attr->value().string()));
00147         break;
00148     case ATTR_ONFOCUS:
00149         getDocument()->setWindowEventListener(EventImpl::FOCUS_EVENT,
00150         getDocument()->createHTMLEventListener(attr->value().string()));
00151         break;
00152     case ATTR_ONRESIZE:
00153         getDocument()->setWindowEventListener(EventImpl::RESIZE_EVENT,
00154         getDocument()->createHTMLEventListener(attr->value().string()));
00155         break;
00156     case ATTR_NOSAVE:
00157     break;
00158     default:
00159         HTMLElementImpl::parseAttribute(attr);
00160     }
00161 }
00162 
00163 void HTMLBodyElementImpl::insertedIntoDocument()
00164 {
00165     HTMLElementImpl::insertedIntoDocument();
00166 
00167     KHTMLView* w = getDocument()->view();
00168     if(w->marginWidth() != -1) {
00169         QString s;
00170         s.sprintf( "%d", w->marginWidth() );
00171         addCSSLength(CSS_PROP_MARGIN_LEFT, s);
00172         addCSSLength(CSS_PROP_MARGIN_RIGHT, s);
00173     }
00174     if(w->marginHeight() != -1) {
00175         QString s;
00176         s.sprintf( "%d", w->marginHeight() );
00177         addCSSLength(CSS_PROP_MARGIN_TOP, s);
00178         addCSSLength(CSS_PROP_MARGIN_BOTTOM, s);
00179     }
00180 
00181     if ( m_bgSet && !m_fgSet )
00182         addCSSProperty(CSS_PROP_COLOR, "#000000");
00183 
00184     if (m_styleSheet)
00185         getDocument()->updateStyleSelector();
00186 }
00187 
00188 void HTMLBodyElementImpl::removedFromDocument()
00189 {
00190     HTMLElementImpl::removedFromDocument();
00191 
00192     if (m_styleSheet)
00193         getDocument()->updateStyleSelector();
00194 }
00195 
00196 void HTMLBodyElementImpl::attach()
00197 {
00198     assert(!m_render);
00199     assert(parentNode());
00200     assert(parentNode()->renderer());
00201 
00202     RenderStyle* style = getDocument()->styleSelector()->styleForElement(this);
00203     style->ref();
00204     if (style->display() != NONE) {
00205         m_render = new RenderBody(this);
00206         m_render->setStyle(style);
00207         parentNode()->renderer()->addChild(m_render, nextRenderer());
00208     }
00209     style->deref();
00210 
00211     NodeBaseImpl::attach();
00212 }
00213 
00214 // -------------------------------------------------------------------------
00215 
00216 HTMLFrameElementImpl::HTMLFrameElementImpl(DocumentPtr *doc)
00217     : HTMLElementImpl(doc)
00218 {
00219     frameBorder = true;
00220     frameBorderSet = false;
00221     marginWidth = -1;
00222     marginHeight = -1;
00223     scrolling = QScrollView::Auto;
00224     noresize = false;
00225     url = "about:blank";
00226 }
00227 
00228 HTMLFrameElementImpl::~HTMLFrameElementImpl()
00229 {
00230 }
00231 
00232 NodeImpl::Id HTMLFrameElementImpl::id() const
00233 {
00234     return ID_FRAME;
00235 }
00236 
00237 void HTMLFrameElementImpl::parseAttribute(AttributeImpl *attr)
00238 {
00239     switch(attr->id())
00240     {
00241     case ATTR_SRC:
00242         url = khtml::parseURL(attr->val());
00243         // FIXME_APPLE: load new url in the iframe
00244         setChanged();
00245         break;
00246     case ATTR_ID:
00247     case ATTR_NAME:
00248         // FIXME: if already attached, doesn't change the frame name
00249         // FIXME: frame name conflicts, no unique frame name anymore
00250         name = attr->value();
00251         break;
00252     case ATTR_FRAMEBORDER:
00253     {
00254         frameBorder = attr->value().toInt();
00255         frameBorderSet = ( attr->val() != 0 );
00256         // FIXME: when attached, has no effect
00257     }
00258     break;
00259     case ATTR_MARGINWIDTH:
00260         marginWidth = attr->val()->toInt();
00261         // FIXME: when attached, has no effect
00262         break;
00263     case ATTR_MARGINHEIGHT:
00264         marginHeight = attr->val()->toInt();
00265         // FIXME: when attached, has no effect
00266         break;
00267     case ATTR_NORESIZE:
00268         noresize = true;
00269         // FIXME: when attached, has no effect
00270         break;
00271     case ATTR_SCROLLING:
00272         if( strcasecmp( attr->value(), "auto" ) == 0 )
00273             scrolling = QScrollView::Auto;
00274         else if( strcasecmp( attr->value(), "yes" ) == 0 )
00275             scrolling = QScrollView::AlwaysOn;
00276         else if( strcasecmp( attr->value(), "no" ) == 0 )
00277             scrolling = QScrollView::AlwaysOff;
00278         // when attached, has no effect
00279         break;
00280     case ATTR_ONLOAD:
00281         static_cast<HTMLDocumentImpl*>( getDocument() )->body()
00282               ->setHTMLEventListener(EventImpl::LOAD_EVENT,
00283             getDocument()->createHTMLEventListener(attr->value().string()));
00284         break;
00285     case ATTR_ONUNLOAD:
00286         static_cast<HTMLDocumentImpl*>( getDocument() )->body()
00287               ->setHTMLEventListener(EventImpl::UNLOAD_EVENT,
00288             getDocument()->createHTMLEventListener(attr->value().string()));
00289         break;
00290 
00291     default:
00292         HTMLElementImpl::parseAttribute(attr);
00293     }
00294 }
00295 
00296 void HTMLFrameElementImpl::attach()
00297 {
00298     assert(!attached());
00299     assert(parentNode());
00300     assert(parentNode()->renderer());
00301 
00302     // we should first look up via id, then via name.
00303     // this shortterm hack fixes the ugly case. ### rewrite needed for next release
00304     name = getAttribute(ATTR_NAME);
00305     if (name.isNull())
00306         name = getAttribute(ATTR_ID);
00307 
00308     // inherit default settings from parent frameset
00309     HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
00310     while(node)
00311     {
00312         if(node->id() == ID_FRAMESET)
00313         {
00314             HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
00315             if(!frameBorderSet)  frameBorder = frameset->frameBorder();
00316             if(!noresize)  noresize = frameset->noResize();
00317             break;
00318         }
00319         node = static_cast<HTMLElementImpl*>(node->parentNode());
00320     }
00321 
00322     // ignore display: none for this element!
00323     KHTMLView* w = getDocument()->view();
00324 
00325     if (isURLAllowed(url.string()))  {
00326         m_render = new RenderFrame(this);
00327         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
00328         parentNode()->renderer()->addChild(m_render, nextRenderer());
00329     }
00330 
00331     NodeBaseImpl::attach();
00332 
00333     if (!m_render)
00334         return;
00335 
00336     // we need a unique name for every frame in the frameset. Hope that's unique enough.
00337     if(name.isEmpty() || w->part()->frameExists( name.string() ) )
00338       name = DOMString(w->part()->requestFrameName());
00339 
00340     // load the frame contents
00341     w->part()->requestFrame( static_cast<RenderFrame*>(m_render), url.string(), name.string() );
00342 }
00343 
00344 void HTMLFrameElementImpl::setLocation( const DOMString& str )
00345 {
00346     url = str;
00347     KHTMLView* w = getDocument()->view();
00348     if ( m_render && w && w->part() )
00349         // don't call this for an iframe
00350         w->part()->requestFrame( static_cast<khtml::RenderFrame *>(m_render), url.string(), name.string() );
00351 }
00352 
00353 bool HTMLFrameElementImpl::isSelectable() const
00354 {
00355     return m_render!=0;
00356 }
00357 
00358 void HTMLFrameElementImpl::setFocus(bool received)
00359 {
00360     HTMLElementImpl::setFocus(received);
00361     khtml::RenderFrame *renderFrame = static_cast<khtml::RenderFrame *>(m_render);
00362     if (!renderFrame || !renderFrame->widget())
00363     return;
00364     if (received)
00365     renderFrame->widget()->setFocus();
00366     else
00367     renderFrame->widget()->clearFocus();
00368 }
00369 
00370 DocumentImpl* HTMLFrameElementImpl::contentDocument() const
00371 {
00372     if ( !m_render ) return 0;
00373 
00374     RenderPart* render = static_cast<RenderPart*>( m_render );
00375 
00376     if(render->widget() && render->widget()->inherits("KHTMLView"))
00377         return static_cast<KHTMLView*>( render->widget() )->part()->xmlDocImpl();
00378 
00379     return 0;
00380 }
00381 
00382 // -------------------------------------------------------------------------
00383 
00384 HTMLFrameSetElementImpl::HTMLFrameSetElementImpl(DocumentPtr *doc)
00385     : HTMLElementImpl(doc)
00386 {
00387     // default value for rows and cols...
00388     m_totalRows = 1;
00389     m_totalCols = 1;
00390 
00391     m_rows = m_cols = 0;
00392 
00393     frameborder = true;
00394     frameBorderSet = false;
00395     m_border = 4;
00396     noresize = false;
00397 
00398     m_resizing = false;
00399 }
00400 
00401 HTMLFrameSetElementImpl::~HTMLFrameSetElementImpl()
00402 {
00403     if (m_rows)
00404         delete [] m_rows;
00405     if (m_cols)
00406         delete [] m_cols;
00407 }
00408 
00409 NodeImpl::Id HTMLFrameSetElementImpl::id() const
00410 {
00411     return ID_FRAMESET;
00412 }
00413 
00414 void HTMLFrameSetElementImpl::parseAttribute(AttributeImpl *attr)
00415 {
00416     switch(attr->id())
00417     {
00418     case ATTR_ROWS:
00419         if (!attr->val()) break;
00420         if (m_rows) delete [] m_rows;
00421         m_rows = attr->val()->toLengthArray(m_totalRows);
00422         setChanged();
00423     break;
00424     case ATTR_COLS:
00425         if (!attr->val()) break;
00426         delete [] m_cols;
00427         m_cols = attr->val()->toLengthArray(m_totalCols);
00428         setChanged();
00429     break;
00430     case ATTR_FRAMEBORDER:
00431         // false or "no" or "0"..
00432         if ( attr->value().toInt() == 0 ) {
00433             frameborder = false;
00434             m_border = 0;
00435         }
00436         frameBorderSet = true;
00437         break;
00438     case ATTR_NORESIZE:
00439         noresize = true;
00440         break;
00441     case ATTR_BORDER:
00442         m_border = attr->val()->toInt();
00443         if(!m_border)
00444             frameborder = false;
00445         break;
00446     case ATTR_ONLOAD:
00447         getDocument()->setHTMLEventListener(EventImpl::LOAD_EVENT,
00448         getDocument()->createHTMLEventListener(attr->value().string()));
00449         break;
00450     case ATTR_ONUNLOAD:
00451         getDocument()->setHTMLEventListener(EventImpl::UNLOAD_EVENT,
00452         getDocument()->createHTMLEventListener(attr->value().string()));
00453         break;
00454     default:
00455         HTMLElementImpl::parseAttribute(attr);
00456     }
00457 }
00458 
00459 void HTMLFrameSetElementImpl::attach()
00460 {
00461     assert(!m_render);
00462     assert(parentNode());
00463     assert(parentNode()->renderer());
00464 
00465     // inherit default settings from parent frameset
00466     HTMLElementImpl* node = static_cast<HTMLElementImpl*>(parentNode());
00467     while(node)
00468     {
00469         if(node->id() == ID_FRAMESET)
00470         {
00471             HTMLFrameSetElementImpl* frameset = static_cast<HTMLFrameSetElementImpl*>(node);
00472             if(!frameBorderSet)  frameborder = frameset->frameBorder();
00473             if(!noresize)  noresize = frameset->noResize();
00474             break;
00475         }
00476         node = static_cast<HTMLElementImpl*>(node->parentNode());
00477     }
00478 
00479     // ignore display: none
00480     m_render = new RenderFrameSet(this);
00481     m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
00482     parentNode()->renderer()->addChild(m_render, nextRenderer());
00483 
00484     NodeBaseImpl::attach();
00485 }
00486 
00487 void HTMLFrameSetElementImpl::defaultEventHandler(EventImpl *evt)
00488 {
00489     if (evt->isMouseEvent() && !noresize && m_render)
00490         static_cast<khtml::RenderFrameSet *>(m_render)->userResize(static_cast<MouseEventImpl*>(evt));
00491 
00492     evt->setDefaultHandled();
00493     HTMLElementImpl::defaultEventHandler(evt);
00494 }
00495 
00496 void HTMLFrameSetElementImpl::detach()
00497 {
00498     if(attached())
00499         // ### send the event when we actually get removed from the doc instead of here
00500         getDocument()->dispatchHTMLEvent(EventImpl::UNLOAD_EVENT,false,false);
00501 
00502     HTMLElementImpl::detach();
00503 }
00504 
00505 void HTMLFrameSetElementImpl::recalcStyle( StyleChange ch )
00506 {
00507     if (changed() && m_render) {
00508         m_render->setLayouted(false);
00509 //         m_render->layout();
00510         setChanged(false);
00511     }
00512     HTMLElementImpl::recalcStyle( ch );
00513 }
00514 
00515 
00516 // -------------------------------------------------------------------------
00517 
00518 NodeImpl::Id HTMLHeadElementImpl::id() const
00519 {
00520     return ID_HEAD;
00521 }
00522 
00523 void HTMLHtmlElementImpl::attach()
00524 {
00525     assert(!m_render);
00526     assert(parentNode());
00527     assert(parentNode()->renderer());
00528 
00529     m_render = new RenderHtml(this);
00530     m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
00531     parentNode()->renderer()->addChild(m_render, nextRenderer());
00532 
00533     NodeBaseImpl::attach();
00534 }
00535 
00536 // -------------------------------------------------------------------------
00537 
00538 NodeImpl::Id HTMLHtmlElementImpl::id() const
00539 {
00540     return ID_HTML;
00541 }
00542 
00543 
00544 // -------------------------------------------------------------------------
00545 
00546 HTMLIFrameElementImpl::HTMLIFrameElementImpl(DocumentPtr *doc) : HTMLFrameElementImpl(doc)
00547 {
00548     frameBorder = false;
00549     marginWidth = 0;
00550     marginHeight = 0;
00551     needWidgetUpdate = false;
00552 }
00553 
00554 HTMLIFrameElementImpl::~HTMLIFrameElementImpl()
00555 {
00556 }
00557 
00558 NodeImpl::Id HTMLIFrameElementImpl::id() const
00559 {
00560     return ID_IFRAME;
00561 }
00562 
00563 void HTMLIFrameElementImpl::parseAttribute(AttributeImpl *attr )
00564 {
00565   switch (  attr->id() )
00566   {
00567     case ATTR_WIDTH:
00568       addCSSLength( CSS_PROP_WIDTH, attr->value());
00569       break;
00570     case ATTR_HEIGHT:
00571       addCSSLength( CSS_PROP_HEIGHT, attr->value() );
00572       break;
00573     case ATTR_SRC:
00574       needWidgetUpdate = true; // ### do this for scrolling, margins etc?
00575       HTMLFrameElementImpl::parseAttribute( attr );
00576       break;
00577     default:
00578       HTMLFrameElementImpl::parseAttribute( attr );
00579   }
00580 }
00581 
00582 void HTMLIFrameElementImpl::attach()
00583 {
00584     assert(!attached());
00585     assert(!m_render);
00586     assert(parentNode());
00587 
00588     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
00589     _style->ref();
00590     if (isURLAllowed(url.string()) &&
00591         parentNode()->renderer() && _style->display() != NONE) {
00592         m_render = new RenderPartObject(this);
00593         m_render->setStyle(_style);
00594         parentNode()->renderer()->addChild(m_render, nextRenderer());
00595     }
00596     _style->deref();
00597 
00598     NodeBaseImpl::attach();
00599 
00600     if (m_render) {
00601         // we need a unique name for every frame in the frameset. Hope that's unique enough.
00602         KHTMLView* w = getDocument()->view();
00603         if(name.isEmpty() || w->part()->frameExists( name.string() ))
00604             name = DOMString(w->part()->requestFrameName());
00605 
00606         static_cast<RenderPartObject*>(m_render)->updateWidget();
00607         needWidgetUpdate = false;
00608     }
00609 }
00610 
00611 void HTMLIFrameElementImpl::recalcStyle( StyleChange ch )
00612 {
00613     if (needWidgetUpdate) {
00614         if(m_render)  static_cast<RenderPartObject*>(m_render)->updateWidget();
00615         needWidgetUpdate = false;
00616     }
00617     HTMLElementImpl::recalcStyle( ch );
00618 }
00619 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 27 22:16:34 2005 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001