webengine/osswebengine/WebCore/rendering/HitTestResult.cpp
changeset 0 dd21522fd290
child 68 92a765b5b3e7
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * This file is part of the HTML rendering engine for KDE.
       
     3  *
       
     4  * Copyright (C) 2006 Apple Computer, Inc.
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Library General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Library General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Library General Public License
       
    17  * along with this library; see the file COPYING.LIB.  If not, write to
       
    18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    19  * Boston, MA 02110-1301, USA.
       
    20  *
       
    21 */
       
    22 
       
    23 #include "config.h"
       
    24 #include "HitTestResult.h"
       
    25 
       
    26 #include "CSSHelper.h"
       
    27 #include "Document.h"
       
    28 #include "Frame.h"
       
    29 #include "FrameTree.h"
       
    30 #include "HTMLAnchorElement.h"
       
    31 #include "HTMLElement.h"
       
    32 #include "HTMLImageElement.h"
       
    33 #include "HTMLInputElement.h"
       
    34 #include "HTMLNames.h"
       
    35 #include "KURL.h"
       
    36 #include "PlatformScrollBar.h"
       
    37 #include "RenderImage.h"
       
    38 #include "RenderObject.h"
       
    39 #include "SelectionController.h"
       
    40 
       
    41 #if ENABLE(SVG)
       
    42 #include "SVGNames.h"
       
    43 #include "XLinkNames.h"
       
    44 #endif
       
    45 
       
    46 namespace WebCore {
       
    47 
       
    48 using namespace HTMLNames;
       
    49 
       
    50 HitTestResult::HitTestResult(const IntPoint& point)
       
    51     : m_point(point)
       
    52 {
       
    53 }
       
    54 
       
    55 HitTestResult::HitTestResult(const HitTestResult& other)
       
    56     : m_innerNode(other.innerNode())
       
    57     , m_innerNonSharedNode(other.innerNonSharedNode())
       
    58     , m_point(other.point())
       
    59     , m_localPoint(other.localPoint())
       
    60     , m_innerURLElement(other.URLElement())
       
    61     , m_scrollbar(other.scrollbar())
       
    62 {
       
    63 }
       
    64 
       
    65 HitTestResult::~HitTestResult()
       
    66 {
       
    67 }
       
    68 
       
    69 HitTestResult& HitTestResult::operator=(const HitTestResult& other)
       
    70 {
       
    71     m_innerNode = other.innerNode();
       
    72     m_innerNonSharedNode = other.innerNonSharedNode();
       
    73     m_point = other.point();
       
    74     m_innerURLElement = other.URLElement();
       
    75     m_scrollbar = other.scrollbar();
       
    76     return *this;
       
    77 }
       
    78 
       
    79 void HitTestResult::setToNonShadowAncestor()
       
    80 {
       
    81     Node* node = innerNode();
       
    82     if (node)
       
    83         node = node->shadowAncestorNode();
       
    84     setInnerNode(node);
       
    85     node = innerNonSharedNode();
       
    86     if (node)
       
    87         node = node->shadowAncestorNode();
       
    88     setInnerNonSharedNode(node);
       
    89 }
       
    90 
       
    91 void HitTestResult::setInnerNode(Node* n)
       
    92 {
       
    93     m_innerNode = n;
       
    94 }
       
    95     
       
    96 void HitTestResult::setInnerNonSharedNode(Node* n)
       
    97 {
       
    98     m_innerNonSharedNode = n;
       
    99 }
       
   100 
       
   101 void HitTestResult::setURLElement(Element* n) 
       
   102 { 
       
   103     m_innerURLElement = n; 
       
   104 }
       
   105 
       
   106 void HitTestResult::setScrollbar(PlatformScrollbar* s)
       
   107 {
       
   108     m_scrollbar = s;
       
   109 }
       
   110 
       
   111 Frame* HitTestResult::targetFrame() const
       
   112 {
       
   113     if (!m_innerURLElement)
       
   114         return 0;
       
   115 
       
   116     Frame* frame = m_innerURLElement->document()->frame();
       
   117     if (!frame)
       
   118         return 0;
       
   119 
       
   120     return frame->tree()->find(m_innerURLElement->target());
       
   121 }
       
   122 
       
   123 IntRect HitTestResult::boundingBox() const
       
   124 {
       
   125     if (m_innerNonSharedNode) {
       
   126         RenderObject* renderer = m_innerNonSharedNode->renderer();
       
   127         if (renderer)
       
   128             return renderer->absoluteBoundingBoxRect();
       
   129     }
       
   130     
       
   131     return IntRect();
       
   132 }
       
   133 
       
   134 bool HitTestResult::isSelected() const
       
   135 {
       
   136     if (!m_innerNonSharedNode)
       
   137         return false;
       
   138 
       
   139     Frame* frame = m_innerNonSharedNode->document()->frame();
       
   140     if (!frame)
       
   141         return false;
       
   142 
       
   143     return frame->selectionController()->contains(m_point);
       
   144 }
       
   145 
       
   146 String HitTestResult::spellingToolTip() const
       
   147 {
       
   148     // Return the tool tip string associated with this point, if any. Only markers associated with bad grammar
       
   149     // currently supply strings, but maybe someday markers associated with misspelled words will also.
       
   150     if (!m_innerNonSharedNode)
       
   151         return String();
       
   152     
       
   153      DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar);
       
   154     if (!marker)
       
   155         return String();
       
   156 
       
   157     return marker->description;
       
   158 }
       
   159 
       
   160 String HitTestResult::title() const
       
   161 {
       
   162     // Find the title in the nearest enclosing DOM node.
       
   163     // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
       
   164     for (Node* titleNode = m_innerNode.get(); titleNode; titleNode = titleNode->parentNode()) {
       
   165         if (titleNode->isElementNode()) {
       
   166             String title = static_cast<Element*>(titleNode)->title();
       
   167             if (!title.isEmpty())
       
   168                 return title;
       
   169         }
       
   170     }
       
   171     return String();
       
   172 }
       
   173 
       
   174 String displayString(const String& string, const Node* node)
       
   175 {
       
   176     if (!node)
       
   177         return string;
       
   178     String copy(string);
       
   179     copy.replace('\\', node->document()->backslashAsCurrencySymbol());
       
   180     return copy;
       
   181 }
       
   182 
       
   183 String HitTestResult::altDisplayString() const
       
   184 {
       
   185     if (!m_innerNonSharedNode)
       
   186         return String();
       
   187     
       
   188     if (m_innerNonSharedNode->hasTagName(imgTag)) {
       
   189         HTMLImageElement* image = static_cast<HTMLImageElement*>(m_innerNonSharedNode.get());
       
   190         return displayString(image->alt(), m_innerNonSharedNode.get());
       
   191     }
       
   192     
       
   193     if (m_innerNonSharedNode->hasTagName(inputTag)) {
       
   194         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_innerNonSharedNode.get());
       
   195         return displayString(input->alt(), m_innerNonSharedNode.get());
       
   196     }
       
   197     
       
   198     return String();
       
   199 }
       
   200 
       
   201 Image* HitTestResult::image() const
       
   202 {
       
   203     if (!m_innerNonSharedNode)
       
   204         return 0;
       
   205     
       
   206     RenderObject* renderer = m_innerNonSharedNode->renderer();
       
   207     if (renderer && renderer->isImage()) {
       
   208         RenderImage* image = static_cast<WebCore::RenderImage*>(renderer);
       
   209         if (image->cachedImage() && !image->cachedImage()->errorOccurred())
       
   210             return image->cachedImage()->image();
       
   211     }
       
   212 
       
   213     return 0;
       
   214 }
       
   215 
       
   216 IntRect HitTestResult::imageRect() const
       
   217 {
       
   218     if (!image())
       
   219         return IntRect();
       
   220     return m_innerNonSharedNode->renderer()->absoluteContentBox();
       
   221 }
       
   222 
       
   223 KURL HitTestResult::absoluteImageURL() const
       
   224 {
       
   225     if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
       
   226         return KURL();
       
   227 
       
   228     if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isImage()))
       
   229         return KURL();
       
   230 
       
   231     AtomicString urlString;
       
   232     if (m_innerNonSharedNode->hasTagName(imgTag) || m_innerNonSharedNode->hasTagName(inputTag))
       
   233         urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(srcAttr);
       
   234 #if ENABLE(SVG)
       
   235     else if (m_innerNonSharedNode->hasTagName(SVGNames::imageTag))
       
   236         urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(XLinkNames::hrefAttr);
       
   237 #endif
       
   238     else if (m_innerNonSharedNode->hasTagName(objectTag))
       
   239         urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(dataAttr);
       
   240     else
       
   241         return KURL();
       
   242     
       
   243     return KURL(m_innerNonSharedNode->document()->completeURL(parseURL(urlString).deprecatedString()));
       
   244 }
       
   245 
       
   246 KURL HitTestResult::absoluteLinkURL() const
       
   247 {
       
   248     if (!(m_innerURLElement && m_innerURLElement->document()))
       
   249         return KURL();
       
   250 
       
   251     AtomicString urlString;
       
   252     if (m_innerURLElement->hasTagName(aTag) || m_innerURLElement->hasTagName(areaTag) || m_innerURLElement->hasTagName(linkTag))
       
   253         urlString = m_innerURLElement->getAttribute(hrefAttr);
       
   254 #if ENABLE(SVG)
       
   255     else if (m_innerURLElement->hasTagName(SVGNames::aTag))
       
   256         urlString = m_innerURLElement->getAttribute(XLinkNames::hrefAttr);
       
   257 #endif
       
   258     else
       
   259         return KURL();
       
   260 
       
   261     return KURL(m_innerURLElement->document()->completeURL(parseURL(urlString).deprecatedString()));
       
   262 }
       
   263 
       
   264 bool HitTestResult::isLiveLink() const
       
   265 {
       
   266     if (!(m_innerURLElement && m_innerURLElement->document()))
       
   267         return false;
       
   268 
       
   269     if (m_innerURLElement->hasTagName(aTag))
       
   270         return static_cast<HTMLAnchorElement*>(m_innerURLElement.get())->isLiveLink();
       
   271 #if ENABLE(SVG)
       
   272     if (m_innerURLElement->hasTagName(SVGNames::aTag))
       
   273         return m_innerURLElement->isLink();
       
   274 #endif
       
   275     
       
   276     return false;
       
   277 }
       
   278 
       
   279 String HitTestResult::titleDisplayString() const
       
   280 {
       
   281     if (!m_innerURLElement)
       
   282         return String();
       
   283     
       
   284     return displayString(m_innerURLElement->title(), m_innerURLElement.get());
       
   285 }
       
   286 
       
   287 String HitTestResult::textContent() const
       
   288 {
       
   289     if (!m_innerURLElement)
       
   290         return String();
       
   291     return m_innerURLElement->textContent();
       
   292 }
       
   293 
       
   294 // FIXME: This function needs a better name and may belong in a different class. It's not
       
   295 // really isContentEditable(); it's more like needsEditingContextMenu(). In many ways, this
       
   296 // function would make more sense in the ContextMenu class, except that WebElementDictionary 
       
   297 // hooks into it. Anyway, we should architect this better. 
       
   298 bool HitTestResult::isContentEditable() const
       
   299 {
       
   300     if (!m_innerNonSharedNode)
       
   301         return false;
       
   302 
       
   303     if (m_innerNonSharedNode->hasTagName(textareaTag) || m_innerNonSharedNode->hasTagName(isindexTag))
       
   304         return true;
       
   305 
       
   306     if (m_innerNonSharedNode->hasTagName(inputTag))
       
   307         return static_cast<HTMLInputElement*>(m_innerNonSharedNode.get())->isTextField();
       
   308 
       
   309     return m_innerNonSharedNode->isContentEditable();
       
   310 }
       
   311 
       
   312 } // namespace WebCore