00001
00024
00025
00026
00027
00028
00029
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
00076 case ATTR_ID:
00077
00078 setHasID();
00079 setChanged();
00080 break;
00081 case ATTR_CLASS:
00082 case ATTR_NAME:
00083 setChanged();
00084 break;
00085 case ATTR_STYLE:
00086
00087
00088
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
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
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
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 )
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
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
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
00256 if( endTag[id()] == FORBIDDEN )
00257 return false;
00258
00259
00260
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
00298 if( endTag[id()] == FORBIDDEN )
00299 return false;
00300
00301
00302
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
00332
00333 if (getDocument()->isHTMLDocument())
00334 return DOMString();
00335 else
00336 return XHTML_NAMESPACE;
00337 }
00338
00339 void HTMLElementImpl::addHTMLAlignment( DOMString alignment )
00340 {
00341
00342
00343
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
00382 if (!w || w->part()->onlyLocalReferences() && newURL.protocol() != "file")
00383 return false;
00384
00385
00386 if ( !kapp || !kapp->kapp->authorizeURLAction("redirect", w->part()->url(), newURL) )
00387 return false;
00388
00389
00390
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