f33bef292278cb341df6d04b83df3998b461005b
[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             ExceptionCode ec = 0;
401             m_innerText->setInnerText(value, ec);
402             if (value.endsWith("\n") || value.endsWith("\r"))
403                 m_innerText->appendChild(new HTMLBRElement(document()), ec);
404             if (Frame* frame = document()->frame())
405                 frame->editor()->clearUndoRedoOperations();
406             m_dirty = false;
407             m_userEdited = false;
408         }
409         element->setValueMatchesRenderer();
410     }
411
412     if (m_searchPopupIsVisible)
413         m_searchPopup->updateFromElement();
414 }
415
416 int RenderTextControl::selectionStart()
417 {
418     Frame* frame = document()->frame();
419     if (!frame)
420         return 0;
421     return indexForVisiblePosition(frame->selectionController()->start());
422 }
423
424 int RenderTextControl::selectionEnd()
425 {
426     Frame* frame = document()->frame();
427     if (!frame)
428         return 0;
429     return indexForVisiblePosition(frame->selectionController()->end());
430 }
431
432 void RenderTextControl::setSelectionStart(int start)
433 {
434     setSelectionRange(start, max(start, selectionEnd()));
435 }
436
437 void RenderTextControl::setSelectionEnd(int end)
438 {
439     setSelectionRange(min(end, selectionStart()), end);
440 }
441
442 void RenderTextControl::select()
443 {
444     setSelectionRange(0, text().length());
445 }
446
447 void RenderTextControl::setSelectionRange(int start, int end)
448 {
449     end = max(end, 0);
450     start = min(max(start, 0), end);
451
452     document()->updateLayout();
453
454     if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderer()->height()) {
455         if (m_multiLine)
456             static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
457         else
458             static_cast<HTMLInputElement*>(node())->cacheSelection(start, end);
459         return;
460     }
461     VisiblePosition startPosition = visiblePositionForIndex(start);
462     VisiblePosition endPosition;
463     if (start == end)
464         endPosition = startPosition;
465     else
466         endPosition = visiblePositionForIndex(end);
467
468     ASSERT(startPosition.isNotNull() && endPosition.isNotNull());
469     ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
470
471     Selection newSelection = Selection(startPosition, endPosition);
472
473     if (Frame* frame = document()->frame())
474         frame->selectionController()->setSelection(newSelection);
475
476     // FIXME: Granularity is stored separately on the frame, but also in the selection controller.
477     // The granularity in the selection controller should be used, and then this line of code would not be needed.
478     if (Frame* frame = document()->frame())
479         frame->setSelectionGranularity(CharacterGranularity);
480 }
481
482 Selection RenderTextControl::selection(int start, int end) const
483 {
484     return Selection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),
485                      VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));
486 }
487
488 VisiblePosition RenderTextControl::visiblePositionForIndex(int index)
489 {
490     if (index <= 0)
491         return VisiblePosition(m_innerText.get(), 0, DOWNSTREAM);
492     ExceptionCode ec = 0;
493     RefPtr<Range> range = new Range(document());
494     range->selectNodeContents(m_innerText.get(), ec);
495     CharacterIterator it(range.get());
496     it.advance(index - 1);
497     return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM);
498 }
499
500 int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
501 {
502     Position indexPosition = pos.deepEquivalent();
503     if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != m_innerText)
504         return 0;
505     ExceptionCode ec = 0;
506     RefPtr<Range> range = new Range(document());
507     range->setStart(m_innerText.get(), 0, ec);
508     range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
509     return TextIterator::rangeLength(range.get());
510 }
511
512 void RenderTextControl::updateCancelButtonVisibility(RenderStyle* style)
513 {
514     ASSERT(!m_multiLine);
515     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
516     if (input->value().isEmpty())
517         style->setVisibility(HIDDEN);
518     else
519         style->setVisibility(VISIBLE);
520 }
521
522 void RenderTextControl::subtreeHasChanged()
523 {
524     bool wasDirty = m_dirty;
525     m_dirty = true;
526     m_userEdited = true;
527     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
528     if (m_multiLine) {
529         element->setValueMatchesRenderer(false);
530         if (element->focused())
531             if (Frame* frame = document()->frame())
532                 frame->textDidChangeInTextArea(element);
533     } else {
534         HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
535         input->setValueFromRenderer(input->constrainValue(text()));
536         if (m_cancelButton)
537             updateCancelButtonVisibility(m_cancelButton->renderer()->style());
538
539         // If the incremental attribute is set, then dispatch the search event
540         if (!input->getAttribute(incrementalAttr).isNull())
541             startSearchEventTimer();
542
543         if (!wasDirty) {
544             if (input->focused())
545                 if (Frame* frame = document()->frame())
546                     frame->textFieldDidBeginEditing(input);
547         }
548         if (input->focused())
549             if (Frame* frame = document()->frame())
550                 frame->textDidChangeInTextField(input);
551     }
552 }
553
554 String RenderTextControl::finishText(Vector<UChar>& result) const
555 {
556     UChar symbol = backslashAsCurrencySymbol();
557     if (symbol != '\\') {
558         size_t size = result.size();
559         for (size_t i = 0; i < size; ++i)
560             if (result[i] == '\\')
561                 result[i] = symbol;
562     }
563
564     return String::adopt(result);
565 }
566
567 String RenderTextControl::text()
568 {
569     if (!m_innerText)
570         return "";
571  
572     Frame* frame = document()->frame();
573     Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
574
575     Vector<UChar> result;
576
577     for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
578         if (n->isTextNode()) {
579             Text* text = static_cast<Text*>(n);
580             String data = text->data();
581             unsigned length = data.length();
582             if (text != compositionNode)
583                 result.append(data.characters(), length);
584             else {
585                 unsigned compositionStart = min(frame->editor()->compositionStart(), length);
586                 unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
587                 result.append(data.characters(), compositionStart);
588                 result.append(data.characters() + compositionEnd, length - compositionEnd);
589             }
590         }
591     }
592
593     return finishText(result);
594 }
595
596 static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
597 {
598     RootInlineBox* next;
599     for (; line; line = next) {
600         next = line->nextRootBox();
601         if (next && !line->endsWithBreak()) {
602             ASSERT(line->lineBreakObj());
603             breakNode = line->lineBreakObj()->node();
604             breakOffset = line->lineBreakPos();
605             line = next;
606             return;
607         }
608     }
609     breakNode = 0;
610 }
611
612 String RenderTextControl::textWithHardLineBreaks()
613 {
614     if (!m_innerText)
615         return "";
616     Node* firstChild = m_innerText->firstChild();
617     if (!firstChild)
618         return "";
619
620     document()->updateLayout();
621
622     RenderObject* renderer = firstChild->renderer();
623     if (!renderer)
624         return "";
625
626     InlineBox* box = renderer->inlineBox(0, DOWNSTREAM);
627     if (!box)
628         return "";
629
630     Frame* frame = document()->frame();
631     Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
632
633     Node* breakNode;
634     unsigned breakOffset;
635     RootInlineBox* line = box->root();
636     getNextSoftBreak(line, breakNode, breakOffset);
637
638     Vector<UChar> result;
639
640     for (Node* n = firstChild; n; n = n->traverseNextNode(m_innerText.get())) {
641         if (n->hasTagName(brTag))
642             result.append(&newlineCharacter, 1);
643         else if (n->isTextNode()) {
644             Text* text = static_cast<Text*>(n);
645             String data = text->data();
646             unsigned length = data.length();
647             unsigned compositionStart = (text == compositionNode)
648                 ? min(frame->editor()->compositionStart(), length) : 0;
649             unsigned compositionEnd = (text == compositionNode)
650                 ? min(max(compositionStart, frame->editor()->compositionEnd()), length) : 0;
651             unsigned position = 0;
652             while (breakNode == n && breakOffset < compositionStart) {
653                 result.append(data.characters() + position, breakOffset - position);
654                 position = breakOffset;
655                 result.append(&newlineCharacter, 1);
656                 getNextSoftBreak(line, breakNode, breakOffset);
657             }
658             result.append(data.characters() + position, compositionStart - position);
659             position = compositionEnd;
660             while (breakNode == n && breakOffset <= length) {
661                 if (breakOffset > position) {
662                     result.append(data.characters() + position, breakOffset - position);
663                     position = breakOffset;
664                     result.append(&newlineCharacter, 1);
665                 }
666                 getNextSoftBreak(line, breakNode, breakOffset);
667             }
668             result.append(data.characters() + position, length - position);
669         }
670         while (breakNode == n)
671             getNextSoftBreak(line, breakNode, breakOffset);
672     }
673
674     return finishText(result);
675 }
676
677 void RenderTextControl::calcHeight()
678 {
679     int rows = 1;
680     if (m_multiLine)
681         rows = static_cast<HTMLTextAreaElement*>(node())->rows();
682
683     int line = m_innerText->renderer()->lineHeight(true, true);
684     int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
685
686     int innerToAdd = m_innerText->renderer()->borderTop() + m_innerText->renderer()->borderBottom() +
687                      m_innerText->renderer()->paddingTop() + m_innerText->renderer()->paddingBottom() +
688                      m_innerText->renderer()->marginTop() + m_innerText->renderer()->marginBottom();
689
690     if (m_resultsButton) {
691         static_cast<RenderBlock*>(m_resultsButton->renderer())->calcHeight();
692         innerToAdd = max(innerToAdd,
693                          m_resultsButton->renderer()->borderTop() + m_resultsButton->renderer()->borderBottom() +
694                          m_resultsButton->renderer()->paddingTop() + m_resultsButton->renderer()->paddingBottom() +
695                          m_resultsButton->renderer()->marginTop() + m_resultsButton->renderer()->marginBottom());
696         line = max(line, m_resultsButton->renderer()->height());
697     }
698     if (m_cancelButton) {
699         static_cast<RenderBlock*>(m_cancelButton->renderer())->calcHeight();
700         innerToAdd = max(innerToAdd,
701                          m_cancelButton->renderer()->borderTop() + m_cancelButton->renderer()->borderBottom() +
702                          m_cancelButton->renderer()->paddingTop() + m_cancelButton->renderer()->paddingBottom() +
703                          m_cancelButton->renderer()->marginTop() + m_cancelButton->renderer()->marginBottom());
704         line = max(line, m_cancelButton->renderer()->height());
705     }
706     toAdd += innerToAdd;
707
708     // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
709     int scrollbarSize = 0;
710     // We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
711     if (m_innerText->renderer()->style()->overflowX() == OSCROLL ||  (m_innerText->renderer()->style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap))
712         scrollbarSize = PlatformScrollbar::horizontalScrollbarHeight();
713
714     m_height = line * rows + toAdd + scrollbarSize;
715
716     RenderBlock::calcHeight();
717 }
718
719 short RenderTextControl::baselinePosition(bool b, bool isRootLineBox) const
720 {
721     if (m_multiLine)
722         return height() + marginTop() + marginBottom();
723     return RenderBlock::baselinePosition(b, isRootLineBox);
724 }
725
726 bool RenderTextControl::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
727 {
728     // 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
729     // was on the control but not on the inner element (see Radar 4617841).
730
731     // 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,
732     // and act as if we've hit the close block if we're to the right of the inner text block.
733
734     if (RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction) &&
735         (result.innerNode() == element() || result.innerNode() == m_innerBlock)) {
736         IntPoint localPoint = IntPoint(x - tx - m_x, y - ty - m_y);
737         if (m_innerBlock) {
738             int textLeft = tx + m_x + m_innerBlock->renderer()->xPos() + m_innerText->renderer()->xPos();
739             int textRight = textLeft + m_innerText->renderer()->width();
740             if (m_resultsButton && x < textLeft) {
741                 result.setInnerNode(m_resultsButton.get());
742                 result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_resultsButton->renderer()->xPos(),
743                                               localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_resultsButton->renderer()->yPos()));
744                 return true;
745             } 
746             if (m_cancelButton && x > textRight) {
747                 result.setInnerNode(m_cancelButton.get());
748                 result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_cancelButton->renderer()->xPos(),
749                                               localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_cancelButton->renderer()->yPos()));
750                 return true;
751             }
752         }
753         
754         // Hit the inner text block.
755         result.setInnerNode(m_innerText.get());
756         result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->xPos() : 0),
757                                       localPoint.y() - m_innerText->renderer()->yPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->yPos() : 0)));
758         
759         return true;
760     }
761
762     return false;
763 }
764
765 IntRect RenderTextControl::controlClipRect(int tx, int ty) const
766 {
767     IntRect clipRect = contentBox();
768     clipRect.move(tx, ty);
769     return clipRect;
770 }
771
772 void RenderTextControl::layout()
773 {
774     int oldHeight = m_height;
775     calcHeight();
776     bool relayoutChildren = oldHeight != m_height;
777
778     // Set the text block's height
779     int textBlockHeight = m_height - paddingTop() - paddingBottom() - borderTop() - borderBottom();
780     int currentTextBlockHeight = m_innerText->renderer()->height();
781     if (m_multiLine || m_innerBlock || currentTextBlockHeight > m_height) {
782         if (textBlockHeight != currentTextBlockHeight)
783             relayoutChildren = true;
784         m_innerText->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
785     }
786     if (m_innerBlock) {
787         if (textBlockHeight != m_innerBlock->renderer()->height())
788             relayoutChildren = true;
789         m_innerBlock->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
790     }
791
792     int oldWidth = m_width;
793     calcWidth();
794     if (oldWidth != m_width)
795         relayoutChildren = true;
796
797     int searchExtrasWidth = 0;
798     if (m_resultsButton) {
799         m_resultsButton->renderer()->calcWidth();
800         searchExtrasWidth += m_resultsButton->renderer()->width();
801     }
802     if (m_cancelButton) {
803         m_cancelButton->renderer()->calcWidth();
804         searchExtrasWidth += m_cancelButton->renderer()->width();
805     }
806
807     // Set the text block's width
808     int textBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight() -
809                          m_innerText->renderer()->paddingLeft() - m_innerText->renderer()->paddingRight() - searchExtrasWidth;
810     if (textBlockWidth != m_innerText->renderer()->width())
811         relayoutChildren = true;
812     m_innerText->renderer()->style()->setWidth(Length(textBlockWidth, Fixed));
813     if (m_innerBlock) {
814         int innerBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight();
815         if (innerBlockWidth != m_innerBlock->renderer()->width())
816             relayoutChildren = true;
817         m_innerBlock->renderer()->style()->setWidth(Length(innerBlockWidth, Fixed));
818     }
819
820     RenderBlock::layoutBlock(relayoutChildren);
821     
822     // For text fields, center the inner text vertically
823     // Don't do this for search fields, since we don't honor height for them
824     if (!m_multiLine) {
825         currentTextBlockHeight = m_innerText->renderer()->height();
826         if (!m_innerBlock && currentTextBlockHeight < m_height)
827             m_innerText->renderer()->setPos(m_innerText->renderer()->xPos(), (m_height - currentTextBlockHeight) / 2);
828     }
829 }
830
831 void RenderTextControl::paint(PaintInfo& paintInfo, int tx, int ty)
832 {
833     RenderBlock::paint(paintInfo, tx, ty);
834     if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator)
835         theme()->paintCapsLockIndicator(this, paintInfo, absoluteContentBox());
836
837
838 void RenderTextControl::calcPrefWidths()
839 {
840     ASSERT(prefWidthsDirty());
841
842     m_minPrefWidth = 0;
843     m_maxPrefWidth = 0;
844
845     if (style()->width().isFixed() && style()->width().value() > 0)
846         m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
847     else {
848         // Figure out how big a text control needs to be for a given number of characters
849         // (using "0" as the nominal character).
850         const UChar ch = '0';
851         float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
852         int factor;
853         int scrollbarSize = 0;
854         if (m_multiLine) {
855             factor = static_cast<HTMLTextAreaElement*>(node())->cols();
856             // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
857             if (m_innerText->renderer()->style()->overflowY() != OHIDDEN)
858                 scrollbarSize = PlatformScrollbar::verticalScrollbarWidth();
859         } else {
860             factor = static_cast<HTMLInputElement*>(node())->size();
861             if (factor <= 0)
862                 factor = 20;
863         }
864         m_maxPrefWidth = static_cast<int>(ceilf(charWidth * factor)) + scrollbarSize +
865                          m_innerText->renderer()->paddingLeft() + m_innerText->renderer()->paddingRight();
866                 
867         if (m_resultsButton)
868             m_maxPrefWidth += m_resultsButton->renderer()->borderLeft() + m_resultsButton->renderer()->borderRight() +
869                               m_resultsButton->renderer()->paddingLeft() + m_resultsButton->renderer()->paddingRight();
870         if (m_cancelButton)
871             m_maxPrefWidth += m_cancelButton->renderer()->borderLeft() + m_cancelButton->renderer()->borderRight() +
872                               m_cancelButton->renderer()->paddingLeft() + m_cancelButton->renderer()->paddingRight();
873     }
874
875     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
876         m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
877         m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
878     } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
879         m_minPrefWidth = 0;
880     else
881         m_minPrefWidth = m_maxPrefWidth;
882
883     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
884         m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
885         m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
886     }
887
888     int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
889
890     m_minPrefWidth += toAdd;
891     m_maxPrefWidth += toAdd;
892
893     setPrefWidthsDirty(false);
894 }
895
896 void RenderTextControl::forwardEvent(Event* evt)
897 {
898     if (evt->type() == blurEvent) {
899         RenderObject* innerRenderer = m_innerText->renderer();
900         if (innerRenderer) {
901             RenderLayer* innerLayer = innerRenderer->layer();
902             if (innerLayer && !m_multiLine)
903                 innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);
904         }
905         updatePlaceholder();
906         capsLockStateMayHaveChanged();
907     } else if (evt->type() == focusEvent) {
908         updatePlaceholder();
909         capsLockStateMayHaveChanged();
910     } else {
911         if (evt->isMouseEvent() && m_resultsButton && static_cast<MouseEvent*>(evt)->x() < m_innerText->renderer()->absoluteBoundingBoxRect().x())
912             m_resultsButton->defaultEventHandler(evt);
913         else if (evt->isMouseEvent() && m_cancelButton && static_cast<MouseEvent*>(evt)->x() > m_innerText->renderer()->absoluteBoundingBoxRect().right())
914             m_cancelButton->defaultEventHandler(evt);
915         else
916             m_innerText->defaultEventHandler(evt);
917     }
918 }
919
920 void RenderTextControl::selectionChanged(bool userTriggered)
921 {
922     HTMLGenericFormElement* element = static_cast<HTMLGenericFormElement*>(node());
923     if (m_multiLine)
924         static_cast<HTMLTextAreaElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
925     else
926         static_cast<HTMLInputElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
927     if (Frame* frame = document()->frame())
928         if (frame->selectionController()->isRange() && userTriggered)
929             element->dispatchHTMLEvent(selectEvent, true, false);
930 }
931
932 void RenderTextControl::autoscroll()
933 {
934     RenderLayer* layer = m_innerText->renderer()->layer();
935     if (layer)
936         layer->autoscroll();
937 }
938
939 int RenderTextControl::scrollWidth() const
940 {
941     if (m_innerText)
942         return m_innerText->scrollWidth();
943     return RenderBlock::scrollWidth();
944 }
945
946 int RenderTextControl::scrollHeight() const
947 {
948     if (m_innerText)
949         return m_innerText->scrollHeight();
950     return RenderBlock::scrollHeight();
951 }
952
953 int RenderTextControl::scrollLeft() const
954 {
955     if (m_innerText)
956         return m_innerText->scrollLeft();
957     return RenderBlock::scrollLeft();
958 }
959
960 int RenderTextControl::scrollTop() const
961 {
962     if (m_innerText)
963         return m_innerText->scrollTop();
964     return RenderBlock::scrollTop();
965 }
966
967 void RenderTextControl::setScrollLeft(int newLeft)
968 {
969     if (m_innerText)
970         m_innerText->setScrollLeft(newLeft);
971 }
972
973 void RenderTextControl::setScrollTop(int newTop)
974 {
975     if (m_innerText)
976         m_innerText->setScrollTop(newTop);
977 }
978
979 const AtomicString& RenderTextControl::autosaveName() const
980 {
981     return static_cast<Element*>(node())->getAttribute(autosaveAttr);
982 }
983
984 void RenderTextControl::addSearchResult()
985 {
986     ASSERT(!m_multiLine);
987
988     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
989     if (input->maxResults() <= 0)
990         return;
991
992     String value = input->value();
993     if (value.isEmpty())
994         return;
995
996     Settings* settings = document()->settings();
997     if (!settings || settings->privateBrowsingEnabled())
998         return;
999
1000     int size = static_cast<int>(m_recentSearches.size());
1001     for (int i = size - 1; i >= 0; --i)
1002         if (m_recentSearches[i] == value)
1003             m_recentSearches.remove(i);
1004
1005     m_recentSearches.insert(0, value);
1006     while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
1007         m_recentSearches.removeLast();
1008
1009     const AtomicString& name = autosaveName();
1010     if (!m_searchPopup)
1011         m_searchPopup = SearchPopupMenu::create(this);
1012     m_searchPopup->saveRecentSearches(name, m_recentSearches);
1013 }
1014
1015 void RenderTextControl::showPopup()
1016 {
1017     if (m_searchPopupIsVisible)
1018         return;
1019
1020     if (!m_searchPopup)
1021         m_searchPopup = SearchPopupMenu::create(this);
1022
1023     if (!m_searchPopup->enabled())
1024         return;
1025     
1026     m_searchPopupIsVisible = true;
1027
1028     const AtomicString& name = autosaveName();
1029     m_searchPopup->loadRecentSearches(name, m_recentSearches);
1030
1031     // Trim the recent searches list if the maximum size has changed since we last saved.
1032     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
1033     if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
1034         do
1035             m_recentSearches.removeLast();
1036         while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
1037         m_searchPopup->saveRecentSearches(name, m_recentSearches);
1038     }
1039
1040     m_searchPopup->show(absoluteBoundingBoxRect(), document()->view(), -1);
1041 }
1042
1043 void RenderTextControl::hidePopup()
1044 {
1045     if (m_searchPopup)
1046         m_searchPopup->hide();
1047     m_searchPopupIsVisible = false;
1048 }
1049
1050 void RenderTextControl::valueChanged(unsigned listIndex, bool fireEvents)
1051 {
1052     ASSERT(static_cast<int>(listIndex) < listSize());
1053     HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
1054     if (static_cast<int>(listIndex) == (listSize() - 1)) {
1055         if (fireEvents) {
1056             m_recentSearches.clear();
1057             const AtomicString& name = autosaveName();
1058             if (!name.isEmpty()) {
1059                 if (!m_searchPopup)
1060                     m_searchPopup = SearchPopupMenu::create(this);
1061                 m_searchPopup->saveRecentSearches(name, m_recentSearches);
1062             }
1063         }
1064     } else {
1065         input->setValue(itemText(listIndex));
1066         if (fireEvents)
1067             input->onSearch();
1068         input->select();
1069     }
1070 }
1071
1072 String RenderTextControl::itemText(unsigned listIndex) const
1073 {
1074     int size = listSize();
1075     if (size == 1) {
1076         ASSERT(!listIndex);
1077         return searchMenuNoRecentSearchesText();
1078     }
1079     if (!listIndex)
1080         return searchMenuRecentSearchesText();
1081     if (itemIsSeparator(listIndex))
1082         return String();
1083     if (static_cast<int>(listIndex) == (size - 1))
1084         return searchMenuClearRecentSearchesText();
1085     return m_recentSearches[listIndex - 1];
1086 }
1087
1088 bool RenderTextControl::itemIsEnabled(unsigned listIndex) const
1089 {
1090      if (!listIndex || itemIsSeparator(listIndex))
1091         return false;
1092     return true;
1093 }
1094
1095 RenderStyle* RenderTextControl::itemStyle(unsigned listIndex) const
1096 {
1097     return style();
1098 }
1099
1100 Color RenderTextControl::itemBackgroundColor(unsigned listIndex) const
1101 {
1102     return style()->backgroundColor();
1103 }
1104
1105 RenderStyle* RenderTextControl::clientStyle() const
1106 {
1107     return style();
1108 }
1109
1110 Document* RenderTextControl::clientDocument() const
1111 {
1112     return document();
1113 }
1114
1115 int RenderTextControl::clientInsetLeft() const
1116 {
1117     // Inset the menu by the radius of the cap on the left so that
1118     // it only runs along the straight part of the bezel.
1119     return height() / 2;
1120 }
1121
1122 int RenderTextControl::clientInsetRight() const
1123 {
1124     // Inset the menu by the radius of the cap on the right so that
1125     // it only runs along the straight part of the bezel (unless it needs
1126     // to be wider).
1127     return height() / 2;
1128 }
1129
1130 int RenderTextControl::clientPaddingLeft() const
1131 {
1132     return paddingLeft() + m_resultsButton->renderer()->width();
1133 }
1134
1135 int RenderTextControl::clientPaddingRight() const
1136 {
1137     return paddingRight() + m_cancelButton->renderer()->width();
1138 }
1139
1140 int RenderTextControl::listSize() const
1141 {
1142     // If there are no recent searches, then our menu will have 1 "No recent searches" item.
1143     if (!m_recentSearches.size())
1144         return 1;
1145     // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
1146     return m_recentSearches.size() + 3;
1147 }
1148
1149 int RenderTextControl::selectedIndex() const
1150 {
1151     return -1;
1152 }
1153
1154 bool RenderTextControl::itemIsSeparator(unsigned listIndex) const
1155 {
1156    // The separator will be the second to last item in our list.
1157    return static_cast<int>(listIndex) == (listSize() - 2);
1158 }
1159
1160 bool RenderTextControl::itemIsLabel(unsigned listIndex) const
1161 {
1162     return listIndex == 0;
1163 }
1164
1165 bool RenderTextControl::itemIsSelected(unsigned listIndex) const
1166 {
1167     return false;
1168 }
1169
1170 void RenderTextControl::setTextFromItem(unsigned listIndex)
1171 {
1172     static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
1173 }
1174
1175 bool RenderTextControl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
1176 {
1177     RenderLayer* layer = m_innerText->renderer()->layer();
1178     if (layer && layer->scroll(direction, granularity, multiplier))
1179         return true;
1180     return RenderObject::scroll(direction, granularity, multiplier);
1181 }
1182
1183 void RenderTextControl::searchEventTimerFired(Timer<RenderTextControl>*)
1184 {
1185     static_cast<HTMLInputElement*>(node())->onSearch();
1186 }
1187
1188 void RenderTextControl::stopSearchEventTimer()
1189 {
1190     m_searchEventTimer.stop();
1191 }
1192
1193 void RenderTextControl::startSearchEventTimer()
1194 {
1195     unsigned length = text().length();
1196
1197     // If there's no text, fire the event right away.
1198     if (!length) {
1199         m_searchEventTimer.stop();
1200         static_cast<HTMLInputElement*>(node())->onSearch();
1201         return;
1202     }
1203
1204     // After typing the first key, we wait 0.5 seconds.
1205     // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
1206     m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
1207 }
1208
1209 bool RenderTextControl::isScrollable() const
1210 {
1211     if (m_innerText && m_innerText->renderer()->isScrollable())
1212         return true;
1213     return RenderObject::isScrollable();
1214 }
1215
1216 FontSelector* RenderTextControl::fontSelector() const
1217 {
1218     return document()->styleSelector()->fontSelector();
1219 }
1220
1221 void RenderTextControl::capsLockStateMayHaveChanged()
1222 {
1223     // Only draw the caps lock indicator if these things are true:
1224     // 1) The field is a password field
1225     // 2) The frame is active
1226     // 3) The element is focused
1227     // 4) The caps lock is on
1228
1229     bool shouldDrawCapsLockIndicator = false;
1230     if (Node* n = node())
1231         if (Document* d = document())
1232             if (Frame* f = d->frame())
1233                 shouldDrawCapsLockIndicator = !m_multiLine && static_cast<HTMLInputElement*>(n)->inputType() == HTMLInputElement::PASSWORD && 
1234                                                f->selectionController()->isFocusedAndActive() && d->focusedNode() == n && PlatformKeyboardEvent::currentCapsLockState();
1235
1236     if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
1237         m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
1238         repaint();
1239     }
1240 }
1241
1242 } // namespace WebCore