1 /**
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #include "config.h"
23 #include "RenderTextControlMultiLine.h"
24
25 #include "Event.h"
26 #include "EventNames.h"
27 #include "Frame.h"
28 #include "HTMLNames.h"
29 #include "HTMLTextAreaElement.h"
30 #include "HitTestResult.h"
31 #ifdef ANDROID_LAYOUT
32 #include "Settings.h"
33 #endif
34
35 namespace WebCore {
36
RenderTextControlMultiLine(Node * node,bool placeholderVisible)37 RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node, bool placeholderVisible)
38 : RenderTextControl(node, placeholderVisible)
39 {
40 }
41
~RenderTextControlMultiLine()42 RenderTextControlMultiLine::~RenderTextControlMultiLine()
43 {
44 if (node() && node()->inDocument())
45 static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
46 }
47
subtreeHasChanged()48 void RenderTextControlMultiLine::subtreeHasChanged()
49 {
50 RenderTextControl::subtreeHasChanged();
51 HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(node());
52 textArea->setChangedSinceLastFormControlChangeEvent(true);
53 textArea->setFormControlValueMatchesRenderer(false);
54 textArea->setNeedsValidityCheck();
55
56 if (!node()->focused())
57 return;
58
59 if (Frame* frame = this->frame())
60 frame->editor()->textDidChangeInTextArea(textArea);
61 }
62
nodeAtPoint(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)63 bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
64 {
65 if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction))
66 return false;
67
68 if (result.innerNode() == node() || result.innerNode() == innerTextElement())
69 hitInnerTextElement(result, x, y, tx, ty);
70
71 return true;
72 }
73
forwardEvent(Event * event)74 void RenderTextControlMultiLine::forwardEvent(Event* event)
75 {
76 RenderTextControl::forwardEvent(event);
77 }
78
getAvgCharWidth(AtomicString family)79 float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family)
80 {
81 // Since Lucida Grande is the default font, we want this to match the width
82 // of Courier New, the default font for textareas in IE, Firefox and Safari Win.
83 // 1229 is the avgCharWidth value in the OS/2 table for Courier New.
84 if (family == AtomicString("Lucida Grande"))
85 return scaleEmToUnits(1229);
86
87 return RenderTextControl::getAvgCharWidth(family);
88 }
89
preferredContentWidth(float charWidth) const90 int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const
91 {
92 int factor = static_cast<HTMLTextAreaElement*>(node())->cols();
93 return static_cast<int>(ceilf(charWidth * factor)) + scrollbarThickness();
94 }
95
adjustControlHeightBasedOnLineHeight(int lineHeight)96 void RenderTextControlMultiLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
97 {
98 setHeight(height() + lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows());
99 }
100
baselinePosition(FontBaseline baselineType,bool firstLine,LineDirectionMode direction,LinePositionMode linePositionMode) const101 int RenderTextControlMultiLine::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
102 {
103 return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
104 }
105
updateFromElement()106 void RenderTextControlMultiLine::updateFromElement()
107 {
108 createSubtreeIfNeeded(0);
109 RenderTextControl::updateFromElement();
110
111 setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value());
112 }
113
cacheSelection(int start,int end)114 void RenderTextControlMultiLine::cacheSelection(int start, int end)
115 {
116 static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
117 }
118
createInnerTextStyle(const RenderStyle * startStyle) const119 PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
120 {
121 RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
122 textBlockStyle->inheritFrom(startStyle);
123 adjustInnerTextStyle(startStyle, textBlockStyle.get());
124 textBlockStyle->setDisplay(BLOCK);
125
126 return textBlockStyle.release();
127 }
128
textBaseStyle() const129 RenderStyle* RenderTextControlMultiLine::textBaseStyle() const
130 {
131 return style();
132 }
133
textBlockInsetLeft() const134 int RenderTextControlMultiLine::textBlockInsetLeft() const
135 {
136 int inset = borderLeft() + paddingLeft();
137 if (HTMLElement* innerText = innerTextElement()) {
138 if (RenderBox* innerTextRenderer = innerText->renderBox())
139 inset += innerTextRenderer->paddingLeft();
140 }
141 return inset;
142 }
143
textBlockInsetRight() const144 int RenderTextControlMultiLine::textBlockInsetRight() const
145 {
146 int inset = borderRight() + paddingRight();
147 if (HTMLElement* innerText = innerTextElement()) {
148 if (RenderBox* innerTextRenderer = innerText->renderBox())
149 inset += innerTextRenderer->paddingRight();
150 }
151 return inset;
152 }
153
textBlockInsetTop() const154 int RenderTextControlMultiLine::textBlockInsetTop() const
155 {
156 int inset = borderTop() + paddingTop();
157 if (HTMLElement* innerText = innerTextElement()) {
158 if (RenderBox* innerTextRenderer = innerText->renderBox())
159 inset += innerTextRenderer->paddingTop();
160 }
161 return inset;
162 }
163
164 }
165