WebCore:
[WebKit-https.git] / WebCore / rendering / RenderTextControl.cpp
1 /**
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "RenderTextControl.h"
23
24 #include "CharacterNames.h"
25 #include "CSSStyleSelector.h"
26 #include "Document.h"
27 #include "Editor.h"
28 #include "EditorClient.h"
29 #include "Event.h"
30 #include "EventNames.h"
31 #include "FontSelector.h"
32 #include "Frame.h"
33 #include "HTMLBRElement.h"
34 #include "HTMLInputElement.h"
35 #include "HTMLNames.h"
36 #include "HTMLTextAreaElement.h"
37 #include "HTMLTextFieldInnerElement.h"
38 #include "HitTestResult.h"
39 #include "LocalizedStrings.h"
40 #include "MouseEvent.h"
41 #include "PlatformKeyboardEvent.h"
42 #include "PlatformScrollBar.h"
43 #include "RenderTheme.h"
44 #include "SearchPopupMenu.h"
45 #include "SelectionController.h"
46 #include "Settings.h"
47 #include "Text.h"
48 #include "TextIterator.h"
49 #include "htmlediting.h"
50 #include "visible_units.h"
51 #include <math.h>
52
53 using namespace std;
54
55 namespace WebCore {
56
57 using namespace EventNames;
58 using namespace HTMLNames;
59
60 class RenderTextControlInnerBlock : public RenderBlock {
61 public:
62     RenderTextControlInnerBlock(Node* node) : RenderBlock(node) { }
63
64     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
65 };
66
67 bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
68 {
69     RenderTextControl* renderer = static_cast<RenderTextControl*>(node()->shadowAncestorNode()->renderer());
70     
71     return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, renderer->placeholderIsVisible() ? HitTestBlockBackground : hitTestAction);
72 }
73
74 RenderTextControl::RenderTextControl(Node* node, bool multiLine)
75     : RenderBlock(node)
76     , m_dirty(false)
77     , m_multiLine(multiLine)
78     , m_placeholderVisible(false)
79     , m_userEdited(false)
80     , m_shouldDrawCapsLockIndicator(false)
81     , m_searchPopup(0)
82     , m_searchPopupIsVisible(false)
83     , m_searchEventTimer(this, &RenderTextControl::searchEventTimerFired)
84 {
85 }
86
87 RenderTextControl::~RenderTextControl()
88 {
89     if (m_searchPopup) {
90         m_searchPopup->disconnectClient();
91         m_searchPopup = 0;
92     }
93     if (m_multiLine && node())
94         static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
95     // The children renderers have already been destroyed by destroyLeftoverChildren
96     if (m_innerBlock)
97         m_innerBlock->detach();
98     else if (m_innerText)
99         m_innerText->detach();
100 }
101
102 void RenderTextControl::setStyle(RenderStyle* style)
103 {
104     RenderBlock::setStyle(style);
105     if (m_innerBlock) {
106         // We may have set the width and the height in the old style in layout(). Reset them now to avoid
107         // getting a spurious layout hint.
108         m_innerBlock->renderer()->style()->setHeight(Length());
109         m_innerBlock->renderer()->style()->setWidth(Length());
110         m_innerBlock->renderer()->setStyle(createInnerBlockStyle(style));
111     }
112
113     if (m_innerText) {
114         RenderBlock* textBlockRenderer = static_cast<RenderBlock*>(m_innerText->renderer());
115         RenderStyle* textBlockStyle = createInnerTextStyle(style);
116         // We may have set the width and the height in the old style in layout(). Reset them now to avoid
117         // getting a spurious layout hint.
118         textBlockRenderer->style()->setHeight(Length());
119         textBlockRenderer->style()->setWidth(Length());
120         textBlockRenderer->setStyle(textBlockStyle);
121         for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
122             if (n->renderer())
123                 n->renderer()->setStyle(textBlockStyle);
124         }
125     }
126     if (m_resultsButton)
127         m_resultsButton->renderer()->setStyle(createResultsButtonStyle(style));
128
129     if (m_cancelButton)
130         m_cancelButton->renderer()->setStyle(createCancelButtonStyle(style));
131
132     setHasOverflowClip(false);
133     setReplaced(isInline());
134 }
135
136 static Color disabledTextColor(const Color& textColor, const Color& backgroundColor)
137 {
138     // The explcit check for black is an optimization for the 99% case (black on white).
139     // This also means that black on black will turn into grey on black when disabled.
140     if (textColor.rgb() == Color::black || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))
141         return textColor.light();
142     return textColor.dark();
143 }
144
145 RenderStyle* RenderTextControl::createInnerBlockStyle(RenderStyle* startStyle)
146 {
147     RenderStyle* innerBlockStyle = new (renderArena()) RenderStyle();
148
149     innerBlockStyle->inheritFrom(startStyle);
150     innerBlockStyle->setDisplay(BLOCK);
151     innerBlockStyle->setDirection(LTR);
152     // 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.
153     innerBlockStyle->setUserModify(READ_ONLY);
154
155     return innerBlockStyle;
156 }
157
158 RenderStyle* RenderTextControl::createInnerTextStyle(RenderStyle* startStyle)
159 {
160     RenderStyle* textBlockStyle = new (renderArena()) RenderStyle();
161     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
162
163     textBlockStyle->inheritFrom(startStyle);
164     // The inner block, if present, always has its direction set to LTR,
165     // so we need to inherit the direction from the element.
166     textBlockStyle->setDirection(style()->direction());
167     textBlockStyle->setUserModify(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
168     if (m_innerBlock)
169         textBlockStyle->setDisplay(INLINE_BLOCK);
170     else
171         textBlockStyle->setDisplay(BLOCK);
172
173     if (m_multiLine) {
174         // Forward overflow properties.
175         textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
176         textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
177
178         // Set word wrap property based on wrap attribute
179         if (static_cast<HTMLTextAreaElement*>(element)->wrap() == HTMLTextAreaElement::ta_NoWrap) {
180             textBlockStyle->setWhiteSpace(PRE);
181             textBlockStyle->setWordWrap(NormalWordWrap);
182         } else {
183             textBlockStyle->setWhiteSpace(PRE_WRAP);
184             textBlockStyle->setWordWrap(BreakWordWrap);
185         }
186     } else {
187         textBlockStyle->setWhiteSpace(PRE);
188         textBlockStyle->setWordWrap(NormalWordWrap);
189         textBlockStyle->setOverflowX(OHIDDEN);
190         textBlockStyle->setOverflowY(OHIDDEN);
191         
192         // Do not allow line-height to be smaller than our default.
193         if (textBlockStyle->font().lineSpacing() > lineHeight(true, true))
194             textBlockStyle->setLineHeight(Length(-100.0f, Percent));
195     }
196
197     if (!m_multiLine) {
198         // We're adding one extra pixel of padding to match WinIE.
199         textBlockStyle->setPaddingLeft(Length(1, Fixed));
200         textBlockStyle->setPaddingRight(Length(1, Fixed));
201     } else {
202         // We're adding three extra pixels of padding to line textareas up with text fields.
203         textBlockStyle->setPaddingLeft(Length(3, Fixed));
204         textBlockStyle->setPaddingRight(Length(3, Fixed));
205     }
206
207     if (!element->isEnabled())
208         textBlockStyle->setColor(disabledTextColor(startStyle->color(), startStyle->backgroundColor()));
209
210     return textBlockStyle;
211 }
212
213 RenderStyle* RenderTextControl::createResultsButtonStyle(RenderStyle* startStyle)
214 {
215     ASSERT(!m_multiLine);
216     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
217     RenderStyle* resultsBlockStyle;
218     if (input->maxResults() < 0)
219         resultsBlockStyle = getPseudoStyle(RenderStyle::SEARCH_DECORATION);
220     else if (!input->maxResults())
221         resultsBlockStyle = getPseudoStyle(RenderStyle::SEARCH_RESULTS_DECORATION);
222     else
223         resultsBlockStyle = getPseudoStyle(RenderStyle::SEARCH_RESULTS_BUTTON);
224
225     if (!resultsBlockStyle)
226         resultsBlockStyle = new (renderArena()) RenderStyle();
227
228     if (startStyle)
229         resultsBlockStyle->inheritFrom(startStyle);
230
231     resultsBlockStyle->setDisplay(INLINE_BLOCK);
232
233     return resultsBlockStyle;
234 }
235
236 RenderStyle* RenderTextControl::createCancelButtonStyle(RenderStyle* startStyle)
237 {
238     RenderStyle* cancelBlockStyle;
239     
240     if (RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SEARCH_CANCEL_BUTTON))
241         // We may be sharing style with another search field, but we must not share the cancel button style.
242         cancelBlockStyle = new (renderArena()) RenderStyle(*pseudoStyle);
243     else
244         cancelBlockStyle = new (renderArena()) RenderStyle();
245
246     if (startStyle)
247         cancelBlockStyle->inheritFrom(startStyle);
248
249     cancelBlockStyle->setDisplay(INLINE_BLOCK);
250
251     updateCancelButtonVisibility(cancelBlockStyle);
252
253     return cancelBlockStyle;
254 }
255
256 void RenderTextControl::updatePlaceholder()
257 {
258     bool oldPlaceholderVisible = m_placeholderVisible;
259     
260     String placeholder;
261     if (!m_multiLine) {
262         HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
263         if (input->value().isEmpty() && document()->focusedNode() != node())
264             placeholder = input->getAttribute(placeholderAttr);
265     }
266
267     if (!placeholder.isEmpty() || m_placeholderVisible) {
268         ExceptionCode ec = 0;
269         m_innerText->setInnerText(placeholder, ec);
270         m_placeholderVisible = !placeholder.isEmpty();
271     }
272
273     Color color;
274     if (!placeholder.isEmpty())
275         color = Color::darkGray;
276     else if (node()->isEnabled())
277         color = style()->color();
278     else
279         color = disabledTextColor(style()->color(), style()->backgroundColor());
280
281     RenderObject* renderer = m_innerText->renderer();
282     RenderStyle* innerStyle = renderer->style();
283     if (innerStyle->color() != color) {
284         innerStyle->setColor(color);
285         renderer->repaint();
286     }
287
288     // temporary disable textSecurity if placeholder is visible
289     if (style()->textSecurity() != TSNONE && oldPlaceholderVisible != m_placeholderVisible) {
290         RenderStyle* newInnerStyle = new (renderArena()) RenderStyle(*innerStyle);
291         newInnerStyle->setTextSecurity(m_placeholderVisible ? TSNONE : style()->textSecurity());
292         renderer->setStyle(newInnerStyle);
293         for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
294             if (n->renderer())
295                 n->renderer()->setStyle(newInnerStyle);
296         }
297     }
298 }
299
300 void RenderTextControl::createSubtreeIfNeeded()
301 {
302     // When adding these elements, create the renderer & style first before adding to the DOM.
303     // Otherwise, the render tree will create some anonymous blocks that will mess up our layout.
304     bool isSearchField = !m_multiLine && static_cast<HTMLInputElement*>(node())->isSearchField();
305     if (isSearchField && !m_innerBlock) {
306         // Create the inner block element and give it a parent, renderer, and style
307         m_innerBlock = new HTMLTextFieldInnerElement(document(), node());
308         RenderBlock* innerBlockRenderer = new (renderArena()) RenderBlock(m_innerBlock.get());
309         m_innerBlock->setRenderer(innerBlockRenderer);
310         m_innerBlock->setAttached();
311         m_innerBlock->setInDocument(true);
312         innerBlockRenderer->setStyle(createInnerBlockStyle(style()));
313
314         // Add inner block renderer to Render tree
315         RenderBlock::addChild(innerBlockRenderer);
316     }
317     if (isSearchField && !m_resultsButton) {
318         // Create the results block element and give it a parent, renderer, and style
319         m_resultsButton = new HTMLSearchFieldResultsButtonElement(document());
320         RenderBlock* resultsBlockRenderer = new (renderArena()) RenderBlock(m_resultsButton.get());
321         m_resultsButton->setRenderer(resultsBlockRenderer);
322         m_resultsButton->setAttached();
323         m_resultsButton->setInDocument(true);
324
325         RenderStyle* resultsBlockStyle = createResultsButtonStyle(m_innerBlock->renderer()->style());
326         resultsBlockRenderer->setStyle(resultsBlockStyle);
327
328         // Add results renderer to DOM & Render tree
329         m_innerBlock->renderer()->addChild(resultsBlockRenderer);
330         ExceptionCode ec = 0;
331         m_innerBlock->appendChild(m_resultsButton, ec);
332     }
333     if (!m_innerText) {
334         // Create the text block element and give it a parent, renderer, and style
335         // For non-search fields, there is no intermediate m_innerBlock as the shadow node.
336         // m_innerText will be the shadow node in that case.
337         m_innerText = new HTMLTextFieldInnerTextElement(document(), m_innerBlock ? 0 : node());
338         RenderTextControlInnerBlock* textBlockRenderer = new (renderArena()) RenderTextControlInnerBlock(m_innerText.get());
339         m_innerText->setRenderer(textBlockRenderer);
340         m_innerText->setAttached();
341         m_innerText->setInDocument(true);
342
343         RenderStyle* parentStyle = style();
344         if (m_innerBlock)
345             parentStyle = m_innerBlock->renderer()->style();
346         RenderStyle* textBlockStyle = createInnerTextStyle(parentStyle);
347         textBlockRenderer->setStyle(textBlockStyle);
348
349         // Add text block renderer to Render tree
350         if (m_innerBlock) {
351             m_innerBlock->renderer()->addChild(textBlockRenderer);
352             ExceptionCode ec = 0;
353             // Add text block to the DOM
354             m_innerBlock->appendChild(m_innerText, ec);
355         } else
356             RenderBlock::addChild(textBlockRenderer);
357     }
358     if (isSearchField && !m_cancelButton) {
359         // Create the close block element and give it a parent, renderer, and style
360         m_cancelButton = new HTMLSearchFieldCancelButtonElement(document());
361         RenderBlock* closeBlockRenderer = new (renderArena()) RenderBlock(m_cancelButton.get());
362         m_cancelButton->setRenderer(closeBlockRenderer);
363         m_cancelButton->setAttached();
364         m_cancelButton->setInDocument(true);
365
366         RenderStyle* closeBlockStyle = createCancelButtonStyle(m_innerBlock->renderer()->style());
367         closeBlockRenderer->setStyle(closeBlockStyle);
368
369         // Add close block renderer to DOM & Render tree
370         m_innerBlock->renderer()->addChild(closeBlockRenderer);
371         ExceptionCode ec = 0;
372         m_innerBlock->appendChild(m_cancelButton, ec);
373     }
374 }
375
376 void RenderTextControl::updateFromElement()
377 {
378     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
379
380     createSubtreeIfNeeded();
381
382     if (m_cancelButton)
383         updateCancelButtonVisibility(m_cancelButton->renderer()->style());
384
385     updatePlaceholder();
386
387     m_innerText->renderer()->style()->setUserModify(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
388
389     if ((!element->valueMatchesRenderer() || m_multiLine) && !m_placeholderVisible) {
390         String value;
391         if (m_multiLine)
392             value = static_cast<HTMLTextAreaElement*>(element)->value();
393         else
394             value = static_cast<HTMLInputElement*>(element)->value();
395         if (value.isNull())
396             value = "";
397         else
398             value = value.replace('\\', backslashAsCurrencySymbol());
399         if (value != text() || !m_innerText->hasChildNodes()) {
400             if (value != text()) {
401                 if (Frame* frame = document()->frame())
402                     frame->editor()->clearUndoRedoOperations();
403             }
404             ExceptionCode ec = 0;
405             m_innerText->setInnerText(value, ec);
406             if (value.endsWith("\n") || value.endsWith("\r"))
407                 m_innerText->appendChild(new HTMLBRElement(document()), ec);
408             m_dirty = false;
409             m_userEdited = false;
410         }
411         element->setValueMatchesRenderer();
412     }
413
414     if (m_searchPopupIsVisible)
415         m_searchPopup->updateFromElement();
416 }
417
418 int RenderTextControl::selectionStart()
419 {
420     Frame* frame = document()->frame();
421     if (!frame)
422         return 0;
423     return indexForVisiblePosition(frame->selectionController()->start());
424 }
425
426 int RenderTextControl::selectionEnd()
427 {
428     Frame* frame = document()->frame();
429     if (!frame)
430         return 0;
431     return indexForVisiblePosition(frame->selectionController()->end());
432 }
433
434 void RenderTextControl::setSelectionStart(int start)
435 {
436     setSelectionRange(start, max(start, selectionEnd()));
437 }
438
439 void RenderTextControl::setSelectionEnd(int end)
440 {
441     setSelectionRange(min(end, selectionStart()), end);
442 }
443
444 void RenderTextControl::select()
445 {
446     setSelectionRange(0, text().length());
447 }
448
449 void RenderTextControl::setSelectionRange(int start, int end)
450 {
451     end = max(end, 0);
452     start = min(max(start, 0), end);
453
454     document()->updateLayout();
455
456     if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderer()->height()) {
457         if (m_multiLine)
458             static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
459         else
460             static_cast<HTMLInputElement*>(node())->cacheSelection(start, end);
461         return;
462     }
463     VisiblePosition startPosition = visiblePositionForIndex(start);
464     VisiblePosition endPosition;
465     if (start == end)
466         endPosition = startPosition;
467     else
468         endPosition = visiblePositionForIndex(end);
469
470     ASSERT(startPosition.isNotNull() && endPosition.isNotNull());
471     ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
472
473     Selection newSelection = Selection(startPosition, endPosition);
474
475     if (Frame* frame = document()->frame())
476         frame->selectionController()->setSelection(newSelection);
477
478     // FIXME: Granularity is stored separately on the frame, but also in the selection controller.
479     // The granularity in the selection controller should be used, and then this line of code would not be needed.
480     if (Frame* frame = document()->frame())
481         frame->setSelectionGranularity(CharacterGranularity);
482 }
483
484 Selection RenderTextControl::selection(int start, int end) const
485 {
486     return Selection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),
487                      VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));
488 }
489
490 VisiblePosition RenderTextControl::visiblePositionForIndex(int index)
491 {
492     if (index <= 0)
493         return VisiblePosition(m_innerText.get(), 0, DOWNSTREAM);
494     ExceptionCode ec = 0;
495     RefPtr<Range> range = new Range(document());
496     range->selectNodeContents(m_innerText.get(), ec);
497     CharacterIterator it(range.get());
498     it.advance(index - 1);
499     return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM);
500 }
501
502 int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
503 {
504     Position indexPosition = pos.deepEquivalent();
505     if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != m_innerText)
506         return 0;
507     ExceptionCode ec = 0;
508     RefPtr<Range> range = new Range(document());
509     range->setStart(m_innerText.get(), 0, ec);
510     range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
511     return TextIterator::rangeLength(range.get());
512 }
513
514 void RenderTextControl::updateCancelButtonVisibility(RenderStyle* style)
515 {
516     ASSERT(!m_multiLine);
517     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
518     if (input->value().isEmpty())
519         style->setVisibility(HIDDEN);
520     else
521         style->setVisibility(VISIBLE);
522 }
523
524 void RenderTextControl::subtreeHasChanged()
525 {
526     bool wasDirty = m_dirty;
527     m_dirty = true;
528     m_userEdited = true;
529     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
530     if (m_multiLine) {
531         element->setValueMatchesRenderer(false);
532         if (element->focused())
533             if (Frame* frame = document()->frame())
534                 frame->textDidChangeInTextArea(element);
535     } else {
536         HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
537         input->setValueFromRenderer(input->constrainValue(text()));
538         if (m_cancelButton)
539             updateCancelButtonVisibility(m_cancelButton->renderer()->style());
540
541         // If the incremental attribute is set, then dispatch the search event
542         if (!input->getAttribute(incrementalAttr).isNull())
543             startSearchEventTimer();
544
545         if (!wasDirty) {
546             if (input->focused())
547                 if (Frame* frame = document()->frame())
548                     frame->textFieldDidBeginEditing(input);
549         }
550         if (input->focused())
551             if (Frame* frame = document()->frame())
552                 frame->textDidChangeInTextField(input);
553     }
554 }
555
556 String RenderTextControl::finishText(Vector<UChar>& result) const
557 {
558     UChar symbol = backslashAsCurrencySymbol();
559     if (symbol != '\\') {
560         size_t size = result.size();
561         for (size_t i = 0; i < size; ++i)
562             if (result[i] == '\\')
563                 result[i] = symbol;
564     }
565
566     return String::adopt(result);
567 }
568
569 String RenderTextControl::text()
570 {
571     if (!m_innerText)
572         return "";
573  
574     Frame* frame = document()->frame();
575     Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
576
577     Vector<UChar> result;
578
579     for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
580         if (n->isTextNode()) {
581             Text* text = static_cast<Text*>(n);
582             String data = text->data();
583             unsigned length = data.length();
584             if (text != compositionNode)
585                 result.append(data.characters(), length);
586             else {
587                 unsigned compositionStart = min(frame->editor()->compositionStart(), length);
588                 unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
589                 result.append(data.characters(), compositionStart);
590                 result.append(data.characters() + compositionEnd, length - compositionEnd);
591             }
592         }
593     }
594
595     return finishText(result);
596 }
597
598 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
599 {
600     RootInlineBox* next;
601     for (; line; line = next) {
602         next = line->nextRootBox();
603         if (next && !line->endsWithBreak()) {
604             ASSERT(line->lineBreakObj());
605             breakNode = line->lineBreakObj()->node();
606             breakOffset = line->lineBreakPos();
607             line = next;
608             return;
609         }
610     }
611     breakNode = 0;
612 }
613
614 String RenderTextControl::textWithHardLineBreaks()
615 {
616     if (!m_innerText)
617         return "";
618     Node* firstChild = m_innerText->firstChild();
619     if (!firstChild)
620         return "";
621
622     document()->updateLayout();
623
624     RenderObject* renderer = firstChild->renderer();
625     if (!renderer)
626         return "";
627
628     InlineBox* box = renderer->inlineBox(0, DOWNSTREAM);
629     if (!box)
630         return "";
631
632     Frame* frame = document()->frame();
633     Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
634
635     Node* breakNode;
636     unsigned breakOffset;
637     RootInlineBox* line = box->root();
638     getNextSoftBreak(line, breakNode, breakOffset);
639
640     Vector<UChar> result;
641
642     for (Node* n = firstChild; n; n = n->traverseNextNode(m_innerText.get())) {
643         if (n->hasTagName(brTag))
644             result.append(&newlineCharacter, 1);
645         else if (n->isTextNode()) {
646             Text* text = static_cast<Text*>(n);
647             String data = text->data();
648             unsigned length = data.length();
649             unsigned compositionStart = (text == compositionNode)
650                 ? min(frame->editor()->compositionStart(), length) : 0;
651             unsigned compositionEnd = (text == compositionNode)
652                 ? min(max(compositionStart, frame->editor()->compositionEnd()), length) : 0;
653             unsigned position = 0;
654             while (breakNode == n && breakOffset < compositionStart) {
655                 result.append(data.characters() + position, breakOffset - position);
656                 position = breakOffset;
657                 result.append(&newlineCharacter, 1);
658                 getNextSoftBreak(line, breakNode, breakOffset);
659             }
660             result.append(data.characters() + position, compositionStart - position);
661             position = compositionEnd;
662             while (breakNode == n && breakOffset <= length) {
663                 if (breakOffset > position) {
664                     result.append(data.characters() + position, breakOffset - position);
665                     position = breakOffset;
666                     result.append(&newlineCharacter, 1);
667                 }
668                 getNextSoftBreak(line, breakNode, breakOffset);
669             }
670             result.append(data.characters() + position, length - position);
671         }
672         while (breakNode == n)
673             getNextSoftBreak(line, breakNode, breakOffset);
674     }
675
676     return finishText(result);
677 }
678
679 void RenderTextControl::calcHeight()
680 {
681     int rows = 1;
682     if (m_multiLine)
683         rows = static_cast<HTMLTextAreaElement*>(node())->rows();
684
685     int line = m_innerText->renderer()->lineHeight(true, true);
686     int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
687
688     int innerToAdd = m_innerText->renderer()->borderTop() + m_innerText->renderer()->borderBottom() +
689                      m_innerText->renderer()->paddingTop() + m_innerText->renderer()->paddingBottom() +
690                      m_innerText->renderer()->marginTop() + m_innerText->renderer()->marginBottom();
691
692     if (m_resultsButton) {
693         static_cast<RenderBlock*>(m_resultsButton->renderer())->calcHeight();
694         innerToAdd = max(innerToAdd,
695                          m_resultsButton->renderer()->borderTop() + m_resultsButton->renderer()->borderBottom() +
696                          m_resultsButton->renderer()->paddingTop() + m_resultsButton->renderer()->paddingBottom() +
697                          m_resultsButton->renderer()->marginTop() + m_resultsButton->renderer()->marginBottom());
698         line = max(line, m_resultsButton->renderer()->height());
699     }
700     if (m_cancelButton) {
701         static_cast<RenderBlock*>(m_cancelButton->renderer())->calcHeight();
702         innerToAdd = max(innerToAdd,
703                          m_cancelButton->renderer()->borderTop() + m_cancelButton->renderer()->borderBottom() +
704                          m_cancelButton->renderer()->paddingTop() + m_cancelButton->renderer()->paddingBottom() +
705                          m_cancelButton->renderer()->marginTop() + m_cancelButton->renderer()->marginBottom());
706         line = max(line, m_cancelButton->renderer()->height());
707     }
708     toAdd += innerToAdd;
709
710     // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
711     int scrollbarSize = 0;
712     // We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
713     if (m_innerText->renderer()->style()->overflowX() == OSCROLL ||  (m_innerText->renderer()->style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap))
714         scrollbarSize = PlatformScrollbar::horizontalScrollbarHeight();
715
716     m_height = line * rows + toAdd + scrollbarSize;
717
718     RenderBlock::calcHeight();
719 }
720
721 short RenderTextControl::baselinePosition(bool b, bool isRootLineBox) const
722 {
723     if (m_multiLine)
724         return height() + marginTop() + marginBottom();
725     return RenderBlock::baselinePosition(b, isRootLineBox);
726 }
727
728 bool RenderTextControl::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
729 {
730     // 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
731     // was on the control but not on the inner element (see Radar 4617841).
732
733     // 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,
734     // and act as if we've hit the close block if we're to the right of the inner text block.
735
736     if (RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction) &&
737         (result.innerNode() == element() || result.innerNode() == m_innerBlock)) {
738         IntPoint localPoint = IntPoint(x - tx - m_x, y - ty - m_y);
739         if (m_innerBlock) {
740             int textLeft = tx + m_x + m_innerBlock->renderer()->xPos() + m_innerText->renderer()->xPos();
741             int textRight = textLeft + m_innerText->renderer()->width();
742             if (m_resultsButton && x < textLeft) {
743                 result.setInnerNode(m_resultsButton.get());
744                 result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_resultsButton->renderer()->xPos(),
745                                               localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_resultsButton->renderer()->yPos()));
746                 return true;
747             } 
748             if (m_cancelButton && x > textRight) {
749                 result.setInnerNode(m_cancelButton.get());
750                 result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_cancelButton->renderer()->xPos(),
751                                               localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_cancelButton->renderer()->yPos()));
752                 return true;
753             }
754         }
755         
756         // Hit the inner text block.
757         result.setInnerNode(m_innerText.get());
758         result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->xPos() : 0),
759                                       localPoint.y() - m_innerText->renderer()->yPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->yPos() : 0)));
760         
761         return true;
762     }
763
764     return false;
765 }
766
767 IntRect RenderTextControl::controlClipRect(int tx, int ty) const
768 {
769     IntRect clipRect = contentBox();
770     clipRect.move(tx, ty);
771     return clipRect;
772 }
773
774 void RenderTextControl::layout()
775 {
776     int oldHeight = m_height;
777     calcHeight();
778     bool relayoutChildren = oldHeight != m_height;
779
780     // Set the text block's height
781     int textBlockHeight = m_height - paddingTop() - paddingBottom() - borderTop() - borderBottom();
782     int currentTextBlockHeight = m_innerText->renderer()->height();
783     if (m_multiLine || m_innerBlock || currentTextBlockHeight > m_height) {
784         if (textBlockHeight != currentTextBlockHeight)
785             relayoutChildren = true;
786         m_innerText->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
787     }
788     if (m_innerBlock) {
789         if (textBlockHeight != m_innerBlock->renderer()->height())
790             relayoutChildren = true;
791         m_innerBlock->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
792     }
793
794     int oldWidth = m_width;
795     calcWidth();
796     if (oldWidth != m_width)
797         relayoutChildren = true;
798
799     int searchExtrasWidth = 0;
800     if (m_resultsButton) {
801         m_resultsButton->renderer()->calcWidth();
802         searchExtrasWidth += m_resultsButton->renderer()->width();
803     }
804     if (m_cancelButton) {
805         m_cancelButton->renderer()->calcWidth();
806         searchExtrasWidth += m_cancelButton->renderer()->width();
807     }
808
809     // Set the text block's width
810     int textBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight() -
811                          m_innerText->renderer()->paddingLeft() - m_innerText->renderer()->paddingRight() - searchExtrasWidth;
812     if (textBlockWidth != m_innerText->renderer()->width())
813         relayoutChildren = true;
814     m_innerText->renderer()->style()->setWidth(Length(textBlockWidth, Fixed));
815     if (m_innerBlock) {
816         int innerBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight();
817         if (innerBlockWidth != m_innerBlock->renderer()->width())
818             relayoutChildren = true;
819         m_innerBlock->renderer()->style()->setWidth(Length(innerBlockWidth, Fixed));
820     }
821
822     RenderBlock::layoutBlock(relayoutChildren);
823     
824     // For text fields, center the inner text vertically
825     // Don't do this for search fields, since we don't honor height for them
826     if (!m_multiLine) {
827         currentTextBlockHeight = m_innerText->renderer()->height();
828         if (!m_innerBlock && currentTextBlockHeight < m_height)
829             m_innerText->renderer()->setPos(m_innerText->renderer()->xPos(), (m_height - currentTextBlockHeight) / 2);
830     }
831 }
832
833 void RenderTextControl::paint(PaintInfo& paintInfo, int tx, int ty)
834 {
835     RenderBlock::paint(paintInfo, tx, ty);
836     if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator)
837         theme()->paintCapsLockIndicator(this, paintInfo, absoluteContentBox());
838
839
840 void RenderTextControl::calcPrefWidths()
841 {
842     ASSERT(prefWidthsDirty());
843
844     m_minPrefWidth = 0;
845     m_maxPrefWidth = 0;
846
847     if (style()->width().isFixed() && style()->width().value() > 0)
848         m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
849     else {
850         // Figure out how big a text control needs to be for a given number of characters
851         // (using "0" as the nominal character).
852         const UChar ch = '0';
853         float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
854         int factor;
855         int scrollbarSize = 0;
856         if (m_multiLine) {
857             factor = static_cast<HTMLTextAreaElement*>(node())->cols();
858             // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
859             if (m_innerText->renderer()->style()->overflowY() != OHIDDEN)
860                 scrollbarSize = PlatformScrollbar::verticalScrollbarWidth();
861         } else {
862             factor = static_cast<HTMLInputElement*>(node())->size();
863             if (factor <= 0)
864                 factor = 20;
865         }
866         m_maxPrefWidth = static_cast<int>(ceilf(charWidth * factor)) + scrollbarSize +
867                          m_innerText->renderer()->paddingLeft() + m_innerText->renderer()->paddingRight();
868                 
869         if (m_resultsButton)
870             m_maxPrefWidth += m_resultsButton->renderer()->borderLeft() + m_resultsButton->renderer()->borderRight() +
871                               m_resultsButton->renderer()->paddingLeft() + m_resultsButton->renderer()->paddingRight();
872         if (m_cancelButton)
873             m_maxPrefWidth += m_cancelButton->renderer()->borderLeft() + m_cancelButton->renderer()->borderRight() +
874                               m_cancelButton->renderer()->paddingLeft() + m_cancelButton->renderer()->paddingRight();
875     }
876
877     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
878         m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
879         m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
880     } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
881         m_minPrefWidth = 0;
882     else
883         m_minPrefWidth = m_maxPrefWidth;
884
885     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
886         m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
887         m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
888     }
889
890     int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
891
892     m_minPrefWidth += toAdd;
893     m_maxPrefWidth += toAdd;
894
895     setPrefWidthsDirty(false);
896 }
897
898 void RenderTextControl::forwardEvent(Event* evt)
899 {
900     if (evt->type() == blurEvent) {
901         RenderObject* innerRenderer = m_innerText->renderer();
902         if (innerRenderer) {
903             RenderLayer* innerLayer = innerRenderer->layer();
904             if (innerLayer && !m_multiLine)
905                 innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);
906         }
907         updatePlaceholder();
908         capsLockStateMayHaveChanged();
909     } else if (evt->type() == focusEvent) {
910         updatePlaceholder();
911         capsLockStateMayHaveChanged();
912     } else {
913         if (evt->isMouseEvent() && m_resultsButton && static_cast<MouseEvent*>(evt)->x() < m_innerText->renderer()->absoluteBoundingBoxRect().x())
914             m_resultsButton->defaultEventHandler(evt);
915         else if (evt->isMouseEvent() && m_cancelButton && static_cast<MouseEvent*>(evt)->x() > m_innerText->renderer()->absoluteBoundingBoxRect().right())
916             m_cancelButton->defaultEventHandler(evt);
917         else
918             m_innerText->defaultEventHandler(evt);
919     }
920 }
921
922 void RenderTextControl::selectionChanged(bool userTriggered)
923 {
924     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
925     if (m_multiLine)
926         static_cast<HTMLTextAreaElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
927     else
928         static_cast<HTMLInputElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
929     if (Frame* frame = document()->frame())
930         if (frame->selectionController()->isRange() && userTriggered)
931             element->dispatchHTMLEvent(selectEvent, true, false);
932 }
933
934 void RenderTextControl::autoscroll()
935 {
936     RenderLayer* layer = m_innerText->renderer()->layer();
937     if (layer)
938         layer->autoscroll();
939 }
940
941 int RenderTextControl::scrollWidth() const
942 {
943     if (m_innerText)
944         return m_innerText->scrollWidth();
945     return RenderBlock::scrollWidth();
946 }
947
948 int RenderTextControl::scrollHeight() const
949 {
950     if (m_innerText)
951         return m_innerText->scrollHeight();
952     return RenderBlock::scrollHeight();
953 }
954
955 int RenderTextControl::scrollLeft() const
956 {
957     if (m_innerText)
958         return m_innerText->scrollLeft();
959     return RenderBlock::scrollLeft();
960 }
961
962 int RenderTextControl::scrollTop() const
963 {
964     if (m_innerText)
965         return m_innerText->scrollTop();
966     return RenderBlock::scrollTop();
967 }
968
969 void RenderTextControl::setScrollLeft(int newLeft)
970 {
971     if (m_innerText)
972         m_innerText->setScrollLeft(newLeft);
973 }
974
975 void RenderTextControl::setScrollTop(int newTop)
976 {
977     if (m_innerText)
978         m_innerText->setScrollTop(newTop);
979 }
980
981 const AtomicString& RenderTextControl::autosaveName() const
982 {
983     return static_cast<Element*>(node())->getAttribute(autosaveAttr);
984 }
985
986 void RenderTextControl::addSearchResult()
987 {
988     ASSERT(!m_multiLine);
989
990     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
991     if (input->maxResults() <= 0)
992         return;
993
994     String value = input->value();
995     if (value.isEmpty())
996         return;
997
998     Settings* settings = document()->settings();
999     if (!settings || settings->privateBrowsingEnabled())
1000         return;
1001
1002     int size = static_cast<int>(m_recentSearches.size());
1003     for (int i = size - 1; i >= 0; --i)
1004         if (m_recentSearches[i] == value)
1005             m_recentSearches.remove(i);
1006
1007     m_recentSearches.insert(0, value);
1008     while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
1009         m_recentSearches.removeLast();
1010
1011     const AtomicString& name = autosaveName();
1012     if (!m_searchPopup)
1013         m_searchPopup = SearchPopupMenu::create(this);
1014     m_searchPopup->saveRecentSearches(name, m_recentSearches);
1015 }
1016
1017 void RenderTextControl::showPopup()
1018 {
1019     if (m_searchPopupIsVisible)
1020         return;
1021
1022     if (!m_searchPopup)
1023         m_searchPopup = SearchPopupMenu::create(this);
1024
1025     if (!m_searchPopup->enabled())
1026         return;
1027     
1028     m_searchPopupIsVisible = true;
1029
1030     const AtomicString& name = autosaveName();
1031     m_searchPopup->loadRecentSearches(name, m_recentSearches);
1032
1033     // Trim the recent searches list if the maximum size has changed since we last saved.
1034     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
1035     if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
1036         do
1037             m_recentSearches.removeLast();
1038         while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
1039         m_searchPopup->saveRecentSearches(name, m_recentSearches);
1040     }
1041
1042     m_searchPopup->show(absoluteBoundingBoxRect(), document()->view(), -1);
1043 }
1044
1045 void RenderTextControl::hidePopup()
1046 {
1047     if (m_searchPopup)
1048         m_searchPopup->hide();
1049     m_searchPopupIsVisible = false;
1050 }
1051
1052 void RenderTextControl::valueChanged(unsigned listIndex, bool fireEvents)
1053 {
1054     ASSERT(static_cast<int>(listIndex) < listSize());
1055     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
1056     if (static_cast<int>(listIndex) == (listSize() - 1)) {
1057         if (fireEvents) {
1058             m_recentSearches.clear();
1059             const AtomicString& name = autosaveName();
1060             if (!name.isEmpty()) {
1061                 if (!m_searchPopup)
1062                     m_searchPopup = SearchPopupMenu::create(this);
1063                 m_searchPopup->saveRecentSearches(name, m_recentSearches);
1064             }
1065         }
1066     } else {
1067         input->setValue(itemText(listIndex));
1068         if (fireEvents)
1069             input->onSearch();
1070         input->select();
1071     }
1072 }
1073
1074 String RenderTextControl::itemText(unsigned listIndex) const
1075 {
1076     int size = listSize();
1077     if (size == 1) {
1078         ASSERT(!listIndex);
1079         return searchMenuNoRecentSearchesText();
1080     }
1081     if (!listIndex)
1082         return searchMenuRecentSearchesText();
1083     if (itemIsSeparator(listIndex))
1084         return String();
1085     if (static_cast<int>(listIndex) == (size - 1))
1086         return searchMenuClearRecentSearchesText();
1087     return m_recentSearches[listIndex - 1];
1088 }
1089
1090 bool RenderTextControl::itemIsEnabled(unsigned listIndex) const
1091 {
1092      if (!listIndex || itemIsSeparator(listIndex))
1093         return false;
1094     return true;
1095 }
1096
1097 RenderStyle* RenderTextControl::itemStyle(unsigned listIndex) const
1098 {
1099     return style();
1100 }
1101
1102 Color RenderTextControl::itemBackgroundColor(unsigned listIndex) const
1103 {
1104     return style()->backgroundColor();
1105 }
1106
1107 RenderStyle* RenderTextControl::clientStyle() const
1108 {
1109     return style();
1110 }
1111
1112 Document* RenderTextControl::clientDocument() const
1113 {
1114     return document();
1115 }
1116
1117 int RenderTextControl::clientInsetLeft() const
1118 {
1119     // Inset the menu by the radius of the cap on the left so that
1120     // it only runs along the straight part of the bezel.
1121     return height() / 2;
1122 }
1123
1124 int RenderTextControl::clientInsetRight() const
1125 {
1126     // Inset the menu by the radius of the cap on the right so that
1127     // it only runs along the straight part of the bezel (unless it needs
1128     // to be wider).
1129     return height() / 2;
1130 }
1131
1132 int RenderTextControl::clientPaddingLeft() const
1133 {
1134     return paddingLeft() + m_resultsButton->renderer()->width();
1135 }
1136
1137 int RenderTextControl::clientPaddingRight() const
1138 {
1139     return paddingRight() + m_cancelButton->renderer()->width();
1140 }
1141
1142 int RenderTextControl::listSize() const
1143 {
1144     // If there are no recent searches, then our menu will have 1 "No recent searches" item.
1145     if (!m_recentSearches.size())
1146         return 1;
1147     // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
1148     return m_recentSearches.size() + 3;
1149 }
1150
1151 int RenderTextControl::selectedIndex() const
1152 {
1153     return -1;
1154 }
1155
1156 bool RenderTextControl::itemIsSeparator(unsigned listIndex) const
1157 {
1158    // The separator will be the second to last item in our list.
1159    return static_cast<int>(listIndex) == (listSize() - 2);
1160 }
1161
1162 bool RenderTextControl::itemIsLabel(unsigned listIndex) const
1163 {
1164     return listIndex == 0;
1165 }
1166
1167 bool RenderTextControl::itemIsSelected(unsigned listIndex) const
1168 {
1169     return false;
1170 }
1171
1172 void RenderTextControl::setTextFromItem(unsigned listIndex)
1173 {
1174     static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
1175 }
1176
1177 bool RenderTextControl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
1178 {
1179     RenderLayer* layer = m_innerText->renderer()->layer();
1180     if (layer && layer->scroll(direction, granularity, multiplier))
1181         return true;
1182     return RenderObject::scroll(direction, granularity, multiplier);
1183 }
1184
1185 void RenderTextControl::searchEventTimerFired(Timer<RenderTextControl>*)
1186 {
1187     static_cast<HTMLInputElement*>(node())->onSearch();
1188 }
1189
1190 void RenderTextControl::stopSearchEventTimer()
1191 {
1192     m_searchEventTimer.stop();
1193 }
1194
1195 void RenderTextControl::startSearchEventTimer()
1196 {
1197     unsigned length = text().length();
1198
1199     // If there's no text, fire the event right away.
1200     if (!length) {
1201         m_searchEventTimer.stop();
1202         static_cast<HTMLInputElement*>(node())->onSearch();
1203         return;
1204     }
1205
1206     // After typing the first key, we wait 0.5 seconds.
1207     // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
1208     m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
1209 }
1210
1211 bool RenderTextControl::isScrollable() const
1212 {
1213     if (m_innerText && m_innerText->renderer()->isScrollable())
1214         return true;
1215     return RenderObject::isScrollable();
1216 }
1217
1218 FontSelector* RenderTextControl::fontSelector() const
1219 {
1220     return document()->styleSelector()->fontSelector();
1221 }
1222
1223 void RenderTextControl::capsLockStateMayHaveChanged()
1224 {
1225     // Only draw the caps lock indicator if these things are true:
1226     // 1) The field is a password field
1227     // 2) The frame is active
1228     // 3) The element is focused
1229     // 4) The caps lock is on
1230
1231     bool shouldDrawCapsLockIndicator = false;
1232     if (Node* n = node())
1233         if (Document* d = document())
1234             if (Frame* f = d->frame())
1235                 shouldDrawCapsLockIndicator = !m_multiLine && static_cast<HTMLInputElement*>(n)->inputType() == HTMLInputElement::PASSWORD && 
1236                                                f->selectionController()->isFocusedAndActive() && d->focusedNode() == n && PlatformKeyboardEvent::currentCapsLockState();
1237
1238     if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
1239         m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
1240         repaint();
1241     }
1242 }
1243
1244 } // namespace WebCore