Rubber stamped by Mitz
[WebKit-https.git] / WebCore / html / HTMLInputElement.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "HTMLInputElement.h"
28
29 #include "BeforeTextInsertedEvent.h"
30 #include "CSSPropertyNames.h"
31 #include "Document.h"
32 #include "Editor.h"
33 #include "Event.h"
34 #include "EventHandler.h"
35 #include "EventNames.h"
36 #include "FocusController.h"
37 #include "FormDataList.h"
38 #include "Frame.h"
39 #include "HTMLFormElement.h"
40 #include "HTMLImageLoader.h"
41 #include "HTMLNames.h"
42 #include "KeyboardEvent.h"
43 #include "LocalizedStrings.h"
44 #include "MouseEvent.h"
45 #include "Page.h"
46 #include "RenderButton.h"
47 #include "RenderFileUploadControl.h"
48 #include "RenderImage.h"
49 #include "RenderText.h"
50 #include "RenderTextControl.h"
51 #include "RenderTheme.h"
52 #include "RenderSlider.h"
53 #include "SelectionController.h"
54 #include "TextBreakIterator.h"
55 #include "TextEvent.h"
56
57 using namespace std;
58
59 namespace WebCore {
60
61 using namespace EventNames;
62 using namespace HTMLNames;
63
64 const int maxSavedResults = 256;
65
66 static int numGraphemeClusters(const StringImpl* s)
67 {
68     if (!s)
69         return 0;
70
71     TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
72     if (!it)
73         return 0;
74     int num = 0;
75     while (textBreakNext(it) != TextBreakDone)
76         ++num;
77     return num;
78 }
79
80 static int numCharactersInGraphemeClusters(const StringImpl* s, int numGraphemeClusters)
81 {
82     if (!s)
83         return 0;
84
85     TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
86     if (!it)
87         return 0;
88     for (int i = 0; i < numGraphemeClusters; ++i)
89         if (textBreakNext(it) == TextBreakDone)
90             return s->length();
91     return textBreakCurrent(it);
92 }
93
94 HTMLInputElement::HTMLInputElement(Document *doc, HTMLFormElement *f)
95     : HTMLGenericFormElement(inputTag, doc, f)
96 {
97     init();
98 }
99
100 HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document *doc, HTMLFormElement *f)
101     : HTMLGenericFormElement(tagName, doc, f)
102 {
103     init();
104 }
105
106 void HTMLInputElement::init()
107 {
108     m_imageLoader = 0;
109     m_type = TEXT;
110     m_maxLen = 1024;
111     m_size = 20;
112     m_checked = false;
113     m_defaultChecked = false;
114     m_useDefaultChecked = true;
115     m_indeterminate = false;
116
117     m_haveType = false;
118     m_activeSubmit = false;
119     m_autocomplete = true;
120     m_inited = false;
121     m_autofilled = false;
122
123     xPos = 0;
124     yPos = 0;
125     
126     cachedSelStart = -1;
127     cachedSelEnd = -1;
128
129     m_maxResults = -1;
130
131     if (form())
132         m_autocomplete = form()->autoComplete();
133
134     document()->registerFormElementWithState(this);
135 }
136
137 HTMLInputElement::~HTMLInputElement()
138 {
139     document()->unregisterFormElementWithState(this);
140     document()->unregisterForDidRestoreFromCacheCallback(this);
141     delete m_imageLoader;
142 }
143
144 const AtomicString& HTMLInputElement::name() const
145 {
146     return m_name.isNull() ? emptyAtom : m_name;
147 }
148
149 bool HTMLInputElement::isKeyboardFocusable(KeyboardEvent* event) const
150 {
151     // If text fields can be focused, then they should always be keyboard focusable
152     if (isTextField())
153         return HTMLGenericFormElement::isFocusable();
154         
155     // If the base class says we can't be focused, then we can stop now.
156     if (!HTMLGenericFormElement::isKeyboardFocusable(event))
157         return false;
158
159     if (inputType() == RADIO) {
160         // Unnamed radio buttons are never focusable (matches WinIE).
161         if (name().isEmpty())
162             return false;
163
164         // Never allow keyboard tabbing to leave you in the same radio group.  Always
165         // skip any other elements in the group.
166         Node* currentFocusedNode = document()->focusedNode();
167         if (currentFocusedNode && currentFocusedNode->hasTagName(inputTag)) {
168             HTMLInputElement* focusedInput = static_cast<HTMLInputElement*>(currentFocusedNode);
169             if (focusedInput->inputType() == RADIO && focusedInput->form() == form() &&
170                 focusedInput->name() == name())
171                 return false;
172         }
173         
174         // Allow keyboard focus if we're checked or if nothing in the group is checked.
175         return checked() || !document()->checkedRadioButtonForGroup(name().impl(), form());
176     }
177     
178     return true;
179 }
180
181 bool HTMLInputElement::isMouseFocusable() const
182 {
183     if (isTextField())
184         return HTMLGenericFormElement::isFocusable();
185     return HTMLGenericFormElement::isMouseFocusable();
186 }
187
188 void HTMLInputElement::focus(bool restorePreviousSelection)
189 {
190     if (isTextField()) {
191         Document* doc = document();
192         if (doc->focusedNode() == this)
193             return;
194         doc->updateLayout();
195         if (!supportsFocus())
196             return;
197         if (Page* page = doc->page())
198             page->focusController()->setFocusedNode(this);
199         // FIXME: Should isFocusable do the updateLayout?
200         if (!isFocusable()) {
201             setNeedsFocusAppearanceUpdate(true);
202             return;
203         }
204         updateFocusAppearance(restorePreviousSelection);
205         return;
206     }
207     HTMLGenericFormElement::focus(restorePreviousSelection);
208 }
209
210 void HTMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
211 {        
212     if (isTextField()) {
213         if (!restorePreviousSelection || cachedSelStart == -1)
214             select();
215         else
216             // Restore the cached selection.
217             setSelectionRange(cachedSelStart, cachedSelEnd); 
218         
219         if (document() && document()->frame())
220             document()->frame()->revealSelection();
221     } else
222         HTMLGenericFormElement::updateFocusAppearance();
223 }
224
225 void HTMLInputElement::aboutToUnload()
226 {
227     if (isTextField() && focused() && document()->frame())
228         document()->frame()->textFieldDidEndEditing(this);
229 }
230
231 void HTMLInputElement::dispatchFocusEvent()
232 {
233     if (isTextField()) {
234         setAutofilled(false);
235         if (inputType() == PASSWORD && document()->frame())
236             document()->setUseSecureKeyboardEntryWhenActive(true);
237     }
238     HTMLGenericFormElement::dispatchFocusEvent();
239 }
240
241 void HTMLInputElement::dispatchBlurEvent()
242 {
243     if (isTextField() && document()->frame()) {
244         if (inputType() == PASSWORD)
245             document()->setUseSecureKeyboardEntryWhenActive(false);
246         document()->frame()->textFieldDidEndEditing(this);
247     }
248     HTMLGenericFormElement::dispatchBlurEvent();
249 }
250
251 void HTMLInputElement::setType(const String& t)
252 {
253     if (t.isEmpty()) {
254         int exccode;
255         removeAttribute(typeAttr, exccode);
256     } else
257         setAttribute(typeAttr, t);
258 }
259
260 void HTMLInputElement::setInputType(const String& t)
261 {
262     InputType newType;
263     
264     if (equalIgnoringCase(t, "password"))
265         newType = PASSWORD;
266     else if (equalIgnoringCase(t, "checkbox"))
267         newType = CHECKBOX;
268     else if (equalIgnoringCase(t, "radio"))
269         newType = RADIO;
270     else if (equalIgnoringCase(t, "submit"))
271         newType = SUBMIT;
272     else if (equalIgnoringCase(t, "reset"))
273         newType = RESET;
274     else if (equalIgnoringCase(t, "file"))
275         newType = FILE;
276     else if (equalIgnoringCase(t, "hidden"))
277         newType = HIDDEN;
278     else if (equalIgnoringCase(t, "image"))
279         newType = IMAGE;
280     else if (equalIgnoringCase(t, "button"))
281         newType = BUTTON;
282     else if (equalIgnoringCase(t, "khtml_isindex"))
283         newType = ISINDEX;
284     else if (equalIgnoringCase(t, "search"))
285         newType = SEARCH;
286     else if (equalIgnoringCase(t, "range"))
287         newType = RANGE;
288     else
289         newType = TEXT;
290
291     // IMPORTANT: Don't allow the type to be changed to FILE after the first
292     // type change, otherwise a JavaScript programmer would be able to set a text
293     // field's value to something like /etc/passwd and then change it to a file field.
294     if (inputType() != newType) {
295         if (newType == FILE && m_haveType)
296             // Set the attribute back to the old value.
297             // Useful in case we were called from inside parseMappedAttribute.
298             setAttribute(typeAttr, type());
299         else {
300             if (inputType() == RADIO && !name().isEmpty())
301                 if (document()->checkedRadioButtonForGroup(name().impl(), form()) == this)
302                     document()->removeRadioButtonGroup(name().impl(), form());
303
304             bool wasAttached = m_attached;
305             if (wasAttached)
306                 detach();
307
308             bool didStoreValue = storesValueSeparateFromAttribute();
309             bool wasPasswordField = inputType() == PASSWORD;
310             bool didRespectHeightAndWidth = respectHeightAndWidthAttrs();
311             m_type = newType;
312             bool willStoreValue = storesValueSeparateFromAttribute();
313             bool isPasswordField = inputType() == PASSWORD;
314             bool willRespectHeightAndWidth = respectHeightAndWidthAttrs();
315
316             if (didStoreValue && !willStoreValue && !m_value.isNull()) {
317                 setAttribute(valueAttr, m_value);
318                 m_value = String();
319             }
320             if (!didStoreValue && willStoreValue)
321                 m_value = constrainValue(getAttribute(valueAttr));
322             else
323                 recheckValue();
324
325             if (wasPasswordField && !isPasswordField) {
326                 document()->registerFormElementWithState(this);
327                 document()->unregisterForDidRestoreFromCacheCallback(this);
328             } else if (!wasPasswordField && isPasswordField) {
329                 document()->unregisterFormElementWithState(this);
330                 document()->registerForDidRestoreFromCacheCallback(this);
331             }
332
333             if (didRespectHeightAndWidth != willRespectHeightAndWidth) {
334                 NamedMappedAttrMap* map = mappedAttributes();
335                 if (MappedAttribute* height = map->getAttributeItem(heightAttr))
336                     attributeChanged(height, false);
337                 if (MappedAttribute* width = map->getAttributeItem(widthAttr))
338                     attributeChanged(width, false);
339                 if (MappedAttribute* align = map->getAttributeItem(alignAttr))
340                     attributeChanged(align, false);
341             }
342
343             if (wasAttached)
344                 attach();
345
346             // If our type morphs into a radio button and we are checked, then go ahead
347             // and signal this to the form.
348             if (inputType() == RADIO && checked())
349                 document()->radioButtonChecked(this, form());
350         }
351     }
352     m_haveType = true;
353
354     if (inputType() != IMAGE && m_imageLoader) {
355         delete m_imageLoader;
356         m_imageLoader = 0;
357     }
358 }
359
360 const AtomicString& HTMLInputElement::type() const
361 {
362     // needs to be lowercase according to DOM spec
363     switch (inputType()) {
364         case BUTTON: {
365             static const AtomicString button("button");
366             return button;
367         }
368         case CHECKBOX: {
369             static const AtomicString checkbox("checkbox");
370             return checkbox;
371         }
372         case FILE: {
373             static const AtomicString file("file");
374             return file;
375         }
376         case HIDDEN: {
377             static const AtomicString hidden("hidden");
378             return hidden;
379         }
380         case IMAGE: {
381             static const AtomicString image("image");
382             return image;
383         }
384         case ISINDEX:
385             return emptyAtom;
386         case PASSWORD: {
387             static const AtomicString password("password");
388             return password;
389         }
390         case RADIO: {
391             static const AtomicString radio("radio");
392             return radio;
393         }
394         case RANGE: {
395             static const AtomicString range("range");
396             return range;
397         }
398         case RESET: {
399             static const AtomicString reset("reset");
400             return reset;
401         }
402         case SEARCH: {
403             static const AtomicString search("search");
404             return search;
405         }
406         case SUBMIT: {
407             static const AtomicString submit("submit");
408             return submit;
409         }
410         case TEXT: {
411             static const AtomicString text("text");
412             return text;
413         }
414     }
415     return emptyAtom;
416 }
417
418 String HTMLInputElement::stateValue() const
419 {
420     ASSERT(inputType() != PASSWORD); // should never save/restore password fields
421     switch (inputType()) {
422         case BUTTON:
423         case FILE:
424         case HIDDEN:
425         case IMAGE:
426         case ISINDEX:
427         case RANGE:
428         case RESET:
429         case SEARCH:
430         case SUBMIT:
431         case TEXT:
432             return value();
433         case CHECKBOX:
434         case RADIO:
435             return checked() ? "on" : "off";
436         case PASSWORD:
437             break;
438     }
439     return String();
440 }
441
442 void HTMLInputElement::restoreState(const String& state)
443 {
444     ASSERT(inputType() != PASSWORD); // should never save/restore password fields
445     switch (inputType()) {
446         case BUTTON:
447         case FILE:
448         case HIDDEN:
449         case IMAGE:
450         case ISINDEX:
451         case RANGE:
452         case RESET:
453         case SEARCH:
454         case SUBMIT:
455         case TEXT:
456             setValue(state);
457             break;
458         case CHECKBOX:
459         case RADIO:
460             setChecked(state == "on");
461             break;
462         case PASSWORD:
463             break;
464     }
465 }
466
467 void HTMLInputElement::closeRenderer()
468 {
469     m_originalValue = value();
470     HTMLGenericFormElement::closeRenderer();
471 }
472
473 bool HTMLInputElement::canHaveSelection() const
474 {
475     return isTextField();
476 }
477
478 int HTMLInputElement::selectionStart() const
479 {
480     if (!isTextField())
481         return 0;
482     if (document()->focusedNode() != this && cachedSelStart != -1)
483         return cachedSelStart;
484     if (!renderer())
485         return 0;
486     return static_cast<RenderTextControl*>(renderer())->selectionStart();
487 }
488
489 int HTMLInputElement::selectionEnd() const
490 {
491     if (!isTextField())
492         return 0;
493     if (document()->focusedNode() != this && cachedSelEnd != -1)
494         return cachedSelEnd;
495     if (!renderer())
496         return 0;
497     return static_cast<RenderTextControl*>(renderer())->selectionEnd();
498 }
499
500 void HTMLInputElement::setSelectionStart(int start)
501 {
502     if (!isTextField())
503         return;
504     if (!renderer())
505         return;
506     static_cast<RenderTextControl*>(renderer())->setSelectionStart(start);
507 }
508
509 void HTMLInputElement::setSelectionEnd(int end)
510 {
511     if (!isTextField())
512         return;
513     if (!renderer())
514         return;
515     static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end);
516 }
517
518 void HTMLInputElement::select()
519 {
520     if (!isTextField())
521         return;
522     if (!renderer())
523         return;
524     static_cast<RenderTextControl*>(renderer())->select();
525 }
526
527 void HTMLInputElement::setSelectionRange(int start, int end)
528 {
529     if (!isTextField())
530         return;
531     if (!renderer())
532         return;
533     static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end);
534 }
535
536 void HTMLInputElement::accessKeyAction(bool sendToAnyElement)
537 {
538     switch (inputType()) {
539         case BUTTON:
540         case CHECKBOX:
541         case FILE:
542         case IMAGE:
543         case RADIO:
544         case RANGE:
545         case RESET:
546         case SUBMIT:
547             focus(false);
548             // send the mouse button events iff the caller specified sendToAnyElement
549             dispatchSimulatedClick(0, sendToAnyElement);
550             break;
551         case HIDDEN:
552             // a no-op for this type
553             break;
554         case ISINDEX:
555         case PASSWORD:
556         case SEARCH:
557         case TEXT:
558             // should never restore previous selection here
559             focus(false);
560             break;
561     }
562 }
563
564 bool HTMLInputElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const
565 {
566     if (((attrName == heightAttr || attrName == widthAttr) && respectHeightAndWidthAttrs()) ||
567         attrName == vspaceAttr ||
568         attrName == hspaceAttr) {
569         result = eUniversal;
570         return false;
571     } 
572
573     if (attrName == alignAttr) {
574         if (inputType() == IMAGE) {
575             // Share with <img> since the alignment behavior is the same.
576             result = eReplaced;
577             return false;
578         }
579     }
580
581     return HTMLElement::mapToEntry(attrName, result);
582 }
583
584 void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
585 {
586     if (attr->name() == nameAttr) {
587         if (inputType() == RADIO && checked()) {
588             // Remove the radio from its old group.
589             if (!m_name.isEmpty())
590                 document()->removeRadioButtonGroup(m_name.impl(), form());
591         }
592         
593         // Update our cached reference to the name.
594         m_name = attr->value();
595         
596         if (inputType() == RADIO) {
597             // Add the button to its new group.
598             if (checked())
599                 document()->radioButtonChecked(this, form());
600         }
601     } else if (attr->name() == autocompleteAttr) {
602         m_autocomplete = !equalIgnoringCase(attr->value(), "off");
603     } else if (attr->name() == typeAttr) {
604         setInputType(attr->value());
605     } else if (attr->name() == valueAttr) {
606         // We only need to setChanged if the form is looking at the default value right now.
607         if (m_value.isNull())
608             setChanged();
609         setValueMatchesRenderer(false);
610     } else if (attr->name() == checkedAttr) {
611         m_defaultChecked = !attr->isNull();
612         if (m_useDefaultChecked) {
613             setChecked(m_defaultChecked);
614             m_useDefaultChecked = true;
615         }
616     } else if (attr->name() == maxlengthAttr) {
617         int oldMaxLen = m_maxLen;
618         m_maxLen = !attr->isNull() ? attr->value().toInt() : 1024;
619         if (m_maxLen <= 0 || m_maxLen > 1024)
620             m_maxLen = 1024;
621         if (oldMaxLen != m_maxLen)
622             recheckValue();
623         setChanged();
624     } else if (attr->name() == sizeAttr) {
625         m_size = !attr->isNull() ? attr->value().toInt() : 20;
626     } else if (attr->name() == altAttr) {
627         if (renderer() && inputType() == IMAGE)
628             static_cast<RenderImage*>(renderer())->updateAltText();
629     } else if (attr->name() == srcAttr) {
630         if (renderer() && inputType() == IMAGE) {
631             if (!m_imageLoader)
632                 m_imageLoader = new HTMLImageLoader(this);
633             m_imageLoader->updateFromElement();
634         }
635     } else if (attr->name() == usemapAttr ||
636                attr->name() == accesskeyAttr) {
637         // FIXME: ignore for the moment
638     } else if (attr->name() == vspaceAttr) {
639         addCSSLength(attr, CSS_PROP_MARGIN_TOP, attr->value());
640         addCSSLength(attr, CSS_PROP_MARGIN_BOTTOM, attr->value());
641     } else if (attr->name() == hspaceAttr) {
642         addCSSLength(attr, CSS_PROP_MARGIN_LEFT, attr->value());
643         addCSSLength(attr, CSS_PROP_MARGIN_RIGHT, attr->value());
644     } else if (attr->name() == alignAttr) {
645         if (inputType() == IMAGE)
646             addHTMLAlignment(attr);
647     } else if (attr->name() == widthAttr) {
648         if (respectHeightAndWidthAttrs())
649             addCSSLength(attr, CSS_PROP_WIDTH, attr->value());
650     } else if (attr->name() == heightAttr) {
651         if (respectHeightAndWidthAttrs())
652             addCSSLength(attr, CSS_PROP_HEIGHT, attr->value());
653     } else if (attr->name() == onfocusAttr) {
654         setHTMLEventListener(focusEvent, attr);
655     } else if (attr->name() == onblurAttr) {
656         setHTMLEventListener(blurEvent, attr);
657     } else if (attr->name() == onselectAttr) {
658         setHTMLEventListener(selectEvent, attr);
659     } else if (attr->name() == onchangeAttr) {
660         setHTMLEventListener(changeEvent, attr);
661     } else if (attr->name() == oninputAttr) {
662         setHTMLEventListener(inputEvent, attr);
663     }
664     // Search field and slider attributes all just cause updateFromElement to be called through style
665     // recalcing.
666     else if (attr->name() == onsearchAttr) {
667         setHTMLEventListener(searchEvent, attr);
668     } else if (attr->name() == resultsAttr) {
669         int oldResults = m_maxResults;
670         m_maxResults = !attr->isNull() ? min(attr->value().toInt(), maxSavedResults) : -1;
671         // FIXME: Detaching just for maxResults change is not ideal.  We should figure out the right
672         // time to relayout for this change.
673         if (m_maxResults != oldResults && (m_maxResults <= 0 || oldResults <= 0) && attached()) {
674             detach();
675             attach();
676         }
677         setChanged();
678     } else if (attr->name() == autosaveAttr ||
679                attr->name() == incrementalAttr ||
680                attr->name() == placeholderAttr ||
681                attr->name() == minAttr ||
682                attr->name() == maxAttr ||
683                attr->name() == precisionAttr) {
684         setChanged();
685     } else
686         HTMLGenericFormElement::parseMappedAttribute(attr);
687 }
688
689 bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
690 {
691     switch (inputType()) {
692         case BUTTON:
693         case CHECKBOX:
694         case FILE:
695         case IMAGE:
696         case ISINDEX:
697         case PASSWORD:
698         case RADIO:
699         case RANGE:
700         case RESET:
701         case SEARCH:
702         case SUBMIT:
703         case TEXT:
704             return HTMLGenericFormElement::rendererIsNeeded(style);
705         case HIDDEN:
706             return false;
707     }
708     ASSERT(false);
709     return false;
710 }
711
712 RenderObject *HTMLInputElement::createRenderer(RenderArena *arena, RenderStyle *style)
713 {
714     switch (inputType()) {
715         case BUTTON:
716         case RESET:
717         case SUBMIT:
718             return new (arena) RenderButton(this);
719         case CHECKBOX:
720         case RADIO:
721             return RenderObject::createObject(this, style);
722         case FILE:
723             return new (arena) RenderFileUploadControl(this);
724         case HIDDEN:
725             break;
726         case IMAGE:
727             return new (arena) RenderImage(this);
728         case RANGE:
729             return new (arena) RenderSlider(this);
730         case ISINDEX:
731         case PASSWORD:
732         case SEARCH:
733         case TEXT:
734             return new (arena) RenderTextControl(this, false);             
735     }
736     ASSERT(false);
737     return 0;
738 }
739
740 void HTMLInputElement::attach()
741 {
742     if (!m_inited) {
743         if (!m_haveType)
744             setInputType(getAttribute(typeAttr));
745         m_inited = true;
746     }
747
748     HTMLGenericFormElement::attach();
749
750     if (inputType() == IMAGE) {
751         if (!m_imageLoader)
752             m_imageLoader = new HTMLImageLoader(this);
753         m_imageLoader->updateFromElement();
754         if (renderer()) {
755             RenderImage* imageObj = static_cast<RenderImage*>(renderer());
756             imageObj->setCachedImage(m_imageLoader->image()); 
757             
758             // If we have no image at all because we have no src attribute, set
759             // image height and width for the alt text instead.
760             if (!m_imageLoader->image() && !imageObj->cachedImage())
761                 imageObj->setImageSizeForAltText();
762         }
763     }
764
765     if (inputType() == PASSWORD)
766         document()->registerForDidRestoreFromCacheCallback(this);
767 }
768
769 void HTMLInputElement::detach()
770 {
771     HTMLGenericFormElement::detach();
772     setValueMatchesRenderer(false);
773 }
774
775 String HTMLInputElement::altText() const
776 {
777     // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
778     // also heavily discussed by Hixie on bugzilla
779     // note this is intentionally different to HTMLImageElement::altText()
780     String alt = getAttribute(altAttr);
781     // fall back to title attribute
782     if (alt.isNull())
783         alt = getAttribute(titleAttr);
784     if (alt.isNull())
785         alt = getAttribute(valueAttr);
786     if (alt.isEmpty())
787         alt = inputElementAltText();
788     return alt;
789 }
790
791 bool HTMLInputElement::isSuccessfulSubmitButton() const
792 {
793     // HTML spec says that buttons must have names to be considered successful.
794     // However, other browsers do not impose this constraint. So we do likewise.
795     return !disabled() && (inputType() == IMAGE || inputType() == SUBMIT);
796 }
797
798 bool HTMLInputElement::isActivatedSubmit() const
799 {
800     return m_activeSubmit;
801 }
802
803 void HTMLInputElement::setActivatedSubmit(bool flag)
804 {
805     m_activeSubmit = flag;
806 }
807
808 bool HTMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
809 {
810     // image generates its own names, but for other types there is no form data unless there's a name
811     if (name().isEmpty() && inputType() != IMAGE)
812         return false;
813
814     switch (inputType()) {
815         case HIDDEN:
816         case ISINDEX:
817         case PASSWORD:
818         case RANGE:
819         case SEARCH:
820         case TEXT:
821             // always successful
822             encoding.appendData(name(), value());
823             return true;
824
825         case CHECKBOX:
826         case RADIO:
827             if (checked()) {
828                 encoding.appendData(name(), value());
829                 return true;
830             }
831             break;
832
833         case BUTTON:
834         case RESET:
835             // these types of buttons are never successful
836             return false;
837
838         case IMAGE:
839             if (m_activeSubmit) {
840                 encoding.appendData(name().isEmpty() ? "x" : (name() + ".x"), xPos);
841                 encoding.appendData(name().isEmpty() ? "y" : (name() + ".y"), yPos);
842                 if (!name().isEmpty() && !value().isEmpty())
843                     encoding.appendData(name(), value());
844                 return true;
845             }
846             break;
847
848         case SUBMIT:
849             if (m_activeSubmit) {
850                 String enc_str = valueWithDefault();
851                 if (!enc_str.isEmpty()) {
852                     encoding.appendData(name(), enc_str);
853                     return true;
854                 }
855             }
856             break;
857
858         case FILE:
859             // Can't submit file on GET.
860             if (!multipart)
861                 return false;
862
863             // If no filename at all is entered, return successful but empty.
864             // Null would be more logical, but Netscape posts an empty file. Argh.
865             if (value().isEmpty()) {
866                 encoding.appendData(name(), String(""));
867                 return true;
868             }
869
870             encoding.appendFile(name(), value());
871             return true;
872     }
873     return false;
874 }
875
876 void HTMLInputElement::reset()
877 {
878     if (storesValueSeparateFromAttribute())
879         setValue(String());
880     else if (inputType() == HIDDEN)
881         setValue(m_originalValue);
882     setChecked(m_defaultChecked);
883     m_useDefaultChecked = true;
884 }
885
886 void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent)
887 {
888     if (checked() == nowChecked)
889         return;
890
891     if (inputType() == RADIO && nowChecked)
892         document()->radioButtonChecked(this, form());
893
894     m_useDefaultChecked = false;
895     m_checked = nowChecked;
896     setChanged();
897     if (renderer() && renderer()->style()->hasAppearance())
898         theme()->stateChanged(renderer(), CheckedState);
899
900     // Only send a change event for items in the document (avoid firing during
901     // parsing) and don't send a change event for a radio button that's getting
902     // unchecked to match other browsers. DOM is not a useful standard for this
903     // because it says only to fire change events at "lose focus" time, which is
904     // definitely wrong in practice for these types of elements.
905     if (sendChangeEvent && inDocument() && (inputType() != RADIO || nowChecked))
906         onChange();
907 }
908
909 void HTMLInputElement::setIndeterminate(bool _indeterminate)
910 {
911     // Only checkboxes honor indeterminate.
912     if (inputType() != CHECKBOX || indeterminate() == _indeterminate)
913         return;
914
915     m_indeterminate = _indeterminate;
916
917     setChanged();
918
919     if (renderer() && renderer()->style()->hasAppearance())
920         theme()->stateChanged(renderer(), CheckedState);
921 }
922
923 void HTMLInputElement::copyNonAttributeProperties(const Element *source)
924 {
925     const HTMLInputElement *sourceElem = static_cast<const HTMLInputElement *>(source);
926
927     m_value = sourceElem->m_value;
928     m_checked = sourceElem->m_checked;
929     m_indeterminate = sourceElem->m_indeterminate;
930     
931     HTMLGenericFormElement::copyNonAttributeProperties(source);
932 }
933
934 String HTMLInputElement::value() const
935 {
936     String value = m_value;
937
938     // It's important *not* to fall back to the value attribute for file inputs,
939     // because that would allow a malicious web page to upload files by setting the
940     // value attribute in markup.
941     if (value.isNull() && inputType() != FILE)
942         value = constrainValue(getAttribute(valueAttr));
943
944     // If no attribute exists, then just use "on" or "" based off the checked() state of the control.
945     if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO))
946         return checked() ? "on" : "";
947
948     return value;
949 }
950
951 String HTMLInputElement::valueWithDefault() const
952 {
953     String v = value();
954     if (v.isNull()) {
955         switch (inputType()) {
956             case BUTTON:
957             case CHECKBOX:
958             case FILE:
959             case HIDDEN:
960             case IMAGE:
961             case ISINDEX:
962             case PASSWORD:
963             case RADIO:
964             case RANGE:
965             case SEARCH:
966             case TEXT:
967                 break;
968             case RESET:
969                 v = resetButtonDefaultLabel();
970                 break;
971             case SUBMIT:
972                 v = submitButtonDefaultLabel();
973                 break;
974         }
975     }
976     return v;
977 }
978
979 void HTMLInputElement::setValue(const String& value)
980 {
981     // For security reasons, we don't allow setting the filename, but we do allow clearing it.
982     if (inputType() == FILE && !value.isEmpty())
983         return;
984
985     setValueMatchesRenderer(false);
986     if (storesValueSeparateFromAttribute()) {
987         m_value = constrainValue(value);
988         if (isTextField() && inDocument())
989             document()->updateRendering();
990         if (renderer())
991             renderer()->updateFromElement();
992         setChanged();
993     } else
994         setAttribute(valueAttr, constrainValue(value));
995     
996     // Restore a caret at the starting point of the old selection.
997     // This matches Safari 2.0 behavior.
998     if (isTextField() && document()->focusedNode() == this && cachedSelStart != -1) {
999         ASSERT(cachedSelEnd != -1);
1000         setSelectionRange(cachedSelStart, cachedSelStart);
1001     }
1002 }
1003
1004 void HTMLInputElement::setValueFromRenderer(const String& value)
1005 {
1006     // Renderer and our event handler are responsible for constraining values.
1007     ASSERT(value == constrainValue(value) || constrainValue(value).isEmpty());
1008
1009     // Workaround for bug where trailing \n is included in the result of textContent.
1010     // The assert macro above may also be simplified to:  value == constrainValue(value)
1011     // http://bugs.webkit.org/show_bug.cgi?id=9661
1012     if (value == "\n")
1013         m_value = "";
1014     else
1015         m_value = value;
1016
1017     setValueMatchesRenderer();
1018
1019     // Fire the "input" DOM event.
1020     dispatchHTMLEvent(inputEvent, true, false);
1021 }
1022
1023 bool HTMLInputElement::storesValueSeparateFromAttribute() const
1024 {
1025     switch (inputType()) {
1026         case BUTTON:
1027         case CHECKBOX:
1028         case HIDDEN:
1029         case IMAGE:
1030         case RADIO:
1031         case RANGE:
1032         case RESET:
1033         case SUBMIT:
1034             return false;
1035         case FILE:
1036         case ISINDEX:
1037         case PASSWORD:
1038         case SEARCH:
1039         case TEXT:
1040             return true;
1041     }
1042     return false;
1043 }
1044
1045 void* HTMLInputElement::preDispatchEventHandler(Event *evt)
1046 {
1047     // preventDefault or "return false" are used to reverse the automatic checking/selection we do here.
1048     // This result gives us enough info to perform the "undo" in postDispatch of the action we take here.
1049     void* result = 0; 
1050     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
1051             && evt->type() == clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1052         if (inputType() == CHECKBOX) {
1053             // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for
1054             // indeterminate.
1055             if (indeterminate()) {
1056                 result = (void*)0x2;
1057                 setIndeterminate(false);
1058             } else {
1059                 if (checked())
1060                     result = (void*)0x1;
1061                 setChecked(!checked(), true);
1062             }
1063         } else {
1064             // For radio buttons, store the current selected radio object.
1065             if (name().isEmpty() || checked())
1066                 return 0; // Match WinIE and don't allow unnamed radio buttons to be checked.
1067                           // Checked buttons just stay checked.
1068                           // FIXME: Need to learn to work without a form.
1069
1070             // We really want radio groups to end up in sane states, i.e., to have something checked.
1071             // Therefore if nothing is currently selected, we won't allow this action to be "undone", since
1072             // we want some object in the radio group to actually get selected.
1073             HTMLInputElement* currRadio = document()->checkedRadioButtonForGroup(name().impl(), form());
1074             if (currRadio) {
1075                 // We have a radio button selected that is not us.  Cache it in our result field and ref it so
1076                 // that it can't be destroyed.
1077                 currRadio->ref();
1078                 result = currRadio;
1079             }
1080             setChecked(true, true);
1081         }
1082     }
1083     return result;
1084 }
1085
1086 void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data)
1087 {
1088     if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent()
1089             && evt->type() == clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1090         if (inputType() == CHECKBOX) {
1091             // Reverse the checking we did in preDispatch.
1092             if (evt->defaultPrevented() || evt->defaultHandled()) {
1093                 if (data == (void*)0x2)
1094                     setIndeterminate(true);
1095                 else
1096                     setChecked(data);
1097             }
1098         } else if (data) {
1099             HTMLInputElement* input = static_cast<HTMLInputElement*>(data);
1100             if (evt->defaultPrevented() || evt->defaultHandled()) {
1101                 // Restore the original selected radio button if possible.
1102                 // Make sure it is still a radio button and only do the restoration if it still
1103                 // belongs to our group.
1104
1105                 // Match WinIE and don't allow unnamed radio buttons to be checked.
1106                 if (input->form() == form() && input->inputType() == RADIO && !name().isEmpty() && input->name() == name()) {
1107                     // Ok, the old radio button is still in our form and in our group and is still a 
1108                     // radio button, so it's safe to restore selection to it.
1109                     input->setChecked(true);
1110                 }
1111             }
1112             input->deref();
1113         }
1114     }
1115 }
1116
1117 void HTMLInputElement::defaultEventHandler(Event* evt)
1118 {
1119     bool clickDefaultFormButton = false;
1120
1121     if (isTextField() && evt->type() == textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
1122         clickDefaultFormButton = true;
1123
1124     if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == clickEvent) {
1125         // record the mouse position for when we get the DOMActivate event
1126         MouseEvent* me = static_cast<MouseEvent*>(evt);
1127         // FIXME: We could just call offsetX() and offsetY() on the event,
1128         // but that's currently broken, so for now do the computation here.
1129         if (me->isSimulated() || !renderer()) {
1130             xPos = 0;
1131             yPos = 0;
1132         } else {
1133             int offsetX, offsetY;
1134             renderer()->absolutePosition(offsetX, offsetY);
1135             xPos = me->pageX() - offsetX;
1136             // FIXME: Why is yPos a short?
1137             yPos = me->pageY() - offsetY;
1138         }
1139     }
1140
1141     // Before calling the base class defaultEventHandler, which will call handleKeypress, call doTextFieldCommandFromEvent.
1142     if (isTextField() && evt->type() == keypressEvent && evt->isKeyboardEvent() && focused() && document()->frame()
1143                 && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
1144         evt->setDefaultHandled();
1145         return;
1146     }
1147     
1148     // Let the key handling done in EventTargetNode take precedence over the event handling here for editable text fields
1149     if (!clickDefaultFormButton) {
1150         HTMLGenericFormElement::defaultEventHandler(evt);
1151         if (evt->defaultHandled())
1152             return;
1153     }
1154
1155     // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
1156     // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
1157     // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
1158     // must dispatch a DOMActivate event - a click event will not do the job.
1159     if (evt->type() == DOMActivateEvent && !disabled()) {
1160         if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) {
1161             if (!form())
1162                 return;
1163             if (inputType() == RESET)
1164                 form()->reset();
1165             else {
1166                 m_activeSubmit = true;
1167                 // FIXME: Would be cleaner to get xPos and yPos out of the underlying mouse
1168                 // event (if any) here instead of relying on the variables set above when
1169                 // processing the click event. Even better, appendFormData could pass the
1170                 // event in, and then we could get rid of xPos and yPos altogether!
1171                 if (!form()->prepareSubmit(evt)) {
1172                     xPos = 0;
1173                     yPos = 0;
1174                 }
1175                 m_activeSubmit = false;
1176             }
1177         } else if (inputType() == FILE && renderer())
1178             static_cast<RenderFileUploadControl*>(renderer())->click();
1179     }
1180
1181     // Use key press event here since sending simulated mouse events
1182     // on key down blocks the proper sending of the key press event.
1183     if (evt->type() == keypressEvent && evt->isKeyboardEvent()) {
1184         bool clickElement = false;
1185
1186         String key = static_cast<KeyboardEvent*>(evt)->keyIdentifier();
1187
1188         if (key == "U+000020") {
1189             switch (inputType()) {
1190                 case BUTTON:
1191                 case CHECKBOX:
1192                 case FILE:
1193                 case IMAGE:
1194                 case RESET:
1195                 case SUBMIT:
1196                     // Simulate mouse click for spacebar for these types of elements.
1197                     // The AppKit already does this for some, but not all, of them.
1198                     clickElement = true;
1199                     break;
1200                 case RADIO:
1201                     // If an unselected radio is tabbed into (because the entire group has nothing
1202                     // checked, or because of some explicit .focus() call), then allow space to check it.
1203                     if (!checked())
1204                         clickElement = true;
1205                     break;
1206                 case HIDDEN:
1207                 case ISINDEX:
1208                 case PASSWORD:
1209                 case RANGE:
1210                 case SEARCH:
1211                 case TEXT:
1212                     break;
1213             }
1214         }
1215
1216         if (key == "Enter") {
1217             switch (inputType()) {
1218                 case BUTTON:
1219                 case CHECKBOX:
1220                 case HIDDEN:
1221                 case ISINDEX:
1222                 case PASSWORD:
1223                 case RANGE:
1224                 case SEARCH:
1225                 case TEXT:
1226                     // Simulate mouse click on the default form button for enter for these types of elements.
1227                     clickDefaultFormButton = true;
1228                     break;
1229                 case FILE:
1230                 case IMAGE:
1231                 case RESET:
1232                 case SUBMIT:
1233                     // Simulate mouse click for enter for these types of elements.
1234                     clickElement = true;
1235                     break;
1236                 case RADIO:
1237                     break; // Don't do anything for enter on a radio button.
1238             }
1239         }
1240
1241         if (inputType() == RADIO && (key == "Up" || key == "Down" || key == "Left" || key == "Right")) {
1242             // Left and up mean "previous radio button".
1243             // Right and down mean "next radio button".
1244             // Tested in WinIE, and even for RTL, left still means previous radio button (and so moves
1245             // to the right).  Seems strange, but we'll match it.
1246             bool forward = (key == "Down" || key == "Right");
1247             
1248             // We can only stay within the form's children if the form hasn't been demoted to a leaf because
1249             // of malformed HTML.
1250             Node* n = this;
1251             while ((n = (forward ? n->traverseNextNode() : n->traversePreviousNode()))) {
1252                 // Once we encounter a form element, we know we're through.
1253                 if (n->hasTagName(formTag))
1254                     break;
1255                     
1256                 // Look for more radio buttons.
1257                 if (n->hasTagName(inputTag)) {
1258                     HTMLInputElement* elt = static_cast<HTMLInputElement*>(n);
1259                     if (elt->form() != form())
1260                         break;
1261                     if (n->hasTagName(inputTag)) {
1262                         // Match WinIE and don't allow unnamed radio buttons to be checked.
1263                         HTMLInputElement* inputElt = static_cast<HTMLInputElement*>(n);
1264                         if (inputElt->inputType() == RADIO && !name().isEmpty() && inputElt->name() == name() && inputElt->isFocusable()) {
1265                             inputElt->setChecked(true);
1266                             document()->setFocusedNode(inputElt);
1267                             inputElt->dispatchSimulatedClick(evt, false, false);
1268                             evt->setDefaultHandled();
1269                             break;
1270                         }
1271                     }
1272                 }
1273             }
1274         }
1275
1276         if (clickElement) {
1277             dispatchSimulatedClick(evt);
1278             evt->setDefaultHandled();
1279             return;
1280         }        
1281     }
1282
1283     if (clickDefaultFormButton) {
1284         if (isSearchField()) {
1285             addSearchResult();
1286             onSearch();
1287         }
1288         // Fire onChange for text fields.
1289         RenderObject* r = renderer();
1290         if (r && r->isTextField() && r->isEdited()) {
1291             onChange();
1292             r->setEdited(false);
1293         }
1294         // Form may never have been present, or may have been destroyed by the change event.
1295         if (form())
1296             form()->submitClick(evt);
1297         evt->setDefaultHandled();
1298         return;
1299     }
1300
1301     if (evt->isBeforeTextInsertedEvent()) {
1302         // Make sure that the text to be inserted will not violate the maxLength.
1303         int oldLen = numGraphemeClusters(value().impl());
1304         ASSERT(oldLen <= maxLength());
1305         int selectionLen = numGraphemeClusters(document()->frame()->selectionController()->toString().impl());
1306         ASSERT(oldLen >= selectionLen);
1307         int maxNewLen = maxLength() - (oldLen - selectionLen);
1308
1309         // Truncate the inserted text to avoid violating the maxLength and other constraints.
1310         BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(evt);
1311         textEvent->setText(constrainValue(textEvent->text(), maxNewLen));
1312     }
1313
1314     if (isTextField() && renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == blurEvent || evt->type() == focusEvent))
1315         static_cast<RenderTextControl*>(renderer())->forwardEvent(evt);
1316
1317     if (inputType() == RANGE && renderer()) {
1318         RenderSlider* slider = static_cast<RenderSlider*>(renderer());
1319         if (evt->isMouseEvent() && evt->type() == mousedownEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
1320             MouseEvent* mEvt = static_cast<MouseEvent*>(evt);
1321             if (!slider->mouseEventIsInThumb(mEvt)) {
1322                 slider->setValueForPosition(slider->positionForOffset(IntPoint(mEvt->offsetX(), mEvt->offsetY())));
1323             }
1324         }
1325         if (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent())
1326             slider->forwardEvent(evt);
1327     }
1328 }
1329
1330 bool HTMLInputElement::isURLAttribute(Attribute *attr) const
1331 {
1332     return (attr->name() == srcAttr);
1333 }
1334
1335 String HTMLInputElement::defaultValue() const
1336 {
1337     return getAttribute(valueAttr);
1338 }
1339
1340 void HTMLInputElement::setDefaultValue(const String &value)
1341 {
1342     setAttribute(valueAttr, value);
1343 }
1344
1345 bool HTMLInputElement::defaultChecked() const
1346 {
1347     return !getAttribute(checkedAttr).isNull();
1348 }
1349
1350 void HTMLInputElement::setDefaultChecked(bool defaultChecked)
1351 {
1352     setAttribute(checkedAttr, defaultChecked ? "" : 0);
1353 }
1354
1355 String HTMLInputElement::accept() const
1356 {
1357     return getAttribute(acceptAttr);
1358 }
1359
1360 void HTMLInputElement::setAccept(const String &value)
1361 {
1362     setAttribute(acceptAttr, value);
1363 }
1364
1365 String HTMLInputElement::accessKey() const
1366 {
1367     return getAttribute(accesskeyAttr);
1368 }
1369
1370 void HTMLInputElement::setAccessKey(const String &value)
1371 {
1372     setAttribute(accesskeyAttr, value);
1373 }
1374
1375 String HTMLInputElement::align() const
1376 {
1377     return getAttribute(alignAttr);
1378 }
1379
1380 void HTMLInputElement::setAlign(const String &value)
1381 {
1382     setAttribute(alignAttr, value);
1383 }
1384
1385 String HTMLInputElement::alt() const
1386 {
1387     return getAttribute(altAttr);
1388 }
1389
1390 void HTMLInputElement::setAlt(const String &value)
1391 {
1392     setAttribute(altAttr, value);
1393 }
1394
1395 void HTMLInputElement::setMaxLength(int _maxLength)
1396 {
1397     setAttribute(maxlengthAttr, String::number(_maxLength));
1398 }
1399
1400 void HTMLInputElement::setSize(unsigned _size)
1401 {
1402     setAttribute(sizeAttr, String::number(_size));
1403 }
1404
1405 String HTMLInputElement::src() const
1406 {
1407     return document()->completeURL(getAttribute(srcAttr));
1408 }
1409
1410 void HTMLInputElement::setSrc(const String &value)
1411 {
1412     setAttribute(srcAttr, value);
1413 }
1414
1415 String HTMLInputElement::useMap() const
1416 {
1417     return getAttribute(usemapAttr);
1418 }
1419
1420 void HTMLInputElement::setUseMap(const String &value)
1421 {
1422     setAttribute(usemapAttr, value);
1423 }
1424
1425 String HTMLInputElement::constrainValue(const String& proposedValue) const
1426 {
1427     return constrainValue(proposedValue, m_maxLen);
1428 }
1429
1430 void HTMLInputElement::recheckValue()
1431 {
1432     String oldValue = value();
1433     String newValue = constrainValue(oldValue);
1434     if (newValue != oldValue)
1435         setValue(newValue);
1436 }
1437
1438 String HTMLInputElement::constrainValue(const String& proposedValue, int maxLen) const
1439 {
1440     if (isTextField()) {
1441         StringImpl* s = proposedValue.impl();
1442         int newLen = numCharactersInGraphemeClusters(s, maxLen);
1443         for (int i = 0; i < newLen; ++i)
1444             if ((*s)[i] < ' ') {
1445                 newLen = i;
1446                 break;
1447             }
1448         if (newLen < static_cast<int>(proposedValue.length()))
1449             return proposedValue.substring(0, newLen);
1450     }
1451     return proposedValue;
1452 }
1453
1454 void HTMLInputElement::addSearchResult()
1455 {
1456     ASSERT(isSearchField());
1457     if (renderer())
1458         static_cast<RenderTextControl*>(renderer())->addSearchResult();
1459 }
1460
1461 void HTMLInputElement::onSearch()
1462 {
1463     ASSERT(isSearchField());
1464     if (renderer())
1465         static_cast<RenderTextControl*>(renderer())->stopSearchEventTimer();
1466     dispatchHTMLEvent(searchEvent, true, false);
1467 }
1468
1469 Selection HTMLInputElement::selection() const
1470 {
1471    if (!renderer() || !isTextField() || cachedSelStart == -1 || cachedSelEnd == -1)
1472         return Selection();
1473    return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd);
1474 }
1475
1476 void HTMLInputElement::didRestoreFromCache()
1477 {
1478     ASSERT(inputType() == PASSWORD);
1479     reset();
1480 }
1481     
1482 } // namespace