File indexing completed on 2024-05-05 16:10:13
0001 /** 0002 * This file is part of the DOM implementation for KDE. 0003 * 0004 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 0005 * (C) 1999 Antti Koivisto (koivisto@kde.org) 0006 * (C) 2000 Simon Hausmann <hausmann@kde.org> 0007 * (C) 2001-2003 Dirk Mueller (mueller@kde.org) 0008 * (C) 2002 Apple Computer, Inc. 0009 * 0010 * This library is free software; you can redistribute it and/or 0011 * modify it under the terms of the GNU Library General Public 0012 * License as published by the Free Software Foundation; either 0013 * version 2 of the License, or (at your option) any later version. 0014 * 0015 * This library is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0018 * Library General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Library General Public License 0021 * along with this library; see the file COPYING.LIB. If not, write to 0022 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0023 * Boston, MA 02110-1301, USA. 0024 */ 0025 // ------------------------------------------------------------------------- 0026 0027 #include "html/html_inlineimpl.h" 0028 #include "html/html_imageimpl.h" 0029 #include "html/html_documentimpl.h" 0030 0031 #include "khtmlview.h" 0032 #include "khtml_part.h" 0033 #include "css/cssproperties.h" 0034 #include "css/cssvalues.h" 0035 #include "css/cssstyleselector.h" 0036 #include "xml/dom2_eventsimpl.h" 0037 #include "rendering/render_br.h" 0038 #include "rendering/render_image.h" 0039 #include "rendering/render_inline.h" 0040 0041 #include <QKeyEvent> 0042 0043 using namespace khtml; 0044 using namespace DOM; 0045 0046 NodeImpl::Id HTMLAnchorElementImpl::id() const 0047 { 0048 return ID_A; 0049 } 0050 0051 void HTMLAnchorElementImpl::defaultEventHandler(EventImpl *evt) 0052 { 0053 bool keydown = evt->id() == EventImpl::KEYDOWN_EVENT && evt->isKeyRelatedEvent(); 0054 0055 // React on clicks and on keypresses. 0056 // Don't make this KEYUP_EVENT again, it makes khtml follow links 0057 // it shouldn't, when pressing Enter in the combo. 0058 if (((evt->id() == EventImpl::CLICK_EVENT && !static_cast<MouseEventImpl *>(evt)->isDoubleClick()) || 0059 (keydown && m_focused)) && m_hasAnchor) { 0060 0061 MouseEventImpl *e = nullptr; 0062 if (evt->id() == EventImpl::CLICK_EVENT) { 0063 e = static_cast<MouseEventImpl *>(evt); 0064 } 0065 0066 KeyEventBaseImpl *k = nullptr; 0067 if (keydown) { 0068 k = static_cast<KeyEventBaseImpl *>(evt); 0069 } 0070 0071 if (e && e->button() == 2) { 0072 HTMLElementImpl::defaultEventHandler(evt); 0073 return; 0074 } 0075 0076 if (k) { 0077 if (k->virtKeyVal() != KeyEventBaseImpl::DOM_VK_ENTER) { 0078 if (k->qKeyEvent()) { 0079 k->qKeyEvent()->ignore(); 0080 } 0081 HTMLElementImpl::defaultEventHandler(evt); 0082 return; 0083 } 0084 if (k->qKeyEvent()) { 0085 k->qKeyEvent()->accept(); 0086 } 0087 } 0088 0089 QString url = getAttribute(ATTR_HREF).trimSpaces().string(); 0090 QString utarget = getAttribute(ATTR_TARGET).string(); 0091 0092 if (e && e->button() == 1) { 0093 utarget = "_blank"; 0094 } 0095 0096 if (static_cast<NodeImpl *>(evt->target())->id() == ID_IMG) { 0097 HTMLImageElementImpl *img = static_cast<HTMLImageElementImpl *>(evt->target()); 0098 if (img && img->isServerMap()) { 0099 khtml::RenderImage *r = static_cast<khtml::RenderImage *>(img->renderer()); 0100 if (r && e) { 0101 KHTMLView *v = document()->view(); 0102 int x = e->clientX(); 0103 int y = e->clientY(); 0104 int absx = 0; 0105 int absy = 0; 0106 if (v) { 0107 x += v->contentsX(); 0108 y += v->contentsY(); 0109 } 0110 r->absolutePosition(absx, absy); 0111 url += QString("?%1,%2").arg(x - absx).arg(y - absy); 0112 } else { 0113 evt->setDefaultHandled(); 0114 HTMLElementImpl::defaultEventHandler(evt); 0115 return; 0116 } 0117 } 0118 } 0119 if (!evt->defaultPrevented()) { 0120 int state = 0; 0121 int button = 0; 0122 0123 if (e) { 0124 if (e->ctrlKey()) { 0125 state |= Qt::ControlModifier; 0126 } 0127 if (e->shiftKey()) { 0128 state |= Qt::ShiftModifier; 0129 } 0130 if (e->altKey()) { 0131 state |= Qt::AltModifier; 0132 } 0133 if (e->metaKey()) { 0134 state |= Qt::MetaModifier; 0135 } 0136 0137 if (e->button() == 0) { 0138 button = Qt::LeftButton; 0139 } else if (e->button() == 1) { 0140 button = Qt::MidButton; 0141 } else if (e->button() == 2) { 0142 button = Qt::RightButton; 0143 } 0144 } else if (k) { 0145 if (k->checkModifier(Qt::ShiftModifier)) { 0146 state |= Qt::ShiftModifier; 0147 } 0148 if (k->checkModifier(Qt::AltModifier)) { 0149 state |= Qt::AltModifier; 0150 } 0151 if (k->checkModifier(Qt::ControlModifier)) { 0152 state |= Qt::ControlModifier; 0153 } 0154 } 0155 0156 if (document()->part() && !isContentEditable()) { 0157 if (k) { 0158 click(); 0159 } else { 0160 KParts::OpenUrlArguments args; 0161 args.setActionRequestedByUser(true); 0162 document()->part()->urlSelected(url, button, state, utarget, args); 0163 } 0164 } 0165 } 0166 evt->setDefaultHandled(); 0167 } 0168 HTMLElementImpl::defaultEventHandler(evt); 0169 } 0170 0171 void HTMLAnchorElementImpl::click() 0172 { 0173 QMouseEvent me(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, nullptr); 0174 dispatchMouseEvent(&me, EventImpl::CLICK_EVENT, 1); 0175 } 0176 0177 void HTMLAnchorElementImpl::parseAttribute(AttributeImpl *attr) 0178 { 0179 switch (attr->id()) { 0180 case ATTR_HREF: { 0181 bool hadAnchor = m_hasAnchor; 0182 m_hasAnchor = attr->val() != nullptr; 0183 document()->incDOMTreeVersion(DocumentImpl::TV_IDNameHref); 0184 if (hadAnchor != m_hasAnchor) { 0185 setChanged(); 0186 } 0187 if (m_hasAnchor && document()->part() && document()->part()->dnsPrefetch()) { 0188 QUrl url(attr->value().string()); 0189 if (!url.host().isEmpty()) { 0190 document()->part()->mayPrefetchHostname(url.host()); 0191 } 0192 } 0193 } 0194 break; 0195 case ATTR_TARGET: 0196 m_hasTarget = attr->val() != nullptr; 0197 break; 0198 case ATTR_TITLE: 0199 case ATTR_REL: 0200 break; 0201 case ATTR_ACCESSKEY: 0202 break; 0203 default: 0204 HTMLElementImpl::parseAttribute(attr); 0205 } 0206 } 0207 0208 bool HTMLAnchorElementImpl::isFocusableImpl(FocusType ft) const 0209 { 0210 if (m_hasAnchor) { 0211 return true; 0212 } 0213 return HTMLElementImpl::isFocusableImpl(ft); 0214 } 0215 0216 // ------------------------------------------------------------------------- 0217 0218 NodeImpl::Id HTMLBRElementImpl::id() const 0219 { 0220 return ID_BR; 0221 } 0222 0223 void HTMLBRElementImpl::parseAttribute(AttributeImpl *attr) 0224 { 0225 switch (attr->id()) { 0226 case ATTR_CLEAR: { 0227 DOMString str = attr->value().lower(); 0228 if (str.isEmpty()) { 0229 str = "none"; 0230 } else if (strcmp(str, "all") == 0) { 0231 str = "both"; 0232 } 0233 addCSSProperty(CSS_PROP_CLEAR, str); 0234 break; 0235 } 0236 default: 0237 HTMLElementImpl::parseAttribute(attr); 0238 } 0239 } 0240 0241 void HTMLBRElementImpl::attach() 0242 { 0243 assert(!attached()); 0244 assert(!m_render); 0245 assert(parentNode()); 0246 0247 if (parentNode()->renderer() && parentNode()->renderer()->childAllowed()) { 0248 RenderStyle *style = document()->styleSelector()->styleForElement(this); 0249 style->ref(); 0250 if (style->display() != NONE) { 0251 m_render = new(document()->renderArena()) RenderBR(this); 0252 m_render->setStyle(style); 0253 parentNode()->renderer()->addChild(m_render, nextRenderer()); 0254 } 0255 style->deref(); 0256 } 0257 NodeImpl::attach(); 0258 } 0259 0260 // ------------------------------------------------------------------------- 0261 0262 NodeImpl::Id HTMLWBRElementImpl::id() const 0263 { 0264 return ID_WBR; 0265 } 0266 0267 void HTMLWBRElementImpl::attach() 0268 { 0269 assert(!attached()); 0270 assert(!m_render); 0271 assert(parentNode()); 0272 0273 if (parentNode()->renderer() && parentNode()->renderer()->childAllowed()) { 0274 RenderStyle *style = document()->styleSelector()->styleForElement(this); 0275 style->ref(); 0276 if (style->display() != NONE) { 0277 m_render = new(document()->renderArena()) RenderInline(this); 0278 m_render->setStyle(style); 0279 parentNode()->renderer()->addChild(m_render, nextRenderer()); 0280 } 0281 style->deref(); 0282 } 0283 NodeImpl::attach(); 0284 } 0285 0286 // ------------------------------------------------------------------------- 0287 0288 NodeImpl::Id HTMLFontElementImpl::id() const 0289 { 0290 return ID_FONT; 0291 } 0292 0293 void HTMLFontElementImpl::parseAttribute(AttributeImpl *attr) 0294 { 0295 switch (attr->id()) { 0296 case ATTR_SIZE: { 0297 DOMStringImpl *v = attr->val(); 0298 if (v) { 0299 const QChar *s = v->s; 0300 int num = v->toInt(); 0301 int len = v->l; 0302 while (len && s->isSpace()) { 0303 len--, s++; 0304 } 0305 if (len && *s == '+') { 0306 num += 3; 0307 } 0308 int size; 0309 switch (num) { 0310 case -2: 0311 case 1: size = CSS_VAL_XX_SMALL; break; 0312 case -1: 0313 case 2: size = CSS_VAL_SMALL; break; 0314 case 0: // treat 0 the same as 3, because people 0315 // expect it to be between -1 and +1 0316 case 3: size = CSS_VAL_MEDIUM; break; 0317 case 4: size = CSS_VAL_LARGE; break; 0318 case 5: size = CSS_VAL_X_LARGE; break; 0319 case 6: size = CSS_VAL_XX_LARGE; break; 0320 default: 0321 if (num > 6) { 0322 size = CSS_VAL__KHTML_XXX_LARGE; 0323 } else { 0324 size = CSS_VAL_XX_SMALL; 0325 } 0326 } 0327 addCSSProperty(CSS_PROP_FONT_SIZE, size); 0328 } 0329 break; 0330 } 0331 case ATTR_COLOR: 0332 addHTMLColor(CSS_PROP_COLOR, attr->value()); 0333 break; 0334 case ATTR_FACE: 0335 addCSSProperty(CSS_PROP_FONT_FAMILY, attr->value()); 0336 break; 0337 default: 0338 HTMLElementImpl::parseAttribute(attr); 0339 } 0340 } 0341