2011-05-18 Emil A Eklund <eae@chromium.org>
[WebKit-https.git] / Source / WebCore / rendering / RenderTextControlSingleLine.cpp
1 /**
2  * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
3  *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
4  * Copyright (C) 2010 Google Inc. All rights reserved.
5  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "RenderTextControlSingleLine.h"
26
27 #include "CSSFontSelector.h"
28 #include "CSSStyleSelector.h"
29 #include "Chrome.h"
30 #include "Event.h"
31 #include "EventNames.h"
32 #include "Frame.h"
33 #include "FrameSelection.h"
34 #include "FrameView.h"
35 #include "HTMLInputElement.h"
36 #include "HTMLNames.h"
37 #include "HitTestResult.h"
38 #include "LocalizedStrings.h"
39 #include "MouseEvent.h"
40 #include "Page.h"
41 #include "PlatformKeyboardEvent.h"
42 #include "RenderLayer.h"
43 #include "RenderScrollbar.h"
44 #include "RenderTheme.h"
45 #include "Settings.h"
46 #include "SimpleFontData.h"
47 #include "TextControlInnerElements.h"
48
49 using namespace std;
50
51 namespace WebCore {
52
53 using namespace HTMLNames;
54
55 VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& point)
56 {
57     IntPoint contentsPoint(point);
58
59     // Multiline text controls have the scroll on shadowAncestorNode, so we need to take that
60     // into account here.
61     if (m_multiLine) {
62         RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer());
63         if (renderer->hasOverflowClip())
64             contentsPoint += renderer->layer()->scrolledContentOffset();
65     }
66
67     return RenderBlock::positionForPoint(contentsPoint);
68 }
69
70 // ----------------------------
71
72 RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node, bool placeholderVisible)
73     : RenderTextControl(node, placeholderVisible)
74     , m_searchPopupIsVisible(false)
75     , m_shouldDrawCapsLockIndicator(false)
76     , m_searchEventTimer(this, &RenderTextControlSingleLine::searchEventTimerFired)
77     , m_searchPopup(0)
78 {
79     ASSERT(node->isHTMLElement());
80     ASSERT(node->toInputElement());
81 }
82
83 RenderTextControlSingleLine::~RenderTextControlSingleLine()
84 {
85     if (m_searchPopup) {
86         m_searchPopup->popupMenu()->disconnectClient();
87         m_searchPopup = 0;
88     }
89  
90     if (m_innerBlock) {
91         m_innerBlock->detach();
92         m_innerBlock = 0;
93     }
94
95     if (m_innerSpinButton)
96         m_innerSpinButton->detach();
97     if (m_outerSpinButton)
98         m_outerSpinButton->detach();
99 #if ENABLE(INPUT_SPEECH)
100     if (m_speechButton)
101         m_speechButton->detach();
102 #endif
103 }
104
105 RenderStyle* RenderTextControlSingleLine::textBaseStyle() const
106 {
107     return m_innerBlock ? m_innerBlock->renderer()->style() : style();
108 }
109
110 void RenderTextControlSingleLine::addSearchResult()
111 {
112     HTMLInputElement* input = inputElement();
113     if (input->maxResults() <= 0)
114         return;
115
116     String value = input->value();
117     if (value.isEmpty())
118         return;
119
120     Settings* settings = document()->settings();
121     if (!settings || settings->privateBrowsingEnabled())
122         return;
123
124     int size = static_cast<int>(m_recentSearches.size());
125     for (int i = size - 1; i >= 0; --i) {
126         if (m_recentSearches[i] == value)
127             m_recentSearches.remove(i);
128     }
129
130     m_recentSearches.insert(0, value);
131     while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
132         m_recentSearches.removeLast();
133
134     const AtomicString& name = autosaveName();
135     if (!m_searchPopup)
136         m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
137
138     m_searchPopup->saveRecentSearches(name, m_recentSearches);
139 }
140
141 void RenderTextControlSingleLine::stopSearchEventTimer()
142 {
143     m_searchEventTimer.stop();
144 }
145
146 void RenderTextControlSingleLine::showPopup()
147 {
148     if (m_searchPopupIsVisible)
149         return;
150
151     if (!m_searchPopup)
152         m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
153
154     if (!m_searchPopup->enabled())
155         return;
156
157     m_searchPopupIsVisible = true;
158
159     const AtomicString& name = autosaveName();
160     m_searchPopup->loadRecentSearches(name, m_recentSearches);
161
162     // Trim the recent searches list if the maximum size has changed since we last saved.
163     HTMLInputElement* input = inputElement();
164     if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
165         do {
166             m_recentSearches.removeLast();
167         } while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
168
169         m_searchPopup->saveRecentSearches(name, m_recentSearches);
170     }
171
172     m_searchPopup->popupMenu()->show(absoluteBoundingBoxRect(true), document()->view(), -1);
173 }
174
175 void RenderTextControlSingleLine::hidePopup()
176 {
177     if (m_searchPopup)
178         m_searchPopup->popupMenu()->hide();
179 }
180
181 void RenderTextControlSingleLine::subtreeHasChanged()
182 {
183     RenderTextControl::subtreeHasChanged();
184
185     ASSERT(node()->isElementNode());
186     Element* element = static_cast<Element*>(node());
187     bool wasChanged = element->wasChangedSinceLastFormControlChangeEvent();
188     element->setChangedSinceLastFormControlChangeEvent(true);
189
190     HTMLInputElement* input = inputElement();
191     // We don't need to call sanitizeUserInputValue() function here because
192     // HTMLInputElement::handleBeforeTextInsertedEvent() has already called
193     // sanitizeUserInputValue().
194     // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
195     String value = text();
196     if (input->isAcceptableValue(value))
197         input->setValueFromRenderer(input->sanitizeValue(input->convertFromVisibleValue(value)));
198     // Recalc for :invalid and hasUnacceptableValue() change.
199     input->setNeedsStyleRecalc();
200
201     if (m_cancelButton)
202         updateCancelButtonVisibility();
203
204     // If the incremental attribute is set, then dispatch the search event
205     if (input->searchEventsShouldBeDispatched())
206         startSearchEventTimer();
207
208     if (!wasChanged && node()->focused()) {
209         if (Frame* frame = this->frame())
210             frame->editor()->textFieldDidBeginEditing(static_cast<Element*>(node()));
211     }
212
213     if (node()->focused()) {
214         if (Frame* frame = document()->frame())
215             frame->editor()->textDidChangeInTextField(static_cast<Element*>(node()));
216     }
217 }
218
219 void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty)
220 {
221     RenderTextControl::paint(paintInfo, tx, ty);
222
223     if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
224         IntRect contentsRect = contentBoxRect();
225
226         // Center vertically like the text.
227         contentsRect.setY((height() - contentsRect.height()) / 2);
228
229         // Convert the rect into the coords used for painting the content
230         contentsRect.move(tx + x(), ty + y());
231         theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);
232     }
233 }
234
235 void RenderTextControlSingleLine::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
236 {
237     paintBoxDecorationsWithSize(paintInfo, IntRect(tx, ty, width() - decorationWidthRight(), height()));
238 }
239
240 void RenderTextControlSingleLine::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
241 {
242     int w = width() - decorationWidthRight();
243     if (w && height())
244         rects.append(IntRect(tx, ty, w, height()));
245 }
246
247 void RenderTextControlSingleLine::layout()
248 {
249     int oldHeight = height();
250     computeLogicalHeight();
251
252     int oldWidth = width();
253     computeLogicalWidth();
254
255     bool relayoutChildren = oldHeight != height() || oldWidth != width();
256
257     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
258     RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0;
259
260     // Set the text block height
261     int desiredHeight = textBlockHeight();
262     int currentHeight = innerTextRenderer->height();
263
264     if (currentHeight > height()) {
265         if (desiredHeight != currentHeight)
266             relayoutChildren = true;
267         innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
268         if (m_innerBlock)
269             innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
270     }
271
272     // Set the text block width
273     int desiredWidth = textBlockWidth();
274     if (desiredWidth != innerTextRenderer->width())
275         relayoutChildren = true;
276     innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));
277
278     if (m_innerBlock) {
279         int innerBlockWidth = width() - borderAndPaddingWidth();
280         if (innerBlockWidth != innerBlockRenderer->width())
281             relayoutChildren = true;
282         innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));
283     }
284
285     RenderBlock::layoutBlock(relayoutChildren);
286
287     // Center the child block vertically
288     RenderBox* childBlock = innerBlockRenderer ? innerBlockRenderer : innerTextRenderer;
289     currentHeight = childBlock->height();
290     if (currentHeight < height())
291         childBlock->setY((height() - currentHeight) / 2);
292
293     // Ignores the paddings for the inner spin button.
294     if (RenderBox* spinBox = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
295         spinBox->setLocation(IntPoint(spinBox->x() + paddingRight(), borderTop()));
296         spinBox->setHeight(height() - borderTop() - borderBottom());
297     }
298
299 #if ENABLE(INPUT_SPEECH)
300     if (RenderBox* button = m_speechButton ? m_speechButton->renderBox() : 0) {
301         if (m_innerBlock) {
302             // This is mostly the case where this is a search field. The speech button is a sibling
303             // of the inner block and laid out at the far right.
304             int x = width() - borderAndPaddingWidth() - button->width() - button->borderAndPaddingWidth();
305             int y = (height() - button->height()) / 2;
306             button->setLocation(IntPoint(x, y));
307         } else {
308             int x = width() - borderRight() - paddingRight() - button->width();
309             if (m_outerSpinButton && m_outerSpinButton->renderBox())
310                 x -= m_outerSpinButton->renderBox()->width();
311
312             RenderBox* spinBox = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0;
313             if (style()->isLeftToRightDirection())
314                 x -= spinBox ? spinBox->width() : 0;
315             else
316                 innerTextRenderer->setX(paddingLeft() + borderLeft() + (spinBox ? spinBox->width() : 0));
317             int y = (height() - button->height()) / 2;
318             button->setLocation(IntPoint(x, y));
319         }
320     }
321 #endif
322
323     // Center the spin button vertically, and move it to the right by
324     // padding + border of the text fields.
325     if (RenderBox* spinBox = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
326         int diff = height() - spinBox->height();
327         // If the diff is odd, the top area over the spin button takes the
328         // remaining one pixel. It's good for Mac NSStepper because it has
329         // shadow at the bottom.
330         int y = (diff / 2) + (diff % 2);
331         int x = width() - borderRight() - paddingRight() - spinBox->width();
332         spinBox->setLocation(IntPoint(x, y));
333     }
334 }
335
336 bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const IntPoint& pointInContainer, int tx, int ty, HitTestAction hitTestAction)
337 {
338     // If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
339     // was on the control but not on the inner element (see Radar 4617841).
340
341     // In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
342     // and act as if we've hit the close block if we're to the right of the inner text block.
343
344     if (!RenderTextControl::nodeAtPoint(request, result, pointInContainer, tx, ty, hitTestAction))
345         return false;
346
347     // If we hit a node inside the inner text element, say that we hit that element,
348     // and if we hit our node (e.g. we're over the border or padding), also say that we hit the
349     // inner text element so that it gains focus.
350     if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node())
351         hitInnerTextElement(result, pointInContainer, tx, ty);
352
353     // If we found a spin button, we're done.
354     if (m_innerSpinButton && result.innerNode() == m_innerSpinButton)
355         return true;
356     if (m_outerSpinButton && result.innerNode() == m_outerSpinButton)
357         return true;
358 #if ENABLE(INPUT_SPEECH)
359     if (m_speechButton && result.innerNode() == m_speechButton)
360         return true;
361 #endif
362     // If we're not a search field, or we already found the speech, results or cancel buttons, we're done.
363     if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton)
364         return true;
365
366     Node* innerNode = 0;
367     RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
368     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
369
370     IntPoint localPoint = result.localPoint();
371     localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());
372
373     int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();
374     if (m_resultsButton && m_resultsButton->renderer() && pointInContainer.x() < textLeft)
375         innerNode = m_resultsButton.get();
376
377 #if ENABLE(INPUT_SPEECH)
378     if (!innerNode && m_speechButton && m_speechButton->renderer()) {
379         int buttonLeft = tx + x() + innerBlockRenderer->x() + innerBlockRenderer->width() - m_speechButton->renderBox()->width();
380         if (pointInContainer.x() >= buttonLeft)
381             innerNode = m_speechButton.get();
382     }
383 #endif
384
385     if (!innerNode) {
386         int textRight = textLeft + innerTextRenderer->width();
387         if (m_cancelButton && m_cancelButton->renderer() && pointInContainer.x() > textRight)
388             innerNode = m_cancelButton.get();
389     }
390
391     if (innerNode) {
392         result.setInnerNode(innerNode);
393         localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
394     }
395
396     result.setLocalPoint(localPoint);
397     return true;
398 }
399
400 void RenderTextControlSingleLine::forwardEvent(Event* event)
401 {
402     RenderBox* innerTextRenderer = innerTextElement()->renderBox();
403
404     if (event->type() == eventNames().blurEvent) {
405         if (innerTextRenderer) {
406             if (RenderLayer* innerLayer = innerTextRenderer->layer())
407                 innerLayer->scrollToOffset(!style()->isLeftToRightDirection() ? innerLayer->scrollWidth() : 0, 0);
408         }
409
410         capsLockStateMayHaveChanged();
411     } else if (event->type() == eventNames().focusEvent)
412         capsLockStateMayHaveChanged();
413
414     if (!event->isMouseEvent()) {
415         RenderTextControl::forwardEvent(event);
416         return;
417     }
418
419 #if ENABLE(INPUT_SPEECH)
420     if (RenderBox* speechBox = m_speechButton ? m_speechButton->renderBox() : 0) {
421         RenderBox* parent = innerTextRenderer ? innerTextRenderer : this;
422         FloatPoint pointInTextControlCoords = parent->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
423         if (speechBox->frameRect().contains(roundedIntPoint(pointInTextControlCoords))) {
424             m_speechButton->defaultEventHandler(event);
425             return;
426         }
427     }
428 #endif
429
430     FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
431     int textRight = innerTextRenderer->borderBoxRect().maxX();
432
433     if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())
434         m_resultsButton->defaultEventHandler(event);
435     else if (m_cancelButton && localPoint.x() > textRight)
436         m_cancelButton->defaultEventHandler(event);
437     else
438         RenderTextControl::forwardEvent(event);
439 }
440
441 void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
442 {
443     RenderTextControl::styleDidChange(diff, oldStyle);
444
445     if (RenderObject* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderer() : 0) {
446         // We may have set the width and the height in the old style in layout().
447         // Reset them now to avoid getting a spurious layout hint.
448         innerBlockRenderer->style()->setHeight(Length());
449         innerBlockRenderer->style()->setWidth(Length());
450         innerBlockRenderer->setStyle(createInnerBlockStyle(style()));
451     }
452
453     if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)
454         resultsRenderer->setStyle(createResultsButtonStyle(style()));
455
456     if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
457         cancelRenderer->setStyle(createCancelButtonStyle(style()));
458
459     if (RenderObject* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderer() : 0)
460         spinRenderer->setStyle(createOuterSpinButtonStyle());
461
462     if (RenderObject* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderer() : 0)
463         spinRenderer->setStyle(createInnerSpinButtonStyle());
464
465 #if ENABLE(INPUT_SPEECH)
466     if (RenderObject* speechRenderer = m_speechButton ? m_speechButton->renderer() : 0)
467         speechRenderer->setStyle(createSpeechButtonStyle());
468 #endif
469
470     setHasOverflowClip(false);
471 }
472
473 void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
474 {
475     if (!node() || !document())
476         return;
477
478     // Only draw the caps lock indicator if these things are true:
479     // 1) The field is a password field
480     // 2) The frame is active
481     // 3) The element is focused
482     // 4) The caps lock is on
483     bool shouldDrawCapsLockIndicator = false;
484
485     if (Frame* frame = document()->frame())
486         shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
487                                       && frame->selection()->isFocusedAndActive()
488                                       && document()->focusedNode() == node()
489                                       && PlatformKeyboardEvent::currentCapsLockState();
490
491     if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
492         m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
493         repaint();
494     }
495 }
496
497 bool RenderTextControlSingleLine::hasControlClip() const
498 {
499     bool clip = m_cancelButton;
500     return clip;
501 }
502
503 IntRect RenderTextControlSingleLine::controlClipRect(int tx, int ty) const
504 {
505     // This should only get called for search & speech inputs.
506     ASSERT(hasControlClip());
507
508     IntRect clipRect = IntRect(m_innerBlock->renderBox()->frameRect());
509     clipRect.move(tx, ty);
510     return clipRect;
511 }
512
513 int RenderTextControlSingleLine::textBlockWidth() const
514 {
515     int width = RenderTextControl::textBlockWidth();
516
517     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
518         resultsRenderer->computeLogicalWidth();
519         width -= resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->marginRight();
520     }
521
522     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
523         cancelRenderer->computeLogicalWidth();
524         width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
525     }
526
527     if (RenderBox* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
528         spinRenderer->computeLogicalWidth();
529         width -= spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight();
530     }
531
532 #if ENABLE(INPUT_SPEECH)
533     if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
534         speechRenderer->computeLogicalWidth();
535         width -= speechRenderer->width() + speechRenderer->marginLeft() + speechRenderer->marginRight();
536     }
537 #endif
538
539     return width - decorationWidthRight();
540 }
541
542 int RenderTextControlSingleLine::decorationWidthRight() const
543 {
544     int width = 0;
545     if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
546         spinRenderer->computeLogicalWidth();
547         width += spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight();
548     }
549     if (width > 0)
550         width += paddingRight() + borderRight();
551     return width;
552 }
553     
554 float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
555 {
556     // Since Lucida Grande is the default font, we want this to match the width
557     // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
558     // IE for some encodings (in IE, the default font is encoding specific).
559     // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg.
560     if (family == AtomicString("Lucida Grande"))
561         return scaleEmToUnits(901);
562
563     return RenderTextControl::getAvgCharWidth(family);
564 }
565     
566 int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
567 {
568     int factor = inputElement()->size();
569     if (factor <= 0)
570         factor = 20;
571
572     int result = static_cast<int>(ceilf(charWidth * factor));
573
574     float maxCharWidth = 0.f;
575     AtomicString family = style()->font().family().family();
576     // Since Lucida Grande is the default font, we want this to match the width
577     // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
578     // IE for some encodings (in IE, the default font is encoding specific).
579     // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg.
580     if (family == AtomicString("Lucida Grande"))
581         maxCharWidth = scaleEmToUnits(4027);
582     else if (hasValidAvgCharWidth(family))
583         maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth());
584
585     // For text inputs, IE adds some extra width.
586     if (maxCharWidth > 0.f)
587         result += maxCharWidth - charWidth;
588
589     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
590         result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() +
591                   resultsRenderer->paddingLeft() + resultsRenderer->paddingRight();
592
593     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
594         result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
595                   cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
596
597 #if ENABLE(INPUT_SPEECH)
598     if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
599         result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
600                   speechRenderer->paddingLeft() + speechRenderer->paddingRight();
601     }
602 #endif
603     return result;
604 }
605
606 int RenderTextControlSingleLine::preferredDecorationWidthRight() const
607 {
608     int width = 0;
609     if (RenderBox* spinRenderer = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
610         spinRenderer->computeLogicalWidth();
611         width += spinRenderer->minPreferredLogicalWidth() + spinRenderer->marginLeft() + spinRenderer->marginRight();
612     }
613     if (width > 0)
614         width += paddingRight() + borderRight();
615     return width;
616 }
617
618 void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
619 {
620     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
621         resultsRenderer->computeLogicalHeight();
622         setHeight(max(height(),
623                   resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
624                   resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
625                   resultsRenderer->marginTop() + resultsRenderer->marginBottom()));
626         lineHeight = max(lineHeight, resultsRenderer->height());
627     }
628     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
629         cancelRenderer->computeLogicalHeight();
630         setHeight(max(height(),
631                   cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
632                   cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
633                   cancelRenderer->marginTop() + cancelRenderer->marginBottom()));
634         lineHeight = max(lineHeight, cancelRenderer->height());
635     }
636
637     setHeight(height() + lineHeight);
638 }
639
640 void RenderTextControlSingleLine::createSubtreeIfNeeded()
641 {
642     if (inputElement()->isSearchField()) {
643         if (!m_innerBlock) {
644             // Create the inner block element
645             m_innerBlock = TextControlInnerElement::create(toHTMLElement(node()));
646             m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
647         }
648
649 #if ENABLE(INPUT_SPEECH)
650         if (inputElement()->isSpeechEnabled() && !m_speechButton) {
651             // Create the speech button element.
652             m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
653             m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
654         }
655 #endif
656
657         if (!m_resultsButton) {
658             // Create the search results button element.
659             m_resultsButton = SearchFieldResultsButtonElement::create(document());
660             m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
661         }
662
663         // Create innerText element before adding the other buttons.
664         RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
665
666         if (!m_cancelButton) {
667             // Create the cancel button element.
668             m_cancelButton = SearchFieldCancelButtonElement::create(document());
669             m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
670         }
671     } else {
672         RenderTextControl::createSubtreeIfNeeded(0);
673
674 #if ENABLE(INPUT_SPEECH)
675         if (inputElement()->isSpeechEnabled() && !m_speechButton) {
676             // Create the speech button element.
677             m_speechButton = InputFieldSpeechButtonElement::create(toHTMLElement(node()));
678             m_speechButton->attachInnerElement(node(), createSpeechButtonStyle(), renderArena());
679         }
680 #endif
681
682         bool hasSpinButton = theme()->shouldHaveSpinButton(inputElement());
683
684         if (hasSpinButton && !m_innerSpinButton) {
685             m_innerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
686             m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena());
687         }
688         if (hasSpinButton && !m_outerSpinButton) {
689             m_outerSpinButton = SpinButtonElement::create(toHTMLElement(node()));
690             m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
691         }
692     }
693 }
694
695 void RenderTextControlSingleLine::updateFromElement()
696 {
697     createSubtreeIfNeeded();
698     RenderTextControl::updateFromElement();
699
700     if (m_cancelButton)
701         updateCancelButtonVisibility();
702
703     if (!inputElement()->suggestedValue().isNull())
704         setInnerTextValue(inputElement()->suggestedValue());
705     else {
706         if (node()->hasTagName(inputTag)) {
707             // For HTMLInputElement, update the renderer value if the formControlValueMatchesRenderer()
708             // flag is false. It protects an unacceptable renderer value from
709             // being overwritten with the DOM value.
710             if (!inputElement()->formControlValueMatchesRenderer())
711                 setInnerTextValue(inputElement()->visibleValue());
712         }
713     }
714
715     if (m_searchPopupIsVisible)
716         m_searchPopup->popupMenu()->updateFromElement();
717 }
718
719 void RenderTextControlSingleLine::cacheSelection(int start, int end)
720 {
721     inputElement()->cacheSelection(start, end);
722 }
723
724 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
725 {
726     RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();   
727     textBlockStyle->inheritFrom(startStyle);
728     adjustInnerTextStyle(startStyle, textBlockStyle.get());
729
730     textBlockStyle->setWhiteSpace(PRE);
731     textBlockStyle->setWordWrap(NormalWordWrap);
732     textBlockStyle->setOverflowX(OHIDDEN);
733     textBlockStyle->setOverflowY(OHIDDEN);
734
735     // Do not allow line-height to be smaller than our default.
736     if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
737         textBlockStyle->setLineHeight(Length(-100.0f, Percent));
738
739     WebCore::EDisplay display = (m_innerBlock || theme()->shouldHaveSpinButton(inputElement()) ? INLINE_BLOCK : BLOCK);
740 #if ENABLE(INPUT_SPEECH)
741     if (inputElement()->isSpeechEnabled())
742       display = INLINE_BLOCK;
743 #endif
744     textBlockStyle->setDisplay(display);
745
746     // We're adding one extra pixel of padding to match WinIE.
747     textBlockStyle->setPaddingLeft(Length(1, Fixed));
748     textBlockStyle->setPaddingRight(Length(1, Fixed));
749
750     return textBlockStyle.release();
751 }
752
753 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
754 {
755     RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
756     innerBlockStyle->inheritFrom(startStyle);
757
758     innerBlockStyle->setDisplay(BLOCK);
759     innerBlockStyle->setDirection(LTR);
760
761     // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
762     innerBlockStyle->setUserModify(READ_ONLY);
763
764     return innerBlockStyle.release();
765 }
766
767 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createResultsButtonStyle(const RenderStyle* startStyle) const
768 {
769     HTMLInputElement* input = inputElement();
770
771     RefPtr<RenderStyle> resultsBlockStyle;
772     if (input->maxResults() < 0)
773         resultsBlockStyle = getCachedPseudoStyle(SEARCH_DECORATION);
774     else if (!input->maxResults())
775         resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_DECORATION);
776     else
777         resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_BUTTON);
778
779     if (!resultsBlockStyle)
780         resultsBlockStyle = RenderStyle::create();
781
782     if (startStyle)
783         resultsBlockStyle->inheritFrom(startStyle);
784
785     return resultsBlockStyle.release();
786 }
787
788 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(const RenderStyle* startStyle) const
789 {
790     RefPtr<RenderStyle> cancelBlockStyle;
791     
792     if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(SEARCH_CANCEL_BUTTON))
793         // We may be sharing style with another search field, but we must not share the cancel button style.
794         cancelBlockStyle = RenderStyle::clone(pseudoStyle.get());
795     else
796         cancelBlockStyle = RenderStyle::create();
797
798     if (startStyle)
799         cancelBlockStyle->inheritFrom(startStyle);
800
801     cancelBlockStyle->setVisibility(visibilityForCancelButton());
802     return cancelBlockStyle.release();
803 }
804
805 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerSpinButtonStyle() const
806 {
807     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INNER_SPIN_BUTTON);
808     if (!buttonStyle)
809         buttonStyle = RenderStyle::create();
810     buttonStyle->inheritFrom(style());
811     return buttonStyle.release();
812 }
813
814 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createOuterSpinButtonStyle() const
815 {
816     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(OUTER_SPIN_BUTTON);
817     if (!buttonStyle)
818         buttonStyle = RenderStyle::create();
819     buttonStyle->inheritFrom(style());
820     return buttonStyle.release();
821 }
822
823 #if ENABLE(INPUT_SPEECH)
824 PassRefPtr<RenderStyle> RenderTextControlSingleLine::createSpeechButtonStyle() const
825 {
826     RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INPUT_SPEECH_BUTTON);
827     if (!buttonStyle)
828         buttonStyle = RenderStyle::create();
829     buttonStyle->inheritFrom(style());
830     return buttonStyle.release();
831 }
832 #endif
833
834 void RenderTextControlSingleLine::updateCancelButtonVisibility() const
835 {
836     if (!m_cancelButton->renderer())
837         return;
838
839     const RenderStyle* curStyle = m_cancelButton->renderer()->style();
840     EVisibility buttonVisibility = visibilityForCancelButton();
841     if (curStyle->visibility() == buttonVisibility)
842         return;
843
844     RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle);
845     cancelButtonStyle->setVisibility(buttonVisibility);
846     m_cancelButton->renderer()->setStyle(cancelButtonStyle);
847 }
848
849 EVisibility RenderTextControlSingleLine::visibilityForCancelButton() const
850 {
851     return inputElement()->value().isEmpty() ? HIDDEN : VISIBLE;
852 }
853
854 const AtomicString& RenderTextControlSingleLine::autosaveName() const
855 {
856     return static_cast<Element*>(node())->getAttribute(autosaveAttr);
857 }
858
859 void RenderTextControlSingleLine::startSearchEventTimer()
860 {
861     unsigned length = text().length();
862
863     // If there's no text, fire the event right away.
864     if (!length) {
865         stopSearchEventTimer();
866         inputElement()->onSearch();
867         return;
868     }
869
870     // After typing the first key, we wait 0.5 seconds.
871     // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
872     m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
873 }
874
875 void RenderTextControlSingleLine::searchEventTimerFired(Timer<RenderTextControlSingleLine>*)
876 {
877     inputElement()->onSearch();
878 }
879
880 // PopupMenuClient methods
881 void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents)
882 {
883     ASSERT(static_cast<int>(listIndex) < listSize());
884     HTMLInputElement* input = inputElement();
885     if (static_cast<int>(listIndex) == (listSize() - 1)) {
886         if (fireEvents) {
887             m_recentSearches.clear();
888             const AtomicString& name = autosaveName();
889             if (!name.isEmpty()) {
890                 if (!m_searchPopup)
891                     m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
892                 m_searchPopup->saveRecentSearches(name, m_recentSearches);
893             }
894         }
895     } else {
896         input->setValue(itemText(listIndex));
897         if (fireEvents)
898             input->onSearch();
899         input->select();
900     }
901 }
902
903 String RenderTextControlSingleLine::itemText(unsigned listIndex) const
904 {
905     int size = listSize();
906     if (size == 1) {
907         ASSERT(!listIndex);
908         return searchMenuNoRecentSearchesText();
909     }
910     if (!listIndex)
911         return searchMenuRecentSearchesText();
912     if (itemIsSeparator(listIndex))
913         return String();
914     if (static_cast<int>(listIndex) == (size - 1))
915         return searchMenuClearRecentSearchesText();
916     return m_recentSearches[listIndex - 1];
917 }
918
919 String RenderTextControlSingleLine::itemLabel(unsigned) const
920 {
921     return String();
922 }
923
924 String RenderTextControlSingleLine::itemIcon(unsigned) const
925 {
926     return String();
927 }
928
929 bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const
930 {
931      if (!listIndex || itemIsSeparator(listIndex))
932         return false;
933     return true;
934 }
935
936 PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
937 {
938     return menuStyle();
939 }
940
941 PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
942 {
943     return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE, style()->display() == NONE, style()->textIndent(), style()->direction(), style()->unicodeBidi() == Override);
944 }
945
946 int RenderTextControlSingleLine::clientInsetLeft() const
947 {
948     // Inset the menu by the radius of the cap on the left so that
949     // it only runs along the straight part of the bezel.
950     return height() / 2;
951 }
952
953 int RenderTextControlSingleLine::clientInsetRight() const
954 {
955     // Inset the menu by the radius of the cap on the right so that
956     // it only runs along the straight part of the bezel (unless it needs
957     // to be wider).
958     return height() / 2;
959 }
960
961 int RenderTextControlSingleLine::clientPaddingLeft() const
962 {
963     int padding = paddingLeft();
964
965     if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
966         padding += resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->paddingLeft() + resultsRenderer->marginRight() + resultsRenderer->paddingRight();
967
968     return padding;
969 }
970
971 int RenderTextControlSingleLine::clientPaddingRight() const
972 {
973     int padding = paddingRight();
974
975     if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
976         padding += cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->paddingLeft() + cancelRenderer->marginRight() + cancelRenderer->paddingRight();
977
978     return padding;
979 }
980
981 int RenderTextControlSingleLine::listSize() const
982 {
983     // If there are no recent searches, then our menu will have 1 "No recent searches" item.
984     if (!m_recentSearches.size())
985         return 1;
986     // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
987     return m_recentSearches.size() + 3;
988 }
989
990 int RenderTextControlSingleLine::selectedIndex() const
991 {
992     return -1;
993 }
994
995 void RenderTextControlSingleLine::popupDidHide()
996 {
997     m_searchPopupIsVisible = false;
998 }
999
1000 bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const
1001 {
1002     // The separator will be the second to last item in our list.
1003     return static_cast<int>(listIndex) == (listSize() - 2);
1004 }
1005
1006 bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const
1007 {
1008     return listIndex == 0;
1009 }
1010
1011 bool RenderTextControlSingleLine::itemIsSelected(unsigned) const
1012 {
1013     return false;
1014 }
1015
1016 void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
1017 {
1018     inputElement()->setValue(itemText(listIndex));
1019 }
1020
1021 FontSelector* RenderTextControlSingleLine::fontSelector() const
1022 {
1023     return document()->styleSelector()->fontSelector();
1024 }
1025
1026 HostWindow* RenderTextControlSingleLine::hostWindow() const
1027 {
1028     return document()->view()->hostWindow();
1029 }
1030
1031 void RenderTextControlSingleLine::autoscroll()
1032 {
1033     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1034     if (layer)
1035         layer->autoscroll();
1036 }
1037
1038 int RenderTextControlSingleLine::scrollWidth() const
1039 {
1040     if (innerTextElement())
1041         return innerTextElement()->scrollWidth();
1042     return RenderBlock::scrollWidth();
1043 }
1044
1045 int RenderTextControlSingleLine::scrollHeight() const
1046 {
1047     if (innerTextElement())
1048         return innerTextElement()->scrollHeight();
1049     return RenderBlock::scrollHeight();
1050 }
1051
1052 int RenderTextControlSingleLine::scrollLeft() const
1053 {
1054     if (innerTextElement())
1055         return innerTextElement()->scrollLeft();
1056     return RenderBlock::scrollLeft();
1057 }
1058
1059 int RenderTextControlSingleLine::scrollTop() const
1060 {
1061     if (innerTextElement())
1062         return innerTextElement()->scrollTop();
1063     return RenderBlock::scrollTop();
1064 }
1065
1066 void RenderTextControlSingleLine::setScrollLeft(int newLeft)
1067 {
1068     if (innerTextElement())
1069         innerTextElement()->setScrollLeft(newLeft);
1070 }
1071
1072 void RenderTextControlSingleLine::setScrollTop(int newTop)
1073 {
1074     if (innerTextElement())
1075         innerTextElement()->setScrollTop(newTop);
1076 }
1077
1078 bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
1079 {
1080     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1081     if (layer && layer->scroll(direction, granularity, multiplier))
1082         return true;
1083     return RenderBlock::scroll(direction, granularity, multiplier, stopNode);
1084 }
1085
1086 bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
1087 {
1088     RenderLayer* layer = innerTextElement()->renderBox()->layer();
1089     if (layer && layer->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
1090         return true;
1091     return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode);
1092 }
1093
1094 PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
1095 {
1096     RefPtr<Scrollbar> widget;
1097     bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
1098     if (hasCustomScrollbarStyle)
1099         widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this);
1100     else
1101         widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
1102     return widget.release();
1103 }
1104
1105 HTMLInputElement* RenderTextControlSingleLine::inputElement() const
1106 {
1107     return node()->toInputElement();
1108 }
1109
1110 int RenderTextControlSingleLine::textBlockInsetLeft() const
1111 {
1112     int inset = borderLeft() + clientPaddingLeft();
1113     if (HTMLElement* innerText = innerTextElement()) {
1114         if (RenderBox* innerTextRenderer = innerText->renderBox())
1115             inset += innerTextRenderer->paddingLeft();
1116     }
1117     return inset;
1118 }
1119     
1120 int RenderTextControlSingleLine::textBlockInsetRight() const
1121 {
1122     int inset = borderRight() + clientPaddingRight();
1123     if (HTMLElement* innerText = innerTextElement()) {
1124         if (RenderBox* innerTextRenderer = innerText->renderBox())
1125             inset += innerTextRenderer->paddingRight();
1126     }
1127     return inset;
1128 }
1129
1130 int RenderTextControlSingleLine::textBlockInsetTop() const
1131 {
1132     RenderBox* innerRenderer = 0;
1133     if (m_innerBlock)
1134         innerRenderer = m_innerBlock->renderBox();
1135     else if (HTMLElement* innerText = innerTextElement())
1136         innerRenderer = innerText->renderBox();
1137     
1138     if (innerRenderer)
1139         return innerRenderer->y();
1140     
1141     return borderTop() + paddingTop();
1142 }    
1143
1144 }