khtml Library API Documentation

html_elementimpl.cpp

00001 
00024 // -------------------------------------------------------------------------
00025 //#define DEBUG
00026 //#define DEBUG_LAYOUT
00027 //#define PAR_DEBUG
00028 //#define EVENT_DEBUG
00029 //#define UNSUPPORTED_ATTR
00030 
00031 #include "html/dtd.h"
00032 #include "html/html_elementimpl.h"
00033 #include "html/html_documentimpl.h"
00034 #include "html/htmltokenizer.h"
00035 
00036 #include "misc/htmlhashes.h"
00037 
00038 #include "khtmlview.h"
00039 #include "khtml_part.h"
00040 
00041 #include "rendering/render_object.h"
00042 #include "rendering/render_replaced.h"
00043 #include "css/css_valueimpl.h"
00044 #include "css/css_stylesheetimpl.h"
00045 #include "css/cssproperties.h"
00046 #include "css/cssvalues.h"
00047 #include "xml/dom_textimpl.h"
00048 #include "xml/dom2_eventsimpl.h"
00049 
00050 #include <kapplication.h>
00051 #include <kdebug.h>
00052 
00053 using namespace DOM;
00054 using namespace khtml;
00055 
00056 HTMLElementImpl::~HTMLElementImpl()
00057 {
00058 }
00059 
00060 void HTMLElementImpl::parseAttribute(AttributeImpl *attr)
00061 {
00062     DOMString indexstring;
00063     switch( attr->id() )
00064     {
00065     case ATTR_ALIGN:
00066         if (attr->val()) {
00067             if ( strcasecmp(attr->value(), "middle" ) == 0 )
00068                 addCSSProperty( CSS_PROP_TEXT_ALIGN, "center" );
00069             else
00070                 addCSSProperty(CSS_PROP_TEXT_ALIGN, attr->value());
00071         }
00072         else
00073             removeCSSProperty(CSS_PROP_TEXT_ALIGN);
00074         break;
00075 // the core attributes...
00076     case ATTR_ID:
00077         // unique id
00078         setHasID();
00079         setChanged(); // in case of a CSS selector on id
00080         break;
00081     case ATTR_CLASS:
00082     case ATTR_NAME:
00083         setChanged(); // in case of a CSS selector on class/name
00084         break;
00085     case ATTR_STYLE:
00086         // ### we need to remove old style info in case there was any!
00087         // ### the inline sheet ay contain more than 1 property!
00088         // stylesheet info
00089         setHasStyle();
00090         if(!m_styleDecls) createDecl();
00091         m_styleDecls->setProperty(attr->value());
00092         setChanged();
00093         break;
00094     case ATTR_TABINDEX:
00095         indexstring=getAttribute(ATTR_TABINDEX);
00096         if (indexstring.length())
00097             setTabIndex(indexstring.toInt());
00098         break;
00099 // i18n attributes
00100     case ATTR_LANG:
00101         break;
00102     case ATTR_DIR:
00103         addCSSProperty(CSS_PROP_DIRECTION, attr->value());
00104         addCSSProperty(CSS_PROP_UNICODE_BIDI, CSS_VAL_EMBED);
00105         break;
00106 // standard events
00107     case ATTR_ONCLICK:
00108     setHTMLEventListener(EventImpl::KHTML_ECMA_CLICK_EVENT,
00109         getDocument()->createHTMLEventListener(attr->value().string()));
00110         break;
00111     case ATTR_ONDBLCLICK:
00112     setHTMLEventListener(EventImpl::KHTML_ECMA_DBLCLICK_EVENT,
00113         getDocument()->createHTMLEventListener(attr->value().string()));
00114         break;
00115     case ATTR_ONMOUSEDOWN:
00116         setHTMLEventListener(EventImpl::MOUSEDOWN_EVENT,
00117         getDocument()->createHTMLEventListener(attr->value().string()));
00118         break;
00119     case ATTR_ONMOUSEMOVE:
00120         setHTMLEventListener(EventImpl::MOUSEMOVE_EVENT,
00121         getDocument()->createHTMLEventListener(attr->value().string()));
00122         break;
00123     case ATTR_ONMOUSEOUT:
00124         setHTMLEventListener(EventImpl::MOUSEOUT_EVENT,
00125         getDocument()->createHTMLEventListener(attr->value().string()));
00126         break;
00127     case ATTR_ONMOUSEOVER:
00128         setHTMLEventListener(EventImpl::MOUSEOVER_EVENT,
00129         getDocument()->createHTMLEventListener(attr->value().string()));
00130         break;
00131     case ATTR_ONMOUSEUP:
00132         setHTMLEventListener(EventImpl::MOUSEUP_EVENT,
00133         getDocument()->createHTMLEventListener(attr->value().string()));
00134         break;
00135     case ATTR_ONFOCUS:
00136         setHTMLEventListener(EventImpl::DOMFOCUSIN_EVENT,
00137         getDocument()->createHTMLEventListener(attr->value().string()));
00138         break;
00139     case ATTR_ONKEYDOWN:
00140         setHTMLEventListener(EventImpl::KHTML_KEYDOWN_EVENT,
00141         getDocument()->createHTMLEventListener(attr->value().string()));
00142     break;
00143     case ATTR_ONKEYPRESS:
00144         setHTMLEventListener(EventImpl::KHTML_KEYPRESS_EVENT,
00145         getDocument()->createHTMLEventListener(attr->value().string()));
00146     break;
00147     case ATTR_ONKEYUP:
00148         setHTMLEventListener(EventImpl::KHTML_KEYUP_EVENT,
00149         getDocument()->createHTMLEventListener(attr->value().string()));
00150         break;
00151 // other misc attributes
00152     default:
00153 #ifdef UNSUPPORTED_ATTR
00154     kdDebug(6030) << "UATTR: <" << this->nodeName().string() << "> ["
00155               << attr->name().string() << "]=[" << attr->value().string() << "]" << endl;
00156 #endif
00157         break;
00158     }
00159 }
00160 
00161 void HTMLElementImpl::recalcStyle( StyleChange ch )
00162 {
00163     ElementImpl::recalcStyle( ch );
00164 
00165     if (m_render /*&& changed*/)
00166         m_render->updateFromElement();
00167 }
00168 
00169 void HTMLElementImpl::addCSSProperty(int id, const DOMString &value)
00170 {
00171     if(!m_styleDecls) createDecl();
00172     m_styleDecls->setProperty(id, value, false, true);
00173     setChanged();
00174 }
00175 
00176 void HTMLElementImpl::addCSSProperty(int id, int value)
00177 {
00178     if(!m_styleDecls) createDecl();
00179     m_styleDecls->setProperty(id, value, false, true);
00180     setChanged();
00181 }
00182 
00183 void HTMLElementImpl::addCSSLength(int id, const DOMString &value, bool numOnly, bool multiLength)
00184 {
00185     if(!m_styleDecls) createDecl();
00186 
00187     // strip attribute garbage..
00188     DOMStringImpl* v = value.implementation();
00189     if ( v ) {
00190         unsigned int l = 0;
00191 
00192         while ( l < v->l && v->s[l].unicode() <= ' ') l++;
00193 
00194         for ( ;l < v->l; l++ ) {
00195             char cc = v->s[l].latin1();
00196             if ( cc > '9' || ( cc < '0' && ( numOnly || (cc != '%' && cc != '.' &&
00197                              !( multiLength && cc == '*') ) ) ) )
00198                 break;
00199         }
00200         if ( l != v->l ) {
00201             m_styleDecls->setLengthProperty( id, DOMString( v->s, l ), false, true, multiLength );
00202             setChanged();
00203             return;
00204         }
00205     }
00206 
00207     m_styleDecls->setLengthProperty(id, value, false, true, multiLength);
00208     setChanged();
00209 }
00210 
00211 void HTMLElementImpl::removeCSSProperty(int id)
00212 {
00213     if(!m_styleDecls)
00214         return;
00215     m_styleDecls->setParent(getDocument()->elementSheet());
00216     m_styleDecls->removeProperty(id);
00217     setChanged();
00218 }
00219 
00220 DOMString HTMLElementImpl::innerHTML() const
00221 {
00222     return toHTML();
00223 }
00224 
00225 DOMString HTMLElementImpl::innerText() const
00226 {
00227     DOMString text;
00228 
00229     const NodeImpl *n = this;
00230     // find the next text/image after the anchor, to get a position
00231     while(n) {
00232         if(n->firstChild())
00233             n = n->firstChild();
00234         else if(n->nextSibling())
00235             n = n->nextSibling();
00236         else {
00237             NodeImpl *next = 0;
00238             while(!next) {
00239                 n = n->parentNode();
00240                 if(!n || n == (NodeImpl *)this ) goto end;
00241                 next = n->nextSibling();
00242             }
00243             n = next;
00244         }
00245         if(n->isTextNode() ) {
00246             text += static_cast<const TextImpl *>(n)->data();
00247         }
00248     }
00249  end:
00250     return text;
00251 }
00252 
00253 bool HTMLElementImpl::setInnerHTML( const DOMString &html )
00254 {
00255     // the following is in accordance with the definition as used by IE
00256     if( endTag[id()] == FORBIDDEN )
00257         return false;
00258     // IE disallows innerHTML on inline elements. I don't see why we should have this restriction, as our
00259     // dhtml engine can cope with it. Lars
00260     //if ( isInline() ) return false;
00261     switch( id() ) {
00262         case ID_COL:
00263         case ID_COLGROUP:
00264         case ID_FRAMESET:
00265         case ID_HEAD:
00266         case ID_HTML:
00267         case ID_STYLE:
00268         case ID_TABLE:
00269         case ID_TBODY:
00270         case ID_TFOOT:
00271         case ID_THEAD:
00272         case ID_TITLE:
00273         case ID_TR:
00274             return false;
00275         default:
00276             break;
00277     }
00278     if ( !getDocument()->isHTMLDocument() )
00279         return false;
00280 
00281     DocumentFragmentImpl *fragment = new DocumentFragmentImpl( docPtr() );
00282     HTMLTokenizer *tok = new HTMLTokenizer( docPtr(), fragment );
00283     tok->begin();
00284     tok->write( html.string(), true );
00285     tok->end();
00286     delete tok;
00287 
00288     removeChildren();
00289     int ec = 0;
00290     appendChild( fragment, ec );
00291     delete fragment;
00292     return !ec;
00293 }
00294 
00295 bool HTMLElementImpl::setInnerText( const DOMString &text )
00296 {
00297     // following the IE specs.
00298     if( endTag[id()] == FORBIDDEN )
00299         return false;
00300     // IE disallows innerHTML on inline elements. I don't see why we should have this restriction, as our
00301     // dhtml engine can cope with it. Lars
00302     //if ( isInline() ) return false;
00303     switch( id() ) {
00304         case ID_COL:
00305         case ID_COLGROUP:
00306         case ID_FRAMESET:
00307         case ID_HEAD:
00308         case ID_HTML:
00309         case ID_TABLE:
00310         case ID_TBODY:
00311         case ID_TFOOT:
00312         case ID_THEAD:
00313         case ID_TR:
00314             return false;
00315         default:
00316             break;
00317     }
00318 
00319     removeChildren();
00320 
00321     TextImpl *t = new TextImpl( docPtr(), text.implementation() );
00322     int ec = 0;
00323     appendChild( t, ec );
00324     if ( !ec )
00325         return true;
00326     return false;
00327 }
00328 
00329 DOMString HTMLElementImpl::namespaceURI() const
00330 {
00331     // For HTML documents, we treat HTML elements as having no namespace. But for XML documents
00332     // the elements have the namespace defined in the XHTML spec
00333     if (getDocument()->isHTMLDocument())
00334         return DOMString();
00335     else
00336         return XHTML_NAMESPACE;
00337 }
00338 
00339 void HTMLElementImpl::addHTMLAlignment( DOMString alignment )
00340 {
00341     //qDebug("alignment is %s", alignment.string().latin1() );
00342     // vertical alignment with respect to the current baseline of the text
00343     // right or left means floating images
00344     int propfloat = -1;
00345     int propvalign = -1;
00346     if ( strcasecmp( alignment, "absmiddle" ) == 0 ) {
00347         propvalign = CSS_VAL_MIDDLE;
00348     } else if ( strcasecmp( alignment, "absbottom" ) == 0 ) {
00349         propvalign = CSS_VAL_BOTTOM;
00350     } else if ( strcasecmp( alignment, "left" ) == 0 ) {
00351     propfloat = CSS_VAL_LEFT;
00352     propvalign = CSS_VAL_TOP;
00353     } else if ( strcasecmp( alignment, "right" ) == 0 ) {
00354     propfloat = CSS_VAL_RIGHT;
00355     propvalign = CSS_VAL_TOP;
00356     } else if ( strcasecmp( alignment, "top" ) == 0 ) {
00357     propvalign = CSS_VAL_TOP;
00358     } else if ( strcasecmp( alignment, "middle" ) == 0 ) {
00359     propvalign = CSS_VAL__KONQ_BASELINE_MIDDLE;
00360     } else if ( strcasecmp( alignment, "center" ) == 0 ) {
00361     propvalign = CSS_VAL_MIDDLE;
00362     } else if ( strcasecmp( alignment, "bottom" ) == 0 ) {
00363     propvalign = CSS_VAL_BASELINE;
00364     } else if ( strcasecmp ( alignment, "texttop") == 0 ) {
00365     propvalign = CSS_VAL_TEXT_TOP;
00366     }
00367 
00368     if ( propfloat != -1 )
00369     addCSSProperty( CSS_PROP_FLOAT, propfloat );
00370     if ( propvalign != -1 )
00371     addCSSProperty( CSS_PROP_VERTICAL_ALIGN, propvalign );
00372 }
00373 
00374 bool HTMLElementImpl::isURLAllowed(const QString& url) const
00375 {
00376     KHTMLView *w = getDocument()->view();
00377 
00378     KURL newURL(getDocument()->completeURL(url));
00379     newURL.setRef(QString::null);
00380 
00381     // Prohibit non-file URLs if we are asked to.
00382     if (!w || w->part()->onlyLocalReferences() && newURL.protocol() != "file")
00383         return false;
00384 
00385     // do we allow this suburl ?
00386     if ( !kapp || !kapp->kapp->authorizeURLAction("redirect", w->part()->url(), newURL) )
00387         return false;
00388 
00389     // We allow one level of self-reference because some sites depend on that.
00390     // But we don't allow more than one.
00391     bool foundSelfReference = false;
00392     for (KHTMLPart *part = w->part(); part; part = part->parentPart()) {
00393         KURL partURL = part->url();
00394         partURL.setRef(QString::null);
00395         if (partURL == newURL) {
00396             if (foundSelfReference)
00397                 return false;
00398             foundSelfReference = true;
00399         }
00400     }
00401 
00402     return true;
00403 }
00404 
00405 
00406 
00407 // -------------------------------------------------------------------------
00408 HTMLGenericElementImpl::HTMLGenericElementImpl(DocumentPtr *doc, ushort i)
00409     : HTMLElementImpl(doc)
00410 {
00411     _id = i;
00412 }
00413 
00414 HTMLGenericElementImpl::~HTMLGenericElementImpl()
00415 {
00416 }
00417 
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:22:36 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001