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