2006-10-31 Mitz Pettel <mitz@webkit.org>
[WebKit-https.git] / WebCore / rendering / HitTestResult.cpp
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., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, 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 "HTMLElement.h"
31 #include "HTMLImageElement.h"
32 #include "HTMLInputElement.h"
33 #include "HTMLNames.h"
34 #include "KURL.h"
35 #include "PlatformScrollBar.h"
36 #include "RenderObject.h"
37 #include "RenderImage.h"
38 #include "SelectionController.h"
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
44 HitTestResult::HitTestResult(const IntPoint& point)
45     : m_point(point)
46 {
47 }
48
49 HitTestResult::HitTestResult(const HitTestResult& other)
50     : m_innerNode(other.innerNode())
51     , m_innerNonSharedNode(other.innerNonSharedNode())
52     , m_point(other.point())
53     , m_innerURLElement(other.URLElement())
54     , m_scrollbar(other.scrollbar())
55 {
56 }
57
58 HitTestResult::~HitTestResult()
59 {
60 }
61
62 HitTestResult& HitTestResult::operator=(const HitTestResult& other)
63 {
64     m_innerNode = other.innerNode();
65     m_innerNonSharedNode = other.innerNonSharedNode();
66     m_point = other.point();
67     m_innerURLElement = other.URLElement();
68     m_scrollbar = other.scrollbar();
69     return *this;
70 }
71
72 void HitTestResult::setInnerNode(Node* n)
73 {
74     m_innerNode = n;
75 }
76     
77 void HitTestResult::setInnerNonSharedNode(Node* n)
78 {
79     m_innerNonSharedNode = n;
80 }
81
82 void HitTestResult::setURLElement(Element* n) 
83
84     m_innerURLElement = n; 
85 }
86
87 void HitTestResult::setScrollbar(PlatformScrollbar* s)
88 {
89     m_scrollbar = s;
90 }
91
92 Frame* HitTestResult::targetFrame() const
93 {
94     if (!m_innerURLElement)
95         return 0;
96
97     Frame* frame = m_innerURLElement->document()->frame();
98     if (!frame)
99         return 0;
100
101     return frame->tree()->find(m_innerURLElement->target());
102 }
103
104 IntRect HitTestResult::boundingBox() const
105 {
106     if (m_innerNonSharedNode) {
107         RenderObject* renderer = m_innerNonSharedNode->renderer();
108         if (renderer)
109             return renderer->absoluteBoundingBoxRect();
110     }
111     
112     return IntRect();
113 }
114
115 bool HitTestResult::isSelected() const
116 {
117     if (!m_innerNonSharedNode)
118         return false;
119
120     Frame* frame = m_innerNonSharedNode->document()->frame();
121     if (!frame)
122         return false;
123
124     return frame->selectionController()->contains(m_point);
125 }
126
127 String HitTestResult::spellingToolTip() const
128 {
129     // Return the tool tip string associated with this point, if any. Only markers associated with bad grammar
130     // currently supply strings, but maybe someday markers associated with misspelled words will also.
131     DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar);
132     if (marker)
133         return marker->description;
134     
135     return String();
136 }
137
138 String HitTestResult::title() const
139 {
140     // Find the title in the nearest enclosing DOM node.
141     // For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
142     for (Node* titleNode = m_innerNode.get(); titleNode; titleNode = titleNode->parentNode()) {
143         if (titleNode->isHTMLElement()) {
144             HTMLElement* titleHTMLNode = static_cast<HTMLElement*>(titleNode);
145             String title = titleHTMLNode->title();
146             if (!title.isEmpty())
147                 return title;
148         }
149     }
150     return String();
151 }
152
153 static String displayString(const String& string, const Node* node)
154 {
155     if (!node)
156         return string;
157     Document* document = node->document();
158     if (!document)
159         return string;
160     String copy(string);
161     copy.replace('\\', document->backslashAsCurrencySymbol());
162     return copy;
163 }
164
165 String HitTestResult::altDisplayString() const
166 {
167     if (!m_innerNonSharedNode)
168         return String();
169     
170     if (m_innerNonSharedNode->hasTagName(imgTag)) {
171         HTMLImageElement* image = static_cast<HTMLImageElement*>(m_innerNonSharedNode.get());
172         return displayString(image->alt(), m_innerNonSharedNode.get());
173     }
174     
175     if (m_innerNonSharedNode->hasTagName(inputTag)) {
176         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_innerNonSharedNode.get());
177         return displayString(input->alt(), m_innerNonSharedNode.get());
178     }
179     
180     return String();
181 }
182
183 Image* HitTestResult::image() const
184 {
185     if (!m_innerNonSharedNode)
186         return 0;
187     
188     RenderObject* renderer = m_innerNonSharedNode->renderer();
189     if (renderer && renderer->isImage()) {
190         RenderImage* image = static_cast<WebCore::RenderImage*>(renderer);
191         if (image->cachedImage() && !image->cachedImage()->isErrorImage())
192             return image->cachedImage()->image();
193     }
194
195     return 0;
196 }
197
198 KURL HitTestResult::absoluteImageURL() const
199 {
200     if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
201         return KURL();
202
203     if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isImage()))
204         return KURL();
205
206     String name;
207     if (m_innerNonSharedNode->hasTagName(imgTag) || m_innerNonSharedNode->hasTagName(inputTag))
208         name = "src";
209     else if (m_innerNonSharedNode->hasTagName(objectTag))
210         name = "data";
211     else
212         return KURL();
213     
214     return KURL(m_innerNonSharedNode->document()->completeURL(parseURL(
215         static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(name)).deprecatedString()));
216 }
217
218 KURL HitTestResult::absoluteLinkURL() const
219 {
220     if (!(m_innerURLElement && m_innerURLElement->document()))
221         return KURL();
222
223     if (!(m_innerURLElement->hasTagName(aTag) || m_innerURLElement->hasTagName(areaTag)
224             || m_innerURLElement->hasTagName(linkTag)))
225         return KURL();
226
227     return KURL(m_innerURLElement->document()->completeURL(parseURL(
228         static_cast<Element*>(m_innerURLElement.get())->getAttribute("href")).deprecatedString()));
229 }
230
231 String HitTestResult::titleDisplayString() const
232 {
233     if (!(m_innerURLElement && m_innerURLElement->isHTMLElement()))
234         return String();
235
236     HTMLElement* element = static_cast<HTMLElement*>(m_innerURLElement.get());
237     return displayString(element->title(), element);
238 }
239
240 String HitTestResult::textContent() const
241 {
242     if (!m_innerURLElement)
243         return String();
244     return m_innerURLElement->textContent();
245 }
246
247 } // namespace WebCore