在chromium中实现WML的支持

从KK开始,Google开始切换Web引擎了, androd webkit废弃,改为chromium了,但是前面运营商大爷要求的WML咋办?唉,硬着头皮开始把WML往chromium上搞呗.
如何搞?采用最笨的方法,HTML相关的类被调用的地方过一遍,加上WML相对应的类。
贴出来部分修改的地方,因为本来就是基于opensource的,所以不存在confidential的问题。
看到修改的文件,大概就能知道HTML相关的类在显示和交互的过程中会与那些类打交道。

Source/core/html/BaseTextInputType.h
class BaseTextInputType : public TextFieldInputType {
protected:
#if ENABLE(WML)
BaseTextInputType(WMLInputElement* element) : TextFieldInputType(element) { }
#endif
BaseTextInputType(HTMLInputElement* element) : TextFieldInputType(element) { }

Source/core/html/BaseTextInputType.cpp
bool BaseTextInputType::patternMismatch(const String& value) const
{
#if ENABLE(WML)
if (isWML()) {
/Fix me, Neo Check???/
return false;
} else {
#endif
const AtomicString& rawPattern = element()->fastGetAttribute(patternAttr);
// Empty values can’t be mismatched
if (rawPattern.isNull() || value.isEmpty() || !RegularExpression(rawPattern, TextCaseSensitive).isValid())
return false;
String pattern = “^(?:” + rawPattern + “)$”;
int matchLength = 0;
int valueLength = value.length();
int matchOffset = RegularExpression(pattern, TextCaseSensitive).match(value, 0, &matchLength);
return matchOffset || matchLength != valueLength;
#if ENABLE(WML)
}
#endif
}

Source/core/html/InputType.h
public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*, const AtomicString&);
static PassOwnPtr createText(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*, const AtomicString&);

protected:
#if ENABLE(WML)
bool isWML() const { return m_wmlinput; }
InputType(WMLInputElement* element) : m_elementwml(element), m_wmlinput(true) { }
WMLInputElement* wmlelement() const { return m_elementwml; }
#endif
InputType(HTMLInputElement* element) : m_element(element),m_wmlinput(false) { }
HTMLInputElement* element() const { return m_element; }
Chrome* chrome() const;
Decimal parseToNumberOrNaN(const String&) const;
void observeFeatureIfVisible(UseCounter::Feature) const;

private:
// Helper for stepUp()/stepDown(). Adds step value * count to the current value.
void applyStep(int count, AnyStepHandling, TextFieldEventBehavior, ExceptionState&);

// Raw pointer because the HTMLInputElement object owns this InputType object.
HTMLInputElement* m_element;

#if ENABLE(WML)
WMLInputElement* m_elementwml;
bool m_wmlinput;
#endif

Source/core/html/InputType.cpp
PassOwnPtr InputType::create(WMLInputElement* element, const AtomicString& typeName)
{
return (typeName == InputTypeNames::password())?PasswordInputType::create(element): TextInputType::create(element);
}

PassOwnPtr InputType::createText(WMLInputElement* element)
{
return TextInputType::create(element);
}
FormControlState InputType::saveFormControlState() const
{
#if ENABLE(WML)
if (isWML())
return FormControlState();
#endif
String currentValue = element()->value();
if (currentValue == element()->defaultValue())
return FormControlState();
return FormControlState(currentValue);
}

void InputType::restoreFormControlState(const FormControlState& state)
{
#if ENABLE(WML)
if (isWML())
wmlelement()->setValue(state[0]);
else
#endif
element()->setValue(state[0]);
}

bool InputType::isFormDataAppendable() const
{
#if ENABLE(WML)
if (isWML())
return !wmlelement()->name().isEmpty();
else
#endif
// There is no form data unless there’s a name for non-image types.
return !element()->name().isEmpty();
}

bool InputType::appendFormData(FormDataList& encoding, bool) const
{
#if ENABLE(WML)
if (isWML())
encoding.appendData(wmlelement()->name(), wmlelement()->value());
else
#endif

bool InputType::sizeShouldIncludeDecoration(int, int& preferredSize) const
{
#if ENABLE(WML)
if (isWML())
preferredSize = wmlelement()->size();
else
#endif
preferredSize = element()->size();
return false;
}

String InputType::validationMessage() const
{
String value;
#if ENABLE(WML)
if (isWML())
value = wmlelement()->value();
else
#endif
value = element()->value();

// The order of the following checks is meaningful. e.g. We'd like to show the
// badInput message even if the control has other validation errors.
if (hasBadInput())
    return badInputText();

if (valueMissing(value))
    return valueMissingText();

if (typeMismatch())
    return typeMismatchText();

if (patternMismatch(value))
    return validationMessagePatternMismatchText();

#if ENABLE(WML)
if (isWML() && wmlelement()->tooLong())
return validationMessageTooLongText(numGraphemeClusters(value), wmlelement()->maxLength());
if (!isWML() && element()->tooLong())
return validationMessageTooLongText(numGraphemeClusters(value), element()->maxLength());
#endif

PassRefPtr InputType::formForSubmission() const
{
#if ENABLE(WML)
if (isWML())
return 0;
else
#endif
return element()->form();
}

RenderObject* InputType::createRenderer(RenderStyle* style) const
{
#if ENABLE(WML)
if (isWML())
return RenderObject::createObject(wmlelement(), style);
else
#endif
return RenderObject::createObject(element(), style);
}

PassRefPtr InputType::customStyleForRenderer(PassRefPtr originalStyle)
{
return originalStyle;
}

void InputType::blur()
{
#if ENABLE(WML)
if (isWML())
wmlelement()->defaultBlur();
else
#endif
element()->defaultBlur();
}

void InputType::createShadowSubtree()
{
}

void InputType::destroyShadowSubtree()
{
ShadowRoot* root;
#if ENABLE(WML)
if (isWML())
root = wmlelement()->userAgentShadowRoot();
else
#endif
root = element()->userAgentShadowRoot();
if (!root)
return;
void InputType::dispatchSimulatedClickIfActive(KeyboardEvent* event) const
{
#if ENABLE(WML)
if (isWML()) {
if (wmlelement()->active())
wmlelement()->dispatchSimulatedClick(event);
} else {
#endif
if (element()->active())
element()->dispatchSimulatedClick(event);
event->setDefaultHandled();
#if ENABLE(WML)
}
#endif
}

Chrome* InputType::chrome() const
{
#if ENABLE(WML)
if (isWML()) {
if (Page* page = wmlelement()->document()->page())
return &page->chrome();
}
else
#endif
if (Page* page = element()->document()->page())
return &page->chrome();
return 0;
}

bool InputType::canSetStringValue() const
{
return true;
}

bool InputType::hasCustomFocusLogic() const
{
return true;
}

bool InputType::isKeyboardFocusable() const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->isFocusable();
else
#endif
return element()->isFocusable();
}
void InputType::accessKeyAction(bool)
{
#if ENABLE(WML)
if (isWML())
wmlelement()->focus(false);
else
#endif
element()->focus(false);
}
void InputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
#if ENABLE(WML)
if (isWML()) {
wmlelement()->setValueInternal(sanitizedValue, eventBehavior);
wmlelement()->setNeedsStyleRecalc();
if (!valueChanged)
return;
switch (eventBehavior) {
case DispatchChangeEvent:
wmlelement()->dispatchFormControlChangeEvent();
break;
case DispatchInputAndChangeEvent:
wmlelement()->dispatchFormControlInputEvent();
wmlelement()->dispatchFormControlChangeEvent();
break;
case DispatchNoEvent:
break;
}
} else {
#endif
element()->setValueInternal(sanitizedValue, eventBehavior);
element()->setNeedsStyleRecalc();
if (!valueChanged)
return;
switch (eventBehavior) {
case DispatchChangeEvent:
element()->dispatchFormControlChangeEvent();
break;
case DispatchInputAndChangeEvent:
element()->dispatchFormControlInputEvent();
element()->dispatchFormControlChangeEvent();
break;
case DispatchNoEvent:
break;
}
#if ENABLE(WML)
}
#endif
}
String InputType::visibleValue() const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->value();
else
#endif
return element()->value();
}
void InputType::applyStep(int count, AnyStepHandling anyStepHandling, TextFieldEventBehavior eventBehavior, ExceptionState& es)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
StepRange stepRange(createStepRange(anyStepHandling));

void InputType::stepUpFromRenderer(int n)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
void InputType::observeFeatureIfVisible(UseCounter::Feature feature) const
{
#if ENABLE(WML)
if (isWML())
return;
#endif
if (RenderStyle* style = element()->renderStyle()) {

/Source/core/html/PasswordInputType.h
class PasswordInputType FINAL : public BaseTextInputType {
public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*);

private:
#if ENABLE(WML)
PasswordInputType(WMLInputElement* element) : BaseTextInputType(element) { }
#endif

Source/core/html/PasswordInputType.cpp
#if ENABLE(WML)
PassOwnPtr PasswordInputType::create(WMLInputElement* element)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, element=%x”,element);
return adoptPtr(new PasswordInputType(element));
}
#endif
PassOwnPtr PasswordInputType::create(HTMLInputElement* element)
{
return adoptPtr(new PasswordInputType(element));
}

HTMLElement* PasswordInputType::passwordGeneratorButtonElement() const
{
return m_generatorButton.get();
}

bool PasswordInputType::isPasswordGenerationEnabled() const
{
#if ENABLE(WML)
if (isWML())
return false;
#endif
void PasswordInputType::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
BaseTextInputType::handleFocusEvent(oldFocusedElement, direction);
#if ENABLE(WML)
if (isWML() && wmlelement()->document()->frame())
wmlelement()->document()->setUseSecureKeyboardEntryWhenActive(true);
else
#endif
if (element()->document()->frame())
element()->document()->setUseSecureKeyboardEntryWhenActive(true);
}

void PasswordInputType::handleBlurEvent()
{
#if ENABLE(WML)
if (isWML() && wmlelement()->document()->frame())
wmlelement()->document()->setUseSecureKeyboardEntryWhenActive(false);
else
#endif
Source/core/html/TextFieldInputType.h
#if ENABLE(WML)
TextFieldInputType(WMLInputElement*);
#endif

Source/core/html/TextFieldInputType.cpp
#if ENABLE(WML)
static inline bool shouldIgnoreRequiredAttribute(const WMLInputElement& input)
{
return false;
}
#endif
static inline bool shouldIgnoreRequiredAttribute(const HTMLInputElement& input)
{
if (!input.document()->settings() || !input.document()->settings()->needsSiteSpecificQuirks())
return false;
if (!equalIgnoringCase(input.document()->url().host(), “egov.uscis.gov”))
return false;
return input.fastGetAttribute(requiredAttr) == “no”;
}

bool TextFieldInputType::valueMissing(const String& value) const
{
#if ENABLE(WML)
if (isWML())
return wmlelement()->isRequired() && value.isEmpty();
#endif
return !shouldIgnoreRequiredAttribute(*element()) && element()->isRequired() && value.isEmpty();
}

bool TextFieldInputType::canSetSuggestedValue()
{
return true;
}

void TextFieldInputType::setValue(const String& sanitizedValue, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
#if ENABLE(WML)
if (isWML()) {
RefPtr input(wmlelement());

    // We don't ask InputType::setValue to dispatch events because
    // TextFieldInputType dispatches events different way from InputType.
    InputType::setValue(sanitizedValue, valueChanged, DispatchNoEvent);

    if (valueChanged)
        updateInnerTextValue();

    unsigned max = visibleValue().length();
    if (input->focused())
        input->setSelectionRange(max, max);
    else
        input->cacheSelectionInResponseToSetValue(max);

    if (!valueChanged)
        return;

    switch (eventBehavior) {
    case DispatchChangeEvent:
        // If the user is still editing this field, dispatch an input event rather than a change event.
        // The change event will be dispatched when editing finishes.
        if (input->focused())
            input->dispatchFormControlInputEvent();
        else
            input->dispatchFormControlChangeEvent();
        break;

    case DispatchInputAndChangeEvent: {
        input->dispatchFormControlInputEvent();
        input->dispatchFormControlChangeEvent();
        break;
    }

    case DispatchNoEvent:
        break;
    }

    // FIXME: Why do we do this when eventBehavior == DispatchNoEvent
    if (!input->focused() || eventBehavior == DispatchNoEvent)
        input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
} else {

#endif

// FIXME: Why do we do this when eventBehavior == DispatchNoEvent
if (!input->focused() || eventBehavior == DispatchNoEvent)
input->setTextAsOfLastFormControlChangeEvent(sanitizedValue);
#if ENABLE(WML)
}
#endif
}

void TextFieldInputType::handleKeydownEvent(KeyboardEvent* event)
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->focused())
return;
Frame* frame = wmlelement()->document()->frame();
if (!frame || !frame->editor()->doTextFieldCommandFromEvent(wmlelement(), event))
return;
} else {
#endif
if (!element()->focused())
return;
Frame* frame = element()->document()->frame();
if (!frame || !frame->editor()->doTextFieldCommandFromEvent(element(), event))
return;
#if ENABLE(WML)
}
#endif
event->setDefaultHandled();
}

void TextFieldInputType::handleKeydownEventForSpinButton(KeyboardEvent* event)
{
#if ENABLE(WML)
if (isWML())
return;
#endif
void TextFieldInputType::forwardEvent(Event* event)
{
#if ENABLE(WML)
if (isWML()) {
if (wmlelement()->renderer() && (event->isMouseEvent() || event->isDragEvent() || event->hasInterface(eventNames().interfaceForWheelEvent) || event->type() == eventNames().blurEvent || event->type() == eventNames().focusEvent)) {
RenderTextControlSingleLine* renderTextControl = toRenderTextControlSingleLine(wmlelement()->renderer());
if (event->type() == eventNames().blurEvent) {
if (RenderBox* innerTextRenderer = innerTextElement()->renderBox()) {
if (RenderLayer* innerLayer = innerTextRenderer->layer()) {
IntSize scrollOffset(!renderTextControl->style()->isLeftToRightDirection() ? innerLayer->scrollWidth() : 0, 0);
innerLayer->scrollToOffset(scrollOffset, RenderLayer::ScrollOffsetClamped);
}
}

            renderTextControl->capsLockStateMayHaveChanged();
        } else if (event->type() == eventNames().focusEvent)
            renderTextControl->capsLockStateMayHaveChanged();

// wmlelement()->forwardEvent(event);
}
} else {
#endif

void TextFieldInputType::handleFocusEvent(Element* oldFocusedNode, FocusDirection focusDirection)
{
InputType::handleFocusEvent(oldFocusedNode, focusDirection);
#if ENABLE(WML)
if (isWML())
wmlelement()->beginEditing();
else
#endif
element()->beginEditing();
}

void TextFieldInputType::handleBlurEvent()
{
InputType::handleBlurEvent();
#if ENABLE(WML)
if (isWML())
wmlelement()->endEditing();
else
#endif
element()->endEditing();
}

bool TextFieldInputType::shouldSubmitImplicitly(Event* event)
{
return (event->type() == eventNames().textInputEvent && event->hasInterface(eventNames().interfaceForTextEvent) && static_cast<TextEvent*>(event)->data() == “\n”) || InputType::shouldSubmitImplicitly(event);
}

RenderObject* TextFieldInputType::createRenderer(RenderStyle*) const
{
#if ENABLE(WML)
if (isWML())
return new RenderTextControlSingleLine(wmlelement());
else
#endif
return new RenderTextControlSingleLine(element());
}

bool TextFieldInputType::needsContainer() const
{
#if ENABLE(INPUT_SPEECH)
#if ENABLE(WML)
if (isWML())
return false;
#endif
return element()->isSpeechEnabled();
#else
return false;
#endif
}

bool TextFieldInputType::shouldHaveSpinButton() const
{
#if ENABLE(WML)
if (isWML())
return false;
#endif
Document* document = element()->document();
RefPtr theme = document->page() ? document->page()->theme() : RenderTheme::defaultTheme();
return theme->shouldHaveSpinButton(element());
}

void TextFieldInputType::createShadowSubtree()
{
#if ENABLE(WML)
if (isWML()) {
ASSERT(wmlelement()->shadow());

    ASSERT(!m_innerText);
    ASSERT(!m_innerBlock);
    ASSERT(!m_innerSpinButton);

    Document* document = wmlelement()->document();
    bool shouldHaveSpinButton = this->shouldHaveSpinButton();
    bool createsContainer = shouldHaveSpinButton || needsContainer();

    m_innerText = TextControlInnerTextElement::create(document);

    if (!createsContainer) {
        wmlelement()->userAgentShadowRoot()->appendChild(m_innerText, IGNORE_EXCEPTION);
        return;
    }

    ShadowRoot* shadowRoot = wmlelement()->userAgentShadowRoot();
    m_container = TextControlInnerContainer::create(document);
    m_container->setPart(AtomicString("-webkit-textfield-decoration-container", AtomicString::ConstructFromLiteral));
    shadowRoot->appendChild(m_container, IGNORE_EXCEPTION);

    m_innerBlock = TextControlInnerElement::create(document);
    m_innerBlock->appendChild(m_innerText, IGNORE_EXCEPTION);
    m_container->appendChild(m_innerBlock, IGNORE_EXCEPTION);

android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x, wmlelement=%x,m_innerText=%x,m_container=%x,m_innerBlock=%x”,this,wmlelement(),m_innerText.get(),m_container.get(),m_innerBlock.get());
} else {
#endif

void TextFieldInputType::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event)
{
// Make sure that the text to be inserted will not violate the maxLength.

// We use HTMLInputElement::innerTextValue() instead of
// HTMLInputElement::value() because they can be mismatched by
// sanitizeValue() in HTMLInputElement::subtreeHasChanged() in some cases.

#if ENABLE(WML)
unsigned oldLength;
if (isWML())
oldLength = wmlelement()->innerTextValue().length();
else
oldLength = element()->innerTextValue().length();
#else
unsigned oldLength = element()->innerTextValue().length();
#endif

// selectionLength represents the selection length of this text field to be
// removed by this insertion.
// If the text field has no focus, we don't need to take account of the
// selection length. The selection is the source of text drag-and-drop in
// that case, and nothing in the text field will be removed.
unsigned selectionLength;

#if ENABLE(WML)
if (isWML())
selectionLength = wmlelement()->focused() ? plainText(wmlelement()->document()->frame()->selection()->selection().toNormalizedRange().get()).length() : 0;
else
#endif
selectionLength = element()->focused() ? plainText(element()->document()->frame()->selection()->selection().toNormalizedRange().get()).length() : 0;
ASSERT(oldLength >= selectionLength);

// Selected characters will be removed by the next text event.
unsigned baseLength = oldLength - selectionLength;
unsigned maxLength;

#if ENABLE(WML)
if (isWML())
maxLength = static_cast(isTextType() ? wmlelement()->maxLength() : HTMLInputElement::maximumLength); // maxLength can never be negative.
else
#endif
maxLength = static_cast(isTextType() ? element()->maxLength() : HTMLInputElement::maximumLength); // maxLength can never be negative.

void TextFieldInputType::updatePlaceholderText()
{
if (!supportsPlaceholder())
return;
#if ENABLE(WML)
if (isWML()) {
if (m_placeholder) {
m_placeholder->parentNode()->removeChild(m_placeholder.get(), ASSERT_NO_EXCEPTION);
m_placeholder.clear();
}
return;
}
#endif

void TextFieldInputType::attach()
{
InputType::attach();
// If container exists, the container should not have any content data.
ASSERT(!m_container || !m_container->renderStyle() || !m_container->renderStyle()->hasContent());
#if ENABLE(WML)
if (isWML())
wmlelement()->fixPlaceholderRenderer(m_placeholder.get(), m_container ? m_container.get() : m_innerText.get());
else
#endif
element()->fixPlaceholderRenderer(m_placeholder.get(), m_container ? m_container.get() : m_innerText.get());
}

bool TextFieldInputType::appendFormData(FormDataList& list, bool multipart) const
{
InputType::appendFormData(list, multipart);
#if ENABLE(WML)
if (isWML())
return true;
#endif

void TextFieldInputType::subtreeHasChanged()
{
bool wasChanged;
#if ENABLE(WML)
if (isWML()) {
ASSERT(wmlelement()->renderer());
wasChanged = wmlelement()->wasChangedSinceLastFormControlChangeEvent();
wmlelement()->setChangedSinceLastFormControlChangeEvent(true);

// We don't need to call sanitizeUserInputValue() function here because
// HTMLInputElement::handleBeforeTextInsertedEvent() has already called
// sanitizeUserInputValue().
// sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.

    wmlelement()->setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element()->innerTextValue())));
    wmlelement()->updatePlaceholderVisibility(false);
    // Recalc for :invalid change.
    wmlelement()->setNeedsStyleRecalc();
} else {

#endif
void TextFieldInputType::didSetValueByUserEdit(ValueChangeState state)
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->focused())
return;
if (Frame* frame = wmlelement()->document()->frame())
frame->editor()->textDidChangeInTextField(wmlelement());
} else {
#endif
void TextFieldInputType::updateInnerTextValue()
{
#if ENABLE(WML)
if (isWML()) {
if (!wmlelement()->suggestedValue().isNull()) {
wmlelement()->setInnerTextValue(wmlelement()->suggestedValue());
wmlelement()->updatePlaceholderVisibility(false);
} else if (!wmlelement()->formControlValueMatchesRenderer()) {
// Update the renderer value if the formControlValueMatchesRenderer() flag is false.
// It protects an unacceptable renderer value from being overwritten with the DOM value.
wmlelement()->setInnerTextValue(visibleValue());
wmlelement()->updatePlaceholderVisibility(false);
}
} else {
#endif
Source/core/html/TextInputType.h

public:
#if ENABLE(WML)
static PassOwnPtr create(WMLInputElement*);
#endif
static PassOwnPtr create(HTMLInputElement*);

private:
#if ENABLE(WML)
TextInputType(WMLInputElement* element) : BaseTextInputType(element) { }
#endif
Source/core/html/TextInputType.cpp
if ENABLE(WML)
PassOwnPtr TextInputType::create(WMLInputElement* element)
{
return adoptPtr(new TextInputType(element));
}
#endif
PassOwnPtr TextInputType::create(HTMLInputElement* element)
{
return adoptPtr(new TextInputType(element));
}

void TextInputType::attach()
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x, element=%x”,this, element());
TextFieldInputType::attach();
#if ENABLE(WML)
if (isWML())
return;
#endif

Source/core/rendering/RenderBox.h
virtual const char* renderName() const { return “renderbox”;}
Source/core/rendering/RenderBox.cpp

bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const
if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && node() && (node()->hasTagName(inputTag)
#if ENABLE(WML)
|| node()->hasTagName(WMLNames::inputTag)
#endif
|| node()->hasTagName(selectTag) || node()->hasTagName(buttonTag) || isHTMLTextAreaElement(node()) || node()->hasTagName(legendTag)))
return true;

Source/core/rendering/RenderTextControl.h
class HTMLTextFormControlElement;
class WMLFormControlElement;

class RenderTextControl : public RenderBlock {
public:
virtual ~RenderTextControl();

HTMLTextFormControlElement* textFormControlElement() const;
WMLFormControlElement* wmlFormControlElement() const;
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;

protected:
#if ENABLE(WML)
RenderTextControl(ContainerNode*);
#else
RenderTextControl(HTMLTextFormControlElement*);
#endif

ource/core/rendering/RenderTextControl.cpp

#if ENABLE(WML)
RenderTextControl::RenderTextControl(ContainerNode* element)
#else
RenderTextControl(HTMLTextFormControlElement*)
#endif
WMLFormControlElement* RenderTextControl::wmlFormControlElement() const
{
return toWMLFormControlElement(node());
}

HTMLElement* RenderTextControl::innerTextElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlFormControlElement()->innerTextElement();
else
#endif

void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
#if ENABLE(WML)
if (node()->isWMLElement())
wmlFormControlElement()->updatePlaceholderVisibility(false);
else
#endif
void RenderTextControl::adjustInnerTextStyle(RenderStyle* textBlockStyle) const
{
// The inner block, if present, always has its direction set to LTR,
// so we need to inherit the direction and unicode-bidi style from the element.
textBlockStyle->setDirection(style()->direction());
textBlockStyle->setUnicodeBidi(style()->unicodeBidi());
#if ENABLE(WML)
if (node()->isWMLElement())
textBlockStyle->setUserModify(READ_WRITE_PLAINTEXT_ONLY);
else
#endif
void RenderTextControl::updateFromElement()
{
#if ENABLE(WML)
if (node()->isWMLElement()) {
Element* innerText = innerTextElement();
if (innerText && innerText->renderer())
innerText->renderer()->style()->setUserModify(READ_WRITE_PLAINTEXT_ONLY);
} else {
#endif
Element* innerText = innerTextElement();
if (innerText && innerText->renderer())
updateUserModifyProperty(textFormControlElement(), innerText->renderer()->style());
#if ENABLE(WML)
}
#endif
RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildren)
{
HTMLElement* placeholder;
if (node()->isWMLElement())
placeholder = toWMLInputElement(node())->placeholderElement();
else
placeholder = toHTMLTextFormControlElement(node())->placeholderElement();

Source/core/rendering/RenderTextControlSingleLine.h
public:
#if ENABLE(WML)
RenderTextControlSingleLine(ContainerNode*);
#else
RenderTextControlSingleLine(HTMLInputElement*);
#endif
WMLInputElement* wmlinputElement() const;

inline HTMLElement* RenderTextControlSingleLine::containerElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->containerElement();
else
#endif
return inputElement()->containerElement();
}

inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->innerBlockElement();
else
#endif

Source/core/rendering/RenderTextControlSingleLine.cpp
inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const
{
#if ENABLE(WML)
if (node()->isWMLElement())
return wmlinputElement()->innerSpinButtonElement();
else
#endif
HTMLElement* placeholderElement;
#if ENABLE(WML)
if (node()->isWMLElement())
placeholderElement = wmlinputElement()->placeholderElement();
else
#endif
placeholderElement = inputElement()->placeholderElement();

void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
m_desiredInnerTextLogicalHeight = -1;
RenderTextControl::styleDidChange(diff, oldStyle);

// We may have set the width and the height in the old style in layout().
// Reset them now to avoid getting a spurious layout hint.
HTMLElement* innerBlock = innerBlockElement();
if (RenderObject* innerBlockRenderer = innerBlock ? innerBlock->renderer() : 0) {
    innerBlockRenderer->style()->setHeight(Length());
    innerBlockRenderer->style()->setWidth(Length());
}
HTMLElement* container = containerElement();
if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
    containerRenderer->style()->setHeight(Length());
    containerRenderer->style()->setWidth(Length());
}
RenderObject* innerTextRenderer = innerTextElement()->renderer();
if (innerTextRenderer && diff == StyleDifferenceLayout)
    innerTextRenderer->setNeedsLayout(MarkContainingBlockChain);

#if ENABLE(WML)
if (node()->isWMLElement()) {
if (HTMLElement* placeholder = wmlinputElement()->placeholderElement())
placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
} else {
#endif

void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
{
if (Frame* frame = document()->frame())
#if ENABLE(WML)
if (node()->isWMLElement())
shouldDrawCapsLockIndicator = wmlinputElement()->isPasswordField() && frame->selection()->isFocusedAndActive() && document()->focusedElement() == node() && PlatformKeyboardEvent::currentCapsLockState();
else
#endif

LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charWidth) const
{
int factor;
bool includesDecoration;
#if ENABLE(WML)
if (node()->isWMLElement())
includesDecoration = wmlinputElement()->sizeShouldIncludeDecoration(factor);
else
#endif

WMLInputElement* RenderTextControlSingleLine::wmlinputElement() const
{
return toWMLInputElement(node());
}
}

Source/core/wml/WMLElement.h
virtual bool rendererIsNeeded(const NodeRenderingContext& context);
virtual RenderObject* createRenderer(RenderStyle*);

virtual void insertedIntoDocument() {}
virtual void removedFromDocument() {}

void addCSSProperty(Attribute* attribute, int id, const String &value)
{/*
	if (!attribute->decl())
		createMappedDecl(attribute);
	attribute->decl()->setProperty(id, value, false);*/
}

void addCSSLength(Attribute*, int id, const String& value) {}
void addCSSProperty(Attribute*, int id, int value) {}
virtual bool hasCustomFocusLogic() const;
virtual bool supportsFocus() const;

String contentEditable() const;
void setContentEditable(const String&, ExceptionState&);

virtual bool draggable() const;
void setDraggable(bool);

bool spellcheck() const;
void setSpellcheck(bool);
void click();

virtual void accessKeyAction(bool sendMouseEvents);
virtual short tabIndex() const;
void setTabIndex(int);

protected:
WMLElement(const QualifiedName& tagName, Document*);
virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;

// Helper function for derived classes
String parseValueSubstitutingVariableReferences(const AtomicString&, WMLErrorCode defaultErrorCode = WMLErrorInvalidVariableReference) const;
String parseValueForbiddingVariableReferences(const AtomicString&) const;
void addWMLLengthToStyle(MutableStylePropertySet*, CSSPropertyID, const String& value);
void applyAlignmentAttributeToStyle(const AtomicString&, MutableStylePropertySet*);
virtual String nodeName() const OVERRIDE FINAL;

private:
AtomicString eventNameForAttributeName(const QualifiedName& attrName) const;
};
inline WMLElement* toWMLElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isWMLElement());
return static_cast<WMLElement*>(node);
}

inline const WMLElement* toWMLElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->isWMLElement());
return static_cast<const WMLElement*>(node);
}

Source/core/wml/WMLElement.cpp
String WMLElement::nodeName() const
{
// FIXME: Would be nice to have an atomicstring lookup based off uppercase
// chars that does not have to copy the string on a hit in the hash.
// FIXME: We should have a way to detect XHTML elements and replace the hasPrefix() check with it.
if (document()->isWMLDocument() && !tagQName().hasPrefix())
return tagQName().localNameUpper();
return Element::nodeName();
}

void WMLElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
{
if (isIdAttributeName(name)
|| name == HTMLNames::classAttr
|| name == HTMLNames::styleAttr)
Element::collectStyleForPresentationAttribute(name, value, style);

if (name == HTMLNames::alignAttr) {
	if (equalIgnoringCase(value, "middle"))
		addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, CSSValueCenter);
	else
		addPropertyToPresentationAttributeStyle(style, CSSPropertyTextAlign, value);
} else if (name == HTMLNames::tabindexAttr) {
	String indexstring = value;
	int tabindex = 0;
	if (parseHTMLInteger(indexstring, tabindex)) {
		// Clamp tabindex to the range of 'short' to match Firefox's behavior.
		setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
	}

} else if (name == HTMLNames::contenteditableAttr) {
if (value.isEmpty() || equalIgnoringCase(value, “true”)) {
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWrite);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
} else if (equalIgnoringCase(value, “plaintext-only”)) {
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap, CSSValueBreakWord);
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak, CSSValueAfterWhiteSpace);
} else if (equalIgnoringCase(value, “false”))
addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitUserModify, CSSValueReadOnly);
} else
Element::collectStyleForPresentationAttribute(name, value, style);
}

AtomicString WMLElement::eventNameForAttributeName(const QualifiedName& attrName) const
{
return AtomicString();
}
void WMLElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (isIdAttributeName(name)
|| name == HTMLNames::classAttr
|| name == HTMLNames::styleAttr)
return Element::parseAttribute(name, value);

if (name == HTMLNames::tabindexAttr) {
    String indexstring = value;
    int tabindex = 0;
    if (parseHTMLInteger(indexstring, tabindex)) {
        // Clamp tabindex to the range of 'short' to match Firefox's behavior.
        setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
    }
} 

}

void WMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment, MutableStylePropertySet* style)
{
// Vertical alignment with respect to the current baseline of the text
// right or left means floating images.
CSSValueID floatValue = CSSValueInvalid;
CSSValueID verticalAlignValue = CSSValueInvalid;

if (equalIgnoringCase(alignment, "absmiddle"))
    verticalAlignValue = CSSValueMiddle;
else if (equalIgnoringCase(alignment, "absbottom"))
    verticalAlignValue = CSSValueBottom;
else if (equalIgnoringCase(alignment, "left")) {
    floatValue = CSSValueLeft;
    verticalAlignValue = CSSValueTop;
} else if (equalIgnoringCase(alignment, "right")) {
    floatValue = CSSValueRight;
    verticalAlignValue = CSSValueTop;
} else if (equalIgnoringCase(alignment, "top"))
    verticalAlignValue = CSSValueTop;
else if (equalIgnoringCase(alignment, "middle"))
    verticalAlignValue = CSSValueWebkitBaselineMiddle;
else if (equalIgnoringCase(alignment, "center"))
    verticalAlignValue = CSSValueMiddle;
else if (equalIgnoringCase(alignment, "bottom"))
    verticalAlignValue = CSSValueBaseline;
else if (equalIgnoringCase(alignment, "texttop"))
    verticalAlignValue = CSSValueTextTop;

if (floatValue != CSSValueInvalid)
    addPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, floatValue);

if (verticalAlignValue != CSSValueInvalid)
    addPropertyToPresentationAttributeStyle(style, CSSPropertyVerticalAlign, verticalAlignValue);

}

bool WMLElement::hasCustomFocusLogic() const
{
return false;
}

bool WMLElement::supportsFocus() const
{
// FIXME: supportsFocus() can be called when layout is not up to date.
// Logic that deals with the renderer should be moved to rendererIsFocusable().
// But supportsFocus must return true when the element is editable, or else
// it won’t be focusable. Furthermore, supportsFocus cannot just return true
// always or else tabIndex() will change for all HTML elements.
return Element::supportsFocus() || (rendererIsEditable() && parentNode() && !parentNode()->rendererIsEditable());
}

String WMLElement::contentEditable() const
{
const AtomicString& value = fastGetAttribute(HTMLNames::contenteditableAttr);

if (value.isNull())
    return "inherit";
if (value.isEmpty() || equalIgnoringCase(value, "true"))
    return "true";
if (equalIgnoringCase(value, "false"))
     return "false";
if (equalIgnoringCase(value, "plaintext-only"))
    return "plaintext-only";

return "inherit";

}

void WMLElement::setContentEditable(const String& enabled, ExceptionState& es)
{
if (equalIgnoringCase(enabled, “true”))
setAttribute(HTMLNames::contenteditableAttr, “true”);
else if (equalIgnoringCase(enabled, “false”))
setAttribute(HTMLNames::contenteditableAttr, “false”);
else if (equalIgnoringCase(enabled, “plaintext-only”))
setAttribute(HTMLNames::contenteditableAttr, “plaintext-only”);
else if (equalIgnoringCase(enabled, “inherit”))
removeAttribute(HTMLNames::contenteditableAttr);
else
es.throwDOMException(SyntaxError);
}

bool WMLElement::draggable() const
{
return equalIgnoringCase(getAttribute(HTMLNames::draggableAttr), “true”);
}

void WMLElement::setDraggable(bool value)
{
setAttribute(HTMLNames::draggableAttr, value ? “true” : “false”);
}

bool WMLElement::spellcheck() const
{
return isSpellCheckingEnabled();
}

void WMLElement::setSpellcheck(bool enable)
{
setAttribute(HTMLNames::spellcheckAttr, enable ? “true” : “false”);
}

void WMLElement::click()
{
dispatchSimulatedClick(0, SendNoEvents, DoNotShowPressedLook);
}

void WMLElement::accessKeyAction(bool sendMouseEvents)
{
dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}

short WMLElement::tabIndex() const
{
if (supportsFocus())
return Element::tabIndex();
return -1;
}

void WMLElement::setTabIndex(int value)
{
setAttribute(HTMLNames::tabindexAttr, String::number(value));
}

bool WMLElement::rendererIsNeeded(const NodeRenderingContext& context)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , " ");
/android::CallStack stack;
stack.update();
stack.dump(“Neo callstack”);
/
return document()->documentElement() == this || Element::rendererIsNeeded(context);
}

RenderObject* WMLElement::createRenderer(RenderStyle* style)
{
return RenderObject::createObject(this, style);
}

void WMLElement::addWMLLengthToStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, const String& value)
{
// FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
// length unit and make the appropriate parsed value.

// strip attribute garbage..
StringImpl* v = value.impl();
if (v) {
    unsigned int l = 0;

    while (l < v->length() && (*v)[l] <= ' ')
        l++;

    for (; l < v->length(); l++) {
        UChar cc = (*v)[l];
        if (cc > '9')
            break;
        if (cc < '0') {
            if (cc == '%' || cc == '*')
                l++;
            if (cc != '.')
                break;
        }
    }

    if (l != v->length()) {
        addPropertyToPresentationAttributeStyle(style, propertyID, v->substring(0, l));
        return;
    }
}

addPropertyToPresentationAttributeStyle(style, propertyID, value);

}

Source/core/wml/WMLFormControlElement.h

class ExceptionState;
class Position;
class RenderTextControl;
class VisiblePosition;
class WMLFormControlElement : public WMLElement {
public:
static PassRefPtr create(const QualifiedName&, Document*);
enum NeedsToCheckDirtyFlag {CheckDirtyFlag, IgnoreDirtyFlag};
virtual ~WMLFormControlElement();

virtual bool isFormControlElement() const { return true; }
virtual bool isReadOnlyFormControl() const { return false; }
virtual bool isTextFormControl() const { return true; }

virtual bool formControlValueMatchesRenderer() const { return m_valueMatchesRenderer; }
virtual void setFormControlValueMatchesRenderer(bool b = true) { m_valueMatchesRenderer = b; }
void attach(const AttachContext& context);
virtual bool supportsFocus() const;
virtual bool isFocusable() const;

// virtual void attach();
virtual void recalcStyle(StyleChange);
void setTextAsOfLastFormControlChangeEvent(const String& text) { m_textAsOfLastFormControlChangeEvent = text; }

void forwardEvent(Event*);


virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;

// The derived class should return true if placeholder processing is needed.
virtual bool supportsPlaceholder() const {}
String strippedPlaceholder() const;
bool placeholderShouldBeVisible() const;
virtual HTMLElement* placeholderElement() const {}
void updatePlaceholderVisibility(bool);
static void fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement);

VisiblePosition visiblePositionForIndex(int) const;
int indexForVisiblePosition(const VisiblePosition&) const;
int selectionStart() const;
int selectionEnd() const;
const AtomicString& selectionDirection() const;
void setSelectionStart(int);
void setSelectionEnd(int);
void setSelectionDirection(const String&);
void select();
virtual void setRangeText(const String& replacement, ExceptionState&);
virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&);
void setSelectionRange(int start, int end, const String& direction);
void setSelectionRange(int start, int end, TextFieldSelectionDirection = SelectionHasNoDirection);
PassRefPtr<Range> selection() const;
String selectedText() const;

virtual void dispatchFormControlChangeEvent();

virtual String value() const {};

virtual HTMLElement* innerTextElement() const { }

void selectionChanged(bool userTriggered);
bool lastChangeWasUserEdit() const;
void setInnerTextValue(const String&);
String innerTextValue() const;

String directionForFormData() const;

virtual void dispatchFormControlInputEvent();
void setNeedsValidityCheck();
void notifyFormStateChanged();
bool isDisabledOrReadOnly() const { return false; }

protected:
WMLFormControlElement(const QualifiedName&, Document*);
bool isPlaceholderEmpty() const;
virtual void updatePlaceholderText() { }

virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;

void cacheSelection(int start, int end, TextFieldSelectionDirection direction)
{
    m_cachedSelectionStart = start;
    m_cachedSelectionEnd = end;
    m_cachedSelectionDirection = direction;
}

void restoreCachedSelection();
bool hasCachedSelection() const { return m_cachedSelectionStart >= 0; }

virtual void defaultEventHandler(Event*);
virtual void subtreeHasChanged() {}

void setLastChangeWasNotUserEdit() { m_lastChangeWasUserEdit = false; }

String valueWithHardLineBreaks() const;

private:
int computeSelectionStart() const;
int computeSelectionEnd() const;
TextFieldSelectionDirection computeSelectionDirection() const;

// FIXME: Author shadows should be allowed
// https://bugs.webkit.org/show_bug.cgi?id=92608
virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; }

virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE;
virtual void dispatchBlurEvent(Element* newFocusedElement) OVERRIDE;

// Returns true if user-editable value is empty. Used to check placeholder visibility.
virtual bool isEmptyValue() const {}
// Returns true if suggested value is empty. Used to check placeholder visibility.
virtual bool isEmptySuggestedValue() const { return true; }
// Called in dispatchFocusEvent(), after placeholder process, before calling parent's dispatchFocusEvent().
virtual void handleFocusEvent(Element* /* oldFocusedNode */, FocusDirection) { }
// Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent().
virtual void handleBlurEvent() { }

String m_textAsOfLastFormControlChangeEvent;
bool m_lastChangeWasUserEdit;

int m_cachedSelectionStart;
int m_cachedSelectionEnd;
TextFieldSelectionDirection m_cachedSelectionDirection;
bool m_valueMatchesRenderer;

};
inline bool isWMLFormControlElement(const Node* node)
{
return node->isElementNode() && toElement(node)->isTextFormControl();
}

inline WMLFormControlElement* toWMLFormControlElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || isWMLFormControlElement(node));
return static_cast<WMLFormControlElement*>(node);
}

WMLFormControlElement* enclosingFormControl(const Position&);
/Fix me, Neo/
}
Source/core/wml/WMLFormControlElement.cpp
WMLFormControlElement::WMLFormControlElement(const QualifiedName& tagName, Document* document)
: WMLElement(tagName, document)
, m_valueMatchesRenderer(false)
, m_lastChangeWasUserEdit(false)
, m_cachedSelectionStart(-1)
, m_cachedSelectionEnd(-1)
, m_cachedSelectionDirection(SelectionHasNoDirection)
void WMLFormControlElement::attach(const AttachContext& context)
{
ASSERT(!attached());
PostAttachCallbackDisabler disabler(this);
WMLElement::attach(context);
if (renderer())
renderer()->updateFromElement();

Node::InsertionNotificationRequest WMLFormControlElement::insertedInto(ContainerNode* insertionPoint)
{
WMLElement::insertedInto(insertionPoint);
if (!insertionPoint->inDocument())
return InsertionDone;
String initialValue = value();
setTextAsOfLastFormControlChangeEvent(initialValue.isNull() ? emptyString() : initialValue);
return InsertionDone;
}

void WMLFormControlElement::dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
handleFocusEvent(oldFocusedElement, direction);
WMLElement::dispatchFocusEvent(oldFocusedElement, direction);
}

void WMLFormControlElement::dispatchBlurEvent(Element* newFocusedElement)
{
handleBlurEvent();
WMLElement::dispatchBlurEvent(newFocusedElement);
}

void WMLFormControlElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().webkitEditableContentChangedEvent && renderer() && renderer()->isTextControl()) {
m_lastChangeWasUserEdit = true;
subtreeHasChanged();
return;
}

WMLFormControlElement::defaultEventHandler(event);

}

void WMLFormControlElement::forwardEvent(Event* event)
{
if (event->type() == eventNames().blurEvent || event->type() == eventNames().focusEvent)
return;
innerTextElement()->defaultEventHandler(event);
}

String WMLFormControlElement::strippedPlaceholder() const
{
// According to the HTML5 specification, we need to remove CR and LF from
// the attribute value.
const AtomicString& attributeValue = fastGetAttribute(HTMLNames::placeholderAttr);
if (!attributeValue.contains(newlineCharacter) && !attributeValue.contains(carriageReturn))
return attributeValue;

StringBuilder stripped;
unsigned length = attributeValue.length();
stripped.reserveCapacity(length);
for (unsigned i = 0; i < length; ++i) {
    UChar character = attributeValue[i];
    if (character == newlineCharacter || character == carriageReturn)
        continue;
    stripped.append(character);
}
return stripped.toString();

}

static bool isNotLineBreak(UChar ch) { return ch != newlineCharacter && ch != carriageReturn; }

bool WMLFormControlElement::isPlaceholderEmpty() const
{
return true;
// const AtomicString& attributeValue = fastGetAttribute(placeholderAttr);
// return attributeValue.string().find(isNotLineBreak) == notFound;
}

bool WMLFormControlElement::placeholderShouldBeVisible() const
{
return supportsPlaceholder()
&& isEmptyValue()
&& isEmptySuggestedValue()
&& !isPlaceholderEmpty()
&& (document()->focusedElement() != this || (renderer() && renderer()->theme()->shouldShowPlaceholderWhenFocused()))
&& (!renderer() || renderer()->style()->visibility() == VISIBLE);
}

void WMLFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
{
if (!supportsPlaceholder())
return;
if (!placeholderElement() || placeholderValueChanged)
updatePlaceholderText();
HTMLElement* placeholder = placeholderElement();
if (!placeholder)
return;
placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden);
}

void WMLFormControlElement::fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement)
{
// FIXME: We should change the order of DOM nodes. But it makes an assertion
// failure in editing code.
if (!placeholder || !placeholder->renderer())
return;
RenderObject* placeholderRenderer = placeholder->renderer();
RenderObject* siblingRenderer = siblingElement->renderer();
if (!siblingRenderer)
return;
if (placeholderRenderer->nextSibling() == siblingRenderer)
return;
RenderObject* parentRenderer = placeholderRenderer->parent();
ASSERT(siblingRenderer->parent() == parentRenderer);
parentRenderer->removeChild(placeholderRenderer);
parentRenderer->addChild(placeholderRenderer, siblingRenderer);
}

void WMLFormControlElement::setSelectionStart(int start)
{
setSelectionRange(start, max(start, selectionEnd()), selectionDirection());
}

void WMLFormControlElement::setSelectionEnd(int end)
{
setSelectionRange(min(end, selectionStart()), end, selectionDirection());
}

void WMLFormControlElement::setSelectionDirection(const String& direction)
{
setSelectionRange(selectionStart(), selectionEnd(), direction);
}

void WMLFormControlElement::select()
{
setSelectionRange(0, numeric_limits::max(), SelectionHasNoDirection);
}

String WMLFormControlElement::selectedText() const
{
if (!isTextFormControl())
return String();
return value().substring(selectionStart(), selectionEnd() - selectionStart());
}

void WMLFormControlElement::dispatchFormControlChangeEvent()
{
if (m_textAsOfLastFormControlChangeEvent != value()) {
WMLElement::dispatchChangeEvent();
setTextAsOfLastFormControlChangeEvent(value());
}
setChangedSinceLastFormControlChangeEvent(false);
}

static inline bool hasVisibleTextArea(RenderTextControl* textControl, HTMLElement* innerText)
{
ASSERT(textControl);
return textControl->style()->visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height();
}

void WMLFormControlElement::setRangeText(const String& replacement, ExceptionState& es)
{
setRangeText(replacement, selectionStart(), selectionEnd(), String(), es);
}

void WMLFormControlElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& es)
{
if (start > end) {
es.throwDOMException(IndexSizeError);
return;
}

String text = innerTextValue();
unsigned textLength = text.length();
unsigned replacementLength = replacement.length();
unsigned newSelectionStart = selectionStart();
unsigned newSelectionEnd = selectionEnd();

start = std::min(start, textLength);
end = std::min(end, textLength);

if (start < end)
    text.replace(start, end - start, replacement);
else
    text.insert(replacement, start);

setInnerTextValue(text);

// FIXME: What should happen to the value (as in value()) if there's no renderer?
if (!renderer())
    return;

subtreeHasChanged();

if (equalIgnoringCase(selectionMode, "select")) {
    newSelectionStart = start;
    newSelectionEnd = start + replacementLength;
} else if (equalIgnoringCase(selectionMode, "start"))
    newSelectionStart = newSelectionEnd = start;
else if (equalIgnoringCase(selectionMode, "end"))
    newSelectionStart = newSelectionEnd = start + replacementLength;
else {
    // Default is "preserve".
    long delta = replacementLength - (end - start);

    if (newSelectionStart > end)
        newSelectionStart += delta;
    else if (newSelectionStart > start)
        newSelectionStart = start;

    if (newSelectionEnd > end)
        newSelectionEnd += delta;
    else if (newSelectionEnd > start)
        newSelectionEnd = start + replacementLength;
}

setSelectionRange(newSelectionStart, newSelectionEnd, SelectionHasNoDirection);

}

void WMLFormControlElement::setSelectionRange(int start, int end, const String& directionString)
{
TextFieldSelectionDirection direction = SelectionHasNoDirection;
if (directionString == “forward”)
direction = SelectionHasForwardDirection;
else if (directionString == “backward”)
direction = SelectionHasBackwardDirection;

return setSelectionRange(start, end, direction);

}

void WMLFormControlElement::setSelectionRange(int start, int end, TextFieldSelectionDirection direction)
{
document()->updateLayoutIgnorePendingStylesheets();

if (!renderer() || !renderer()->isTextControl())
    return;

end = max(end, 0);
start = min(max(start, 0), end);

if (!hasVisibleTextArea(toRenderTextControl(renderer()), innerTextElement())) {
    cacheSelection(start, end, SelectionHasNoDirection);
    return;
}
VisiblePosition startPosition = visiblePositionForIndex(start);
VisiblePosition endPosition;
if (start == end)
    endPosition = startPosition;
else
    endPosition = visiblePositionForIndex(end);

// startPosition and endPosition can be null position for example when
// "-webkit-user-select: none" style attribute is specified.
if (startPosition.isNotNull() && endPosition.isNotNull()) {
    ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() == this
        && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == this);
}
VisibleSelection newSelection;
if (direction == SelectionHasBackwardDirection)
    newSelection = VisibleSelection(endPosition, startPosition);
else
    newSelection = VisibleSelection(startPosition, endPosition);
newSelection.setIsDirectional(direction != SelectionHasNoDirection);

if (Frame* frame = document()->frame())
    frame->selection()->setSelection(newSelection);

}

VisiblePosition WMLFormControlElement::visiblePositionForIndex(int index) const
{
if (index <= 0)
return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTREAM);
RefPtr range = Range::create(document());
range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION);
CharacterIterator it(range.get());
it.advance(index - 1);
return VisiblePosition(it.range()->endPosition(), UPSTREAM);
}

int WMLFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
{
Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
if (enclosingFormControl(indexPosition) != this)
return 0;
RefPtr range = Range::create(indexPosition.document());
range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION);
range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
return TextIterator::rangeLength(range.get());
}

int WMLFormControlElement::selectionStart() const
{
if (!isTextFormControl())
return 0;
if (document()->focusedElement() != this && hasCachedSelection())
return m_cachedSelectionStart;

return computeSelectionStart();

}

int WMLFormControlElement::computeSelectionStart() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return 0;

return indexForVisiblePosition(frame->selection()->start());

}

int WMLFormControlElement::selectionEnd() const
{
if (!isTextFormControl())
return 0;
if (document()->focusedElement() != this && hasCachedSelection())
return m_cachedSelectionEnd;
return computeSelectionEnd();
}

int WMLFormControlElement::computeSelectionEnd() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return 0;

return indexForVisiblePosition(frame->selection()->end());

}

static const AtomicString& directionString(TextFieldSelectionDirection direction)
{
DEFINE_STATIC_LOCAL(const AtomicString, none, (“none”, AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, forward, (“forward”, AtomicString::ConstructFromLiteral));
DEFINE_STATIC_LOCAL(const AtomicString, backward, (“backward”, AtomicString::ConstructFromLiteral));

switch (direction) {
case SelectionHasNoDirection:
    return none;
case SelectionHasForwardDirection:
    return forward;
case SelectionHasBackwardDirection:
    return backward;
}

ASSERT_NOT_REACHED();
return none;

}

const AtomicString& WMLFormControlElement::selectionDirection() const
{
if (!isTextFormControl())
return directionString(SelectionHasNoDirection);
if (document()->focusedElement() != this && hasCachedSelection())
return directionString(m_cachedSelectionDirection);

return directionString(computeSelectionDirection());

}

TextFieldSelectionDirection WMLFormControlElement::computeSelectionDirection() const
{
ASSERT(isTextFormControl());
Frame* frame = document()->frame();
if (!frame)
return SelectionHasNoDirection;

const VisibleSelection& selection = frame->selection()->selection();
return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasForwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection;

}

static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*& containerNode, int& offsetInContainer)
{
if (node->isTextNode()) {
containerNode = node;
offsetInContainer = offset;
} else {
containerNode = node->parentNode();
offsetInContainer = node->nodeIndex() + offset;
}
}

PassRefPtr WMLFormControlElement::selection() const
{
if (!renderer() || !isTextFormControl() || !hasCachedSelection())
return 0;

int start = m_cachedSelectionStart;
int end = m_cachedSelectionEnd;

ASSERT(start <= end);
HTMLElement* innerText = innerTextElement();
if (!innerText)
    return 0;

if (!innerText->firstChild())
    return Range::create(document(), innerText, 0, innerText, 0);

int offset = 0;
Node* startNode = 0;
Node* endNode = 0;
for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) {
    ASSERT(!node->firstChild());
    ASSERT(node->isTextNode() || node->hasTagName(WMLNames::brTag));
    int length = node->isTextNode() ? lastOffsetInNode(node) : 1;

    if (offset <= start && start <= offset + length)
        setContainerAndOffsetForRange(node, start - offset, startNode, start);

    if (offset <= end && end <= offset + length) {
        setContainerAndOffsetForRange(node, end - offset, endNode, end);
        break;
    }

    offset += length;
}

if (!startNode || !endNode)
    return 0;

return Range::create(document(), startNode, start, endNode, end);

}

void WMLFormControlElement::restoreCachedSelection()
{
setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection);
}

void WMLFormControlElement::selectionChanged(bool userTriggered)
{
if (!renderer() || !isTextFormControl())
return;

// selectionStart() or selectionEnd() will return cached selection when this node doesn't have focus
cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelectionDirection());

if (Frame* frame = document()->frame()) {
    if (frame->selection()->isRange() && userTriggered)
        dispatchEvent(Event::create(eventNames().selectEvent, true, false));
}

}

void WMLFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == HTMLNames::placeholderAttr) {
updatePlaceholderVisibility(true);
UseCounter::count(document(), UseCounter::PlaceholderAttribute);
}
WMLElement::parseAttribute(name, value);
}

bool WMLFormControlElement::lastChangeWasUserEdit() const
{
if (!isTextFormControl())
return false;
return m_lastChangeWasUserEdit;
}

void WMLFormControlElement::setInnerTextValue(const String& value)
{
if (!isTextFormControl())
return;

bool textIsChanged = value != innerTextValue();
if (textIsChanged || !innerTextElement()->hasChildNodes()) {
    innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION);

    if (value.endsWith('\n') || value.endsWith('\r'))
        innerTextElement()->appendChild(WMLBRElement::create(WMLNames::brTag, document()), ASSERT_NO_EXCEPTION, AttachLazily);
}

setFormControlValueMatchesRenderer(true);

}

static String finishText(StringBuilder& result)
{
// Remove one trailing newline; there’s always one that’s collapsed out by rendering.
size_t size = result.length();
if (size && result[size - 1] == ‘\n’)
result.resize(–size);
return result.toString();
}

String WMLFormControlElement::innerTextValue() const
{
HTMLElement* innerText = innerTextElement();
if (!innerText || !isTextFormControl())
return emptyString();

StringBuilder result;
for (Node* node = innerText; node; node = NodeTraversal::next(node, innerText)) {
    if (node->hasTagName(WMLNames::brTag))
        result.append(newlineCharacter);
    else if (node->isTextNode())
        result.append(toText(node)->data());
}
return finishText(result);

}

static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
{
RootInlineBox* next;
for (; line; line = next) {
next = line->nextRootBox();
if (next && !line->endsWithBreak()) {
ASSERT(line->lineBreakObj());
breakNode = line->lineBreakObj()->node();
breakOffset = line->lineBreakPos();
line = next;
return;
}
}
breakNode = 0;
breakOffset = 0;
}

String WMLFormControlElement::valueWithHardLineBreaks() const
{
// FIXME: It’s not acceptable to ignore the HardWrap setting when there is no renderer.
// While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
HTMLElement* innerText = innerTextElement();
if (!innerText || !isTextFormControl())
return value();

RenderBlock* renderer = toRenderBlock(innerText->renderer());
if (!renderer)
    return value();

Node* breakNode;
unsigned breakOffset;
RootInlineBox* line = renderer->firstRootBox();
if (!line)
    return value();

getNextSoftBreak(line, breakNode, breakOffset);

StringBuilder result;
for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(node, innerText)) {
    if (node->hasTagName(WMLNames::brTag))
        result.append(newlineCharacter);
    else if (node->isTextNode()) {
        String data = toText(node)->data();
        unsigned length = data.length();
        unsigned position = 0;
        while (breakNode == node && breakOffset <= length) {
            if (breakOffset > position) {
                result.append(data, position, breakOffset - position);
                position = breakOffset;
                result.append(newlineCharacter);
            }
            getNextSoftBreak(line, breakNode, breakOffset);
        }
        result.append(data, position, length - position);
    }
    while (breakNode == node)
        getNextSoftBreak(line, breakNode, breakOffset);
}
return finishText(result);

}

WMLFormControlElement* enclosingFormControl(const Position& position)
{
ASSERT(position.isNull() || position.anchorType() == Position::PositionIsOffsetInAnchor
|| position.containerNode() || !position.anchorNode()->shadowHost()
|| (position.anchorNode()->parentNode() && position.anchorNode()->parentNode()->isShadowRoot()));

Node* container = position.containerNode();
if (!container)
    return 0;
Element* ancestor = container->shadowHost();
return ancestor && isWMLFormControlElement(ancestor) ? toWMLFormControlElement(ancestor) : 0;

}

String WMLFormControlElement::directionForFormData() const
{
/* for (const Element* element = this; element; element = parentHTMLElement(element)) {
const AtomicString& dirAttributeValue = element->fastGetAttribute(dirAttr);
if (dirAttributeValue.isNull())
continue;

    if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr"))
        return dirAttributeValue;

    if (equalIgnoringCase(dirAttributeValue, "auto")) {
        bool isAuto;
        TextDirection textDirection = static_cast<const HTMLElement*>(element)->directionalityIfhasDirAutoAttribute(isAuto);
        return textDirection == RTL ? "rtl" : "ltr";
    }
}

*/
return “ltr”;
}

void WMLFormControlElement::dispatchFormControlInputEvent()
{
setChangedSinceLastFormControlChangeEvent(true);
WMLElement::dispatchInputEvent();
}

void WMLFormControlElement::notifyFormStateChanged()
{
Frame* frame = document()->frame();
if (!frame)
return;

if (Page* page = frame->page())
    page->chrome().client()->formStateDidChange(this);

}

Source/core/wml/WMLInputElement.h
class InputType;
class VisiblePosition;

class WMLInputElement : public WMLFormControlElement{
public:
static PassRefPtr create(const QualifiedName&, Document*);

WMLInputElement(const QualifiedName& tagName, Document*);
virtual ~WMLInputElement();

// virtual InputElement* toInputElement() { return this; }

// virtual bool isKeyboardFocusable(KeyboardEvent*) const;
virtual bool isMouseFocusable() const;
virtual void updateFocusAppearance(bool restorePreviousSelection);
// virtual void aboutToUnload();

virtual bool isChecked() const { return false; }
virtual bool isAutofilled() const { return false; }
virtual bool isIndeterminate() const { return false; }
virtual bool isCheckbox() const ;
virtual bool isInputTypeHidden() const;

// virtual bool isPasswordField() const { return m_isPasswordField; }
virtual bool searchEventsShouldBeDispatched() const { return false; }

virtual const AtomicString& formControlName() const { }
virtual String convertFromVisibleValue(const String& value) const { }

virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; }
virtual void setChangedSinceLastFormControlChangeEvent(bool) {}

// virtual void select();
// virtual void parseMappedAttribute(Attribute*) { }
// virtual void copyNonAttributeProperties(const Element* source);

virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;

// virtual void cacheSelection(int start, int end);

virtual bool isAcceptableValue(const String&) const { return true; }

// virtual void documentDidBecomeActive();

// virtual void willMoveToNewOwnerDocument();
// virtual void didMoveToNewOwnerDocument();

bool isConformedToInputMask(const String&);
bool isConformedToInputMask(UChar, unsigned, bool isUserInput = true);

#if ENABLE(WCSS)
virtual InputElementData data() const { return m_data; }
#endif
// void dispatchFocusEvent(Element* oldFocusedElement, FocusDirection direction);
// void dispatchBlurEvent(Element* newFocusedElement);
VisiblePosition visiblePositionForIndex(int) const;
bool isRequired() const {return !m_isEmptyOk; }
// void fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement);

virtual bool hasBadInput() const OVERRIDE;
virtual bool patternMismatch() const OVERRIDE;
virtual bool rangeUnderflow() const OVERRIDE;
virtual bool rangeOverflow() const;

// virtual bool stepMismatch() const OVERRIDE;
virtual bool tooLong() const OVERRIDE;
virtual bool typeMismatch() const OVERRIDE;
virtual bool valueMissing() const OVERRIDE;
virtual String validationMessage() const OVERRIDE;

// Returns the minimum value for type=date, number, or range.  Don't call this for other types.
double minimum() const;
// Returns the maximum value for type=date, number, or range.  Don't call this for other types.
// This always returns a value which is >= minimum().
double maximum() const;
// Sets the "allowed value step" defined in the HTML spec to the specified double pointer.
// Returns false if there is no "allowed value step."

// bool getAllowedValueStep(Decimal*) const;
// StepRange createStepRange(AnyStepHandling) const;

// Decimal findClosestTickMarkValue(const Decimal&);

// Implementations of HTMLInputElement::stepUp() and stepDown().

/* void stepUp(int, ExceptionState&);
void stepDown(int, ExceptionState&);
void stepUp(ExceptionState& es) { stepUp(1, es); }
void stepDown(ExceptionState& es) { stepDown(1, es); }
// stepUp()/stepDown() for user-interaction.
bool isSteppable() const;
*/
bool isTextButton() const;

bool isRadioButton() const;
bool isTextField() const;
bool isSearchField() const;
bool isPasswordField() const;
bool isRangeControl() const;
bool isColorControl() const;

// FIXME: It's highly likely that any call site calling this function should instead
// be using a different one. Many input elements behave like text fields, and in addition
// any unknown input type is treated as text. Consider, for example, isTextField or
// isTextField && !isPasswordField.
bool isText() const;

bool isEmailField() const;
bool isFileUpload() const;
bool isImageButton() const;
bool isNumberField() const;
bool isSubmitButton() const;
bool isTelephoneField() const;
bool isURLField() const;
bool isDateField() const;
bool isDateTimeLocalField() const;
bool isMonthField() const;
bool isTimeField() const;
bool isWeekField() const;

#if ENABLE(INPUT_SPEECH)
bool isSpeechEnabled() const;
#endif

HTMLElement* containerElement() const;
virtual HTMLElement* innerTextElement() const;
HTMLElement* innerBlockElement() const;
HTMLElement* innerSpinButtonElement() const;

#if ENABLE(INPUT_SPEECH)
HTMLElement* speechButtonElement() const;
#endif
HTMLElement* sliderThumbElement() const;
HTMLElement* sliderTrackElement() const;
HTMLElement* passwordGeneratorButtonElement() const;
virtual HTMLElement* placeholderElement() const;

// bool checked() const { return m_isChecked; }
// void setChecked(bool, TextFieldEventBehavior = DispatchNoEvent);

// 'indeterminate' is a state independent of the checked state that causes the control to draw in a way that hides the actual state.
bool indeterminate() const { return m_isIndeterminate; }
void setIndeterminate(bool);
// shouldAppearChecked is used by the rendering tree/CSS while checked() is used by JS to determine checked state
bool shouldAppearChecked() const;
virtual bool shouldAppearIndeterminate() const OVERRIDE;

int size() const;
bool sizeShouldIncludeDecoration(int& preferredSize) const;

// void setType(const String&);

String value() const;
void setValue(const String&, ExceptionState&, TextFieldEventBehavior = DispatchNoEvent);
void setValue(const String&, TextFieldEventBehavior = DispatchNoEvent);
void setValueForUser(const String&);
// Checks if the specified string would be a valid value.
// We should not call this for types with no string value such as CHECKBOX and RADIO.
bool isValidValue(const String&) const;
bool hasDirtyValue() const { return !m_valueIfDirty.isNull(); };

String sanitizeValue(const String&) const;

String localizeValue(const String&) const;

// The value which is drawn by a renderer.
String visibleValue() const;

const String& suggestedValue() const;
void setSuggestedValue(const String&);

void setEditingValue(const String&);

/*
double valueAsDate() const;
void setValueAsDate(double, ExceptionState&);

double valueAsNumber() const;
void setValueAsNumber(double, ExceptionState&, TextFieldEventBehavior = DispatchNoEvent);

*/
String valueWithDefault() const;

void setValueFromRenderer(const String&);

/* int selectionStartForBinding(ExceptionState&) const;
int selectionEndForBinding(ExceptionState&) const;
String selectionDirectionForBinding(ExceptionState&) const;
void setSelectionStartForBinding(int, ExceptionState&);
void setSelectionEndForBinding(int, ExceptionState&);
void setSelectionDirectionForBinding(const String&, ExceptionState&);
void setSelectionRangeForBinding(int start, int end, ExceptionState&);
void setSelectionRangeForBinding(int start, int end, const String& direction, ExceptionState&);
/
virtual bool rendererIsNeeded(const NodeRenderingContext&);
virtual RenderObject
createRenderer(RenderStyle*);
// virtual void detach(const AttachContext& = AttachContext()) OVERRIDE;

// FIXME: For isActivatedSubmit and setActivatedSubmit, we should use the NVI-idiom here by making
// it private virtual in all classes and expose a public method in HTMLFormControlElement to call
// the private virtual method.
virtual bool isActivatedSubmit() const;
virtual void setActivatedSubmit(bool flag);

// String altText() const;

// int maxResults() const { return m_maxResults; }

String defaultValue() const;
void setDefaultValue(const String&);

// Vector acceptMIMETypes();
// Vector acceptFileExtensions();
// String accept() const;
// String alt() const;

void setSize(unsigned);
void setSize(unsigned, ExceptionState&);

// KURL src() const;

virtual int maxLength() const;

// void setMaxLength(int, ExceptionState&);

// bool multiple() const;

// bool isAutofilled() const { return m_isAutofilled; }
// void setAutofilled(bool = true);

// FileList* files();
// void setFiles(PassRefPtr);

// Returns true if the given DragData has more than one dropped files.

// bool receiveDroppedFiles(const DragData*);

// String droppedFileSystemId();

// Icon* icon() const;
// These functions are used for rendering the input active during a
// drag-and-drop operation.
// bool canReceiveDroppedFiles() const;
// void setCanReceiveDroppedFiles(bool);

// void onSearch();

void updateClearButtonVisibility();

// virtual bool willRespondToMouseClickEvents() OVERRIDE;

// HTMLElement* list() const;
// HTMLDataListElement* dataList() const;
// void listAttributeTargetChanged();

WMLInputElement* checkedRadioButtonForGroup() const;
bool isInRequiredRadioButtonGroup();

// Functions for InputType classes.
void setValueInternal(const String&, TextFieldEventBehavior);
bool valueAttributeWasUpdatedAfterParsing() const { return m_valueAttributeWasUpdatedAfterParsing; }

void cacheSelectionInResponseToSetValue(int caretOffset) { cacheSelection(caretOffset, caretOffset, SelectionHasNoDirection); }

// For test purposes.

// void selectColorInColorChooser(const Color&);

String defaultToolTip() const;

static const unsigned maximumLength;

unsigned height() const;
unsigned width() const;
void setHeight(unsigned);
void setWidth(unsigned);

virtual void blur() OVERRIDE;
void defaultBlur();

virtual const AtomicString& name() const OVERRIDE;

void beginEditing();
void endEditing();

virtual bool matchesReadOnlyPseudoClass() const OVERRIDE;
virtual bool matchesReadWritePseudoClass() const OVERRIDE;
virtual void setRangeText(const String& replacement, ExceptionState&) OVERRIDE;
virtual void setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState&) OVERRIDE;

// bool setupDateTimeChooserParameters(DateTimeChooserParameters&);

bool supportsInputModeAttribute() const;
virtual bool shouldAutocomplete() const;
virtual bool willRespondToMouseClickEvents() OVERRIDE;
bool isSteppable() const;

protected:
virtual void defaultEventHandler(Event*);
private:
friend class WMLCardElement;
void initialize();
virtual void didAddUserAgentShadowRoot(ShadowRoot*) OVERRIDE;

virtual void willChangeForm() OVERRIDE;
virtual void didChangeForm() OVERRIDE;
virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
virtual void removedFrom(ContainerNode*) OVERRIDE;

// virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE;

virtual bool hasCustomFocusLogic() const OVERRIDE;
virtual bool isKeyboardFocusable() const OVERRIDE;
virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE;
virtual bool isEnumeratable() const;
virtual bool supportLabels() const OVERRIDE;
virtual bool shouldUseInputMethod();

virtual bool isTextFormControl() const { return isTextField(); }

virtual bool canTriggerImplicitSubmission() const { return isTextField(); }

virtual const AtomicString& formControlType() const;

virtual bool shouldSaveAndRestoreFormControlState() const OVERRIDE;

// virtual FormControlState saveFormControlState() const OVERRIDE;
// virtual void restoreFormControlState(const FormControlState&) OVERRIDE;

virtual bool canStartSelection() const;

virtual void accessKeyAction(bool sendMouseEvents);

virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStylePropertySet*) OVERRIDE;

// virtual void finishParsingChildren();

virtual void copyNonAttributePropertiesFromElement(const Element&);

virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;

virtual bool appendFormData(FormDataList&, bool);

virtual bool isSuccessfulSubmitButton() const;

virtual void reset();

virtual void* preDispatchEventHandler(Event*);
virtual void postDispatchEventHandler(Event*, void* dataFromPreDispatch);

virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
virtual bool isInRange() const;
virtual bool isOutOfRange() const;

// virtual void addSubresourceAttributeURLs(ListHashSet&) const;

bool supportsMaxLength() const { return isTextType(); }
bool isTextType() const;
bool tooLong(const String&, NeedsToCheckDirtyFlag) const;

virtual bool supportsPlaceholder() const;
virtual void updatePlaceholderText();
virtual bool isEmptyValue() const OVERRIDE { return innerTextValue().isEmpty(); }
virtual bool isEmptySuggestedValue() const { return suggestedValue().isEmpty(); }
virtual void handleFocusEvent(Element* oldFocusedElement, FocusDirection) OVERRIDE;
virtual void handleBlurEvent();

virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
virtual bool isRequiredFormControl() const;
virtual bool recalcWillValidate() const;
virtual void requiredAttributeChanged() OVERRIDE;

void updateType();

virtual void subtreeHasChanged();

// void resetListAttributeTargetObserver();
void parseMaxLengthAttribute(const AtomicString&);
void updateValueIfNeeded();

bool canHaveSelection() const;

// Returns null if this isn't associated with any radio button group.

// CheckedRadioButtons* checkedRadioButtons() const;
// void addToRadioButtonGroup();
// void removeFromRadioButtonGroup();

String validateInputMask(const String&);
unsigned cursorPositionToMaskIndex(unsigned);
String constrainValue(const String&) const;

AtomicString m_name;
String m_valueIfDirty;
String m_suggestedValue;
int m_size;
int m_maxLength;
short m_maxResults;
bool m_isChecked : 1;
bool m_reflectsCheckedAttribute : 1;
bool m_isIndeterminate : 1;
bool m_hasType : 1;
bool m_isActivatedSubmit : 1;
unsigned m_autocomplete : 2; // AutoCompleteSetting
bool m_isAutofilled : 1;
bool m_hasNonEmptyList : 1;
bool m_stateRestored : 1;
bool m_parsingInProgress : 1;
bool m_valueAttributeWasUpdatedAfterParsing : 1;
bool m_wasModifiedByUser : 1;
bool m_canReceiveDroppedFiles : 1;
bool m_hasTouchEventHandler : 1;
bool m_isEmptyOk;

// InputElementData m_data;
// bool m_isPasswordField;
// bool m_wasChangedSinceLastChangeEvent;
// String m_formatMask;
// unsigned m_numOfCharsAllowedByMask;
OwnPtr m_inputType;
};
inline WMLInputElement* toWMLInputElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::inputTag));
return static_cast<WMLInputElement*>(node);
}

inline const WMLInputElement* toWMLInputElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::inputTag));
return static_cast<const WMLInputElement*>(node);
}
Source/core/wml/WMLInputElement.cpp
WMLInputElement::WMLInputElement(const QualifiedName& tagName, Document* doc)
: WMLFormControlElement(tagName, doc)
, m_isEmptyOk(false)
, m_maxResults(-1)
, m_isChecked(false)
, m_reflectsCheckedAttribute(true)
, m_isIndeterminate(false)
, m_hasType(false)
, m_isActivatedSubmit(false)
, m_isAutofilled(false)
, m_hasNonEmptyList(false)
, m_stateRestored(false)
, m_valueAttributeWasUpdatedAfterParsing(false)
, m_wasModifiedByUser(false)
, m_hasTouchEventHandler(false)
, m_inputType(InputType::createText(this))
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x”,this);
}

PassRefPtr WMLInputElement::create(const QualifiedName& tagName, Document* document)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, tagname=%s”,tagName.toString().utf8().data());
/android::CallStack stack;
stack.update();
stack.dump(“Neo callstack”);
/
RefPtr inputElement = adoptRef(new WMLInputElement(tagName, document));
inputElement->ensureUserAgentShadowRoot();
return inputElement.release();
}

void WMLInputElement::didAddUserAgentShadowRoot(ShadowRoot*)
{
m_inputType->createShadowSubtree();
}

WMLInputElement::~WMLInputElement()
{
// Need to remove form association while this is still an HTMLInputElement
// so that virtual functions are called correctly.
// setForm(0);
// setForm(0) may register this to a document-level radio button group.
// We should unregister it to avoid accessing a deleted object.
// if (isRadioButton())
// document()->formController()->checkedRadioButtons().removeButton(this);
}

/static const AtomicString& formatCodes()
{
DEFINE_STATIC_LOCAL(AtomicString, codes, (“AaNnXxMm”));
return codes;
}
/

const AtomicString& WMLInputElement::name() const
{
return m_name.isNull() ? emptyAtom : m_name;
}

/Vector WMLInputElement::filesFromFileInputFormControlState(const FormControlState& state)
{
return NULL;
}
/

HTMLElement* WMLInputElement::containerElement() const
{
return m_inputType->containerElement();
}

HTMLElement* WMLInputElement::innerTextElement() const
{
return m_inputType->innerTextElement();
}

HTMLElement* WMLInputElement::innerBlockElement() const
{
return m_inputType->innerBlockElement();
}

HTMLElement* WMLInputElement::innerSpinButtonElement() const
{
return NULL;
}

#if ENABLE(INPUT_SPEECH)
HTMLElement* WMLInputElement::speechButtonElement() const
{
return NULL;
}
#endif

HTMLElement* WMLInputElement::passwordGeneratorButtonElement() const
{
return NULL;
}

HTMLElement* WMLInputElement::sliderThumbElement() const
{
return NULL;
}

HTMLElement* WMLInputElement::sliderTrackElement() const
{
return NULL;
}

HTMLElement* WMLInputElement::placeholderElement() const
{
return m_inputType->placeholderElement();
}

bool WMLInputElement::shouldAutocomplete() const
{
return false;
}

bool WMLInputElement::isValidValue(const String& value) const
{
if (!m_inputType->canSetStringValue()) {
ASSERT_NOT_REACHED();
return false;
}
return !m_inputType->typeMismatchFor(value)
&& !m_inputType->stepMismatch(value)
&& !m_inputType->rangeUnderflow(value)
&& !m_inputType->rangeOverflow(value)
&& !tooLong(value, IgnoreDirtyFlag)
&& !m_inputType->patternMismatch(value)
&& !m_inputType->valueMissing(value);
}

bool WMLInputElement::tooLong() const
{
return willValidate() && tooLong(value(), CheckDirtyFlag);
}

bool WMLInputElement::typeMismatch() const
{
return willValidate() && m_inputType->typeMismatch();
}

bool WMLInputElement::valueMissing() const
{
return willValidate() && m_inputType->valueMissing(value());
}

bool WMLInputElement::hasBadInput() const
{
return willValidate() && m_inputType->hasBadInput();
}

bool WMLInputElement::patternMismatch() const
{
return willValidate() && m_inputType->patternMismatch(value());
}

bool WMLInputElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
{
// We use isTextType() instead of supportsMaxLength() because of the
// ‘virtual’ overhead.
/* if (!isTextType())
return false;
int max = maxLength();
if (max < 0)
return false;
if (check == CheckDirtyFlag) {
// Return false for the default value or a value set by a script even if
// it is longer than maxLength.
if (!hasDirtyValue() || !m_wasModifiedByUser)
return false;
}
return numGraphemeClusters(value) > static_cast(max);
*/
return false;
}

bool WMLInputElement::rangeUnderflow() const
{
return false;
// return willValidate() && m_inputType->rangeUnderflow(value());
}

bool WMLInputElement::rangeOverflow() const
{ return false;
// return willValidate() && m_inputType->rangeOverflow(value());
}

String WMLInputElement::validationMessage() const
{
/* if (!willValidate())
return String();

if (customError())
    return customValidationMessage();

return m_inputType->validationMessage();*/
return String();

}

double WMLInputElement::minimum() const
{
return m_inputType->minimum();
}

double WMLInputElement::maximum() const
{
return m_inputType->maximum();
}

void WMLInputElement::blur()
{
m_inputType->blur();
}

void WMLInputElement::defaultBlur()
{
WMLFormControlElement::blur();
}

bool WMLInputElement::hasCustomFocusLogic() const
{
return m_inputType->hasCustomFocusLogic();
}

bool WMLInputElement::isKeyboardFocusable() const
{
return m_inputType->isKeyboardFocusable();
// return WMLFormControlElement::isFocusable();
}

bool WMLInputElement::shouldShowFocusRingOnMouseFocus() const
{
return m_inputType->shouldShowFocusRingOnMouseFocus();
}

void WMLInputElement::updateFocusAppearance(bool restorePreviousSelection)
{
if (isTextField()) {
if (!restorePreviousSelection || !hasCachedSelection())
select();
else
restoreCachedSelection();
if (document()->frame())
document()->frame()->selection()->revealSelection();
} else
WMLFormControlElement::updateFocusAppearance(restorePreviousSelection);
}

void WMLInputElement::beginEditing()
{
if (!isTextField())
return;

if (Frame* frame = document()->frame())
    frame->editor()->textFieldDidBeginEditing(this);

}

void WMLInputElement::endEditing()
{
if (!isTextField())
return;

if (Frame* frame = document()->frame())
    frame->editor()->textFieldDidEndEditing(this);

}

bool WMLInputElement::shouldUseInputMethod()
{
return m_inputType->shouldUseInputMethod();
}

void WMLInputElement::handleFocusEvent(Element* oldFocusedElement, FocusDirection direction)
{
m_inputType->handleFocusEvent(oldFocusedElement, direction);
}

void WMLInputElement::handleBlurEvent()
{
m_inputType->handleBlurEvent();
}
void WMLInputElement::updateType()
{
OwnPtr newType = InputType::create(this, fastGetAttribute(HTMLNames::typeAttr));
bool hadType = m_hasType;
m_hasType = true;
if (m_inputType->formControlType() == newType->formControlType()) {
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x,formcontroltype=%s,typeAttr=%s”,this,newType->formControlType().string().utf8().data(),fastGetAttribute(HTMLNames::typeAttr).string().utf8().data());
return;
}
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, exe %x,formcontroltype=%s,typeAttr=%s”,this,newType->formControlType().string().utf8().data(),fastGetAttribute(HTMLNames::typeAttr).string().utf8().data());
if (hadType && !newType->canChangeFromAnotherType()) {
// Set the attribute back to the old value.
// Useful in case we were called from inside parseAttribute.
setAttribute(HTMLNames::typeAttr, formControlType());
return;
}

// removeFromRadioButtonGroup();

bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();

m_inputType->destroyShadowSubtree();

bool wasAttached = attached();
if (wasAttached)
    detach();

m_inputType = newType.release();
m_inputType->createShadowSubtree();

bool hasTouchEventHandler = m_inputType->hasTouchEventHandler();
if (hasTouchEventHandler != m_hasTouchEventHandler) {
    if (hasTouchEventHandler)
        document()->didAddTouchEventHandler(this);
    else
        document()->didRemoveTouchEventHandler(this);
    m_hasTouchEventHandler = hasTouchEventHandler;
}

// setNeedsWillValidateCheck();

bool willStoreValue = m_inputType->storesValueSeparateFromAttribute();

if (didStoreValue && !willStoreValue && hasDirtyValue()) {
    setAttribute(HTMLNames::valueAttr, m_valueIfDirty);
    m_valueIfDirty = String();
}
if (!didStoreValue && willStoreValue) {
    AtomicString valueString = fastGetAttribute(HTMLNames::valueAttr);
    m_valueIfDirty = sanitizeValue(valueString);
} else
    updateValueIfNeeded();

setFormControlValueMatchesRenderer(false);
m_inputType->updateInnerTextValue();

m_wasModifiedByUser = false;

if (didRespectHeightAndWidth != m_inputType->shouldRespectHeightAndWidthAttributes()) {
    ASSERT(elementData());
    if (const Attribute* height = getAttributeItem(HTMLNames::heightAttr))
        attributeChanged(HTMLNames::heightAttr, height->value());
    if (const Attribute* width = getAttributeItem(HTMLNames::widthAttr))
        attributeChanged(HTMLNames::widthAttr, width->value());
    if (const Attribute* align = getAttributeItem(HTMLNames::alignAttr))
        attributeChanged(HTMLNames::alignAttr, align->value());
}

if (wasAttached) {
    lazyAttach();
    if (document()->focusedElement() == this)
        document()->updateFocusAppearanceSoon(true /* restore selection */);
}

setChangedSinceLastFormControlChangeEvent(false);

// addToRadioButtonGroup();

setNeedsValidityCheck();
notifyFormStateChanged();

}
void WMLInputElement::subtreeHasChanged()
{
m_inputType->subtreeHasChanged();
// When typing in an input field, childrenChanged is not called, so we need to force the directionality check.
//calculateAndAdjustDirectionality();
}

const AtomicString& WMLInputElement::formControlType() const
{
return m_inputType->formControlType();
}

bool WMLInputElement::shouldSaveAndRestoreFormControlState() const
{
return false;
}

/*FormControlState HTMLInputElement::saveFormControlState() const
{
return m_inputType->saveFormControlState();
}

void HTMLInputElement::restoreFormControlState(const FormControlState& state)
{
m_inputType->restoreFormControlState(state);
m_stateRestored = true;
}*/

bool WMLInputElement::canStartSelection() const
{
if (!isTextField())
return false;
return WMLFormControlElement::canStartSelection();
}

bool WMLInputElement::canHaveSelection() const
{
return isTextField();
}

void WMLInputElement::accessKeyAction(bool sendMouseEvents)
{
m_inputType->accessKeyAction(sendMouseEvents);
}

bool WMLInputElement::isPresentationAttribute(const QualifiedName& name) const
{
if (name == HTMLNames::vspaceAttr || name == HTMLNames::hspaceAttr || name == HTMLNames::alignAttr || name == HTMLNames::widthAttr || name == HTMLNames::heightAttr)
return true;
return WMLFormControlElement::isPresentationAttribute(name);
}

void WMLInputElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStylePropertySet* style)
{
if (name == HTMLNames::vspaceAttr) {
addWMLLengthToStyle(style, CSSPropertyMarginTop, value);
addWMLLengthToStyle(style, CSSPropertyMarginBottom, value);
} else if (name == HTMLNames::hspaceAttr) {
addWMLLengthToStyle(style, CSSPropertyMarginLeft, value);
addWMLLengthToStyle(style, CSSPropertyMarginRight, value);
} else if (name == HTMLNames::alignAttr) {
if (m_inputType->shouldRespectAlignAttribute())
applyAlignmentAttributeToStyle(value, style);
} else if (name == HTMLNames::widthAttr) {
if (m_inputType->shouldRespectHeightAndWidthAttributes())
addWMLLengthToStyle(style, CSSPropertyWidth, value);
} else if (name == HTMLNames::heightAttr) {
if (m_inputType->shouldRespectHeightAndWidthAttributes())
addWMLLengthToStyle(style, CSSPropertyHeight, value);
} else
WMLFormControlElement::collectStyleForPresentationAttribute(name, value, style);
}

void WMLInputElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == HTMLNames::nameAttr) {
m_name = value;
WMLFormControlElement::parseAttribute(name, value);
// m_data.setName(parseValueForbiddingVariableReferences(value));
} else if (name == HTMLNames::typeAttr) {
// String type = parseValueForbiddingVariableReferences(value);
updateType();
/* if (value == “password”) {
OwnPtr newType = PasswordInputType::create(this);
m_inputType->destroyShadowSubtree();
m_inputType = newType.release();
m_inputType->createShadowSubtree();
}*/
} else if (name == HTMLNames::valueAttr) {
if (!hasDirtyValue()) {
updatePlaceholderVisibility(false);
setNeedsStyleRecalc();
}
setFormControlValueMatchesRenderer(false);
setNeedsValidityCheck();
m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
m_inputType->valueAttributeChanged();
// We only need to setChanged if the form is looking at the default value right now.
// if (m_data.value().isNull())
// setNeedsStyleRecalc();
// setFormControlValueMatchesRenderer(false);
} else if (name == HTMLNames::maxlengthAttr)
parseMaxLengthAttribute(value);
//InputElement::parseMaxLengthAttribute(m_data, this, this, NULL);
else if (name == HTMLNames::sizeAttr) {
int oldSize = m_size;
int valueAsInteger = value.toInt();
m_size = valueAsInteger > 0 ? valueAsInteger : 20;
if (m_size != oldSize && renderer())
renderer()->setNeedsLayoutAndPrefWidthsRecalc();
//InputElement::parseSizeAttribute(m_data, this, NULL);
} else if (name == WMLNames::formatAttr)
;//m_formatMask = validateInputMask(parseValueForbiddingVariableReferences(value));
else if (name == WMLNames::emptyokAttr)
m_isEmptyOk = (value == “true”);
else
WMLFormControlElement::parseAttribute(name, value);

// FIXME: Handle 'accesskey' attribute
// FIXME: Handle 'tabindex' attribute
// FIXME: Handle 'title' attribute

}

/void WMLInputElement::finishParsingChildren()
{
m_parsingInProgress = false;
WMLTextFormControlElement::finishParsingChildren();
if (!m_stateRestored) {
bool checked = hasAttribute(checkedAttr);
if (checked)
setChecked(checked);
m_reflectsCheckedAttribute = true;
}
}
/

bool WMLInputElement::rendererIsNeeded(const NodeRenderingContext& context)
{
return m_inputType->rendererIsNeeded() && WMLFormControlElement::rendererIsNeeded(context);
}

RenderObject* WMLInputElement::createRenderer(RenderStyle* style)
{
android_printLog(ANDROID_LOG_DEBUG,NEO_LOG_TAG , “, %x”,this);
return m_inputType->createRenderer(style);
// return new RenderTextControlSingleLine(this);
}

void WMLInputElement::attach(const AttachContext& context)
{
PostAttachCallbackDisabler disabler(this);

if (!m_hasType)
    updateType();
    
WMLFormControlElement::attach(context);

m_inputType->attach();

if (document()->focusedElement() == this)
    document()->updateFocusAppearanceSoon(true /* restore selection */);

}

void WMLInputElement::detach(const AttachContext& context)
{
WMLElement::detach(context);
setFormControlValueMatchesRenderer(false);
m_inputType->detach();
}

bool WMLInputElement::isSuccessfulSubmitButton() const
{
// HTML spec says that buttons must have names to be considered successful.
// However, other browsers do not impose this constraint. So we do not.
return false;//!isDisabledFormControl() && m_inputType->canBeSuccessfulSubmitButton();
}

bool WMLInputElement::isActivatedSubmit() const
{
return m_isActivatedSubmit;
}

void WMLInputElement::setActivatedSubmit(bool flag)
{
m_isActivatedSubmit = flag;
}

bool WMLInputElement::appendFormData(FormDataList& encoding, bool multipart)
{
return m_inputType->isFormDataAppendable() && m_inputType->appendFormData(encoding, multipart);
}

void WMLInputElement::reset()
{
/* if (m_inputType->storesValueSeparateFromAttribute())
setValue(String());

setAutofilled(false);
setChecked(hasAttribute(checkedAttr));
m_reflectsCheckedAttribute = true;*/

}

bool WMLInputElement::isTextField() const
{
return m_inputType->isTextField();
}

bool WMLInputElement::isTextType() const
{
return m_inputType->isTextType();
}

int WMLInputElement::size() const
{
return m_size;
}

bool WMLInputElement::sizeShouldIncludeDecoration(int& preferredSize) const
{
return m_inputType->sizeShouldIncludeDecoration(20, preferredSize);
}

void WMLInputElement::copyNonAttributePropertiesFromElement(const Element& source)
{
/* const WMLInputElement& sourceElement = static_cast<const WMLInputElement&>(source);

m_valueIfDirty = sourceElement.m_valueIfDirty;
m_wasModifiedByUser = false;
setChecked(sourceElement.m_isChecked);
m_reflectsCheckedAttribute = sourceElement.m_reflectsCheckedAttribute;
m_isIndeterminate = sourceElement.m_isIndeterminate;

WMLFormControlElement::copyNonAttributePropertiesFromElement(source);

setFormControlValueMatchesRenderer(false);
m_inputType->updateInnerTextValue();*/

}

String WMLInputElement::value() const
{
String value;
if (m_inputType->getTypeSpecificValue(value))
return value;

value = m_valueIfDirty;
if (!value.isNull())
    return value;

AtomicString valueString = fastGetAttribute(HTMLNames::valueAttr);
value = sanitizeValue(valueString);
if (!value.isNull())
    return value;

return m_inputType->fallbackValue();

}

String WMLInputElement::valueWithDefault() const
{
String value = this->value();
if (!value.isNull())
return value;

return m_inputType->defaultValue();

}

void WMLInputElement::setValueForUser(const String& value)
{
// Call setValue and make it send a change event.
setValue(value, DispatchChangeEvent);
}

const String& WMLInputElement::suggestedValue() const
{
return m_suggestedValue;
}

void WMLInputElement::setSuggestedValue(const String& value)
{
if (!m_inputType->canSetSuggestedValue())
return;
setFormControlValueMatchesRenderer(false);
m_suggestedValue = sanitizeValue(value);
setNeedsStyleRecalc();
m_inputType->updateInnerTextValue();
}

void WMLInputElement::setEditingValue(const String& value)
{
if (!renderer() || !isTextField())
return;
setInnerTextValue(value);
subtreeHasChanged();

unsigned max = value.length();
if (focused())
    setSelectionRange(max, max);
else
    cacheSelectionInResponseToSetValue(max);

dispatchInputEvent();

}

void WMLInputElement::setValue(const String& value, ExceptionState& es, TextFieldEventBehavior eventBehavior)
{
if (isFileUpload() && !value.isEmpty()) {
es.throwDOMException(InvalidStateError);
return;
}
setValue(value, eventBehavior);
}

void WMLInputElement::setValue(const String& value, TextFieldEventBehavior eventBehavior)
{
if (!m_inputType->canSetValue(value))
return;

RefPtr<WMLInputElement> protector(this);
EventQueueScope scope;
String sanitizedValue = sanitizeValue(value);
bool valueChanged = sanitizedValue != this->value();

setLastChangeWasNotUserEdit();
setFormControlValueMatchesRenderer(false);
m_suggestedValue = String(); // Prevent TextFieldInputType::setValue from using the suggested value.
m_inputType->setValue(sanitizedValue, valueChanged, eventBehavior);

if (!valueChanged)
    return;

// notifyFormStateChanged();
}

void WMLInputElement::setValueInternal(const String& sanitizedValue, TextFieldEventBehavior eventBehavior)
{
m_valueIfDirty = sanitizedValue;
m_wasModifiedByUser = eventBehavior != DispatchNoEvent;
setNeedsValidityCheck();
}

void WMLInputElement::setValueFromRenderer(const String& value)
{
// File upload controls will never use this.
ASSERT(!isFileUpload());

m_suggestedValue = String();

// Renderer and our event handler are responsible for sanitizing values.
ASSERT(value == sanitizeValue(value) || sanitizeValue(value).isEmpty());

m_valueIfDirty = value;

setFormControlValueMatchesRenderer(true);
m_wasModifiedByUser = true;

// Input event is fired by the Node::defaultEventHandler for editable controls.
if (!isTextField())
    dispatchInputEvent();

// notifyFormStateChanged();

setNeedsValidityCheck();

// Clear autofill flag (and yellow background) on user edit.

// setAutofilled(false);
}

void* WMLInputElement::preDispatchEventHandler(Event* event)
{
if (event->type() == eventNames().textInputEvent && m_inputType->shouldSubmitImplicitly(event)) {
event->stopPropagation();
return 0;
}
if (event->type() != eventNames().clickEvent)
return 0;
if (!event->isMouseEvent() || toMouseEvent(event)->button() != LeftButton)
return 0;
// FIXME: Check whether there are any cases where this actually ends up leaking.
return m_inputType->willDispatchClick().leakPtr();
}

void WMLInputElement::postDispatchEventHandler(Event* event, void* dataFromPreDispatch)
{
OwnPtr state = adoptPtr(static_cast<ClickHandlingState*>(dataFromPreDispatch));
if (!state)
return;
m_inputType->didDispatchClick(event, *state);
}

void WMLInputElement::defaultEventHandler(Event* evt)
{
if (evt->isMouseEvent() && evt->type() == eventNames().clickEvent && toMouseEvent(evt)->button() == LeftButton) {
m_inputType->handleClickEvent(toMouseEvent(evt));
if (evt->defaultHandled())
return;
}

if (evt->isTouchEvent()) {
    m_inputType->handleTouchEvent(static_cast<TouchEvent*>(evt));
    if (evt->defaultHandled())
        return;
}

if (evt->isKeyboardEvent() && evt->type() == eventNames().keydownEvent) {
    m_inputType->handleKeydownEvent(toKeyboardEvent(evt));
    if (evt->defaultHandled())
        return;
}

// Call the base event handler before any of our own event handling for almost all events in text fields.
// Makes editing keyboard handling take precedence over the keydown and keypress handling in this function.
bool callBaseClassEarly = isTextField() && (evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
if (callBaseClassEarly) {
    WMLFormControlElement::defaultEventHandler(evt);
    if (evt->defaultHandled())
        return;
}

// DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means
// actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks
// on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element
// must dispatch a DOMActivate event - a click event will not do the job.
if (evt->type() == eventNames().DOMActivateEvent) {
    m_inputType->handleDOMActivateEvent(evt);
    if (evt->defaultHandled())
        return;
}

// Use key press event here since sending simulated mouse events
// on key down blocks the proper sending of the key press event.
if (evt->isKeyboardEvent() && evt->type() == eventNames().keypressEvent) {
    m_inputType->handleKeypressEvent(toKeyboardEvent(evt));
    if (evt->defaultHandled())
        return;
}

if (evt->isKeyboardEvent() && evt->type() == eventNames().keyupEvent) {
    m_inputType->handleKeyupEvent(toKeyboardEvent(evt));
    if (evt->defaultHandled())
        return;
}

if (m_inputType->shouldSubmitImplicitly(evt)) {
    // Form submission finishes editing, just as loss of focus does.
    // If there was a change, send the event now.
    if (wasChangedSinceLastFormControlChangeEvent())
        dispatchFormControlChangeEvent();

/* RefPtr formForSubmission = m_inputType->formForSubmission();
// Form may never have been present, or may have been destroyed by code responding to the change event.
if (formForSubmission)
formForSubmission->submitImplicitly(evt, canTriggerImplicitSubmission());
*/
evt->setDefaultHandled();
return;
}

if (evt->isBeforeTextInsertedEvent())
    m_inputType->handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(evt));

if (evt->isMouseEvent() && evt->type() == eventNames().mousedownEvent) {
    m_inputType->handleMouseDownEvent(toMouseEvent(evt));
    if (evt->defaultHandled())
        return;
}

m_inputType->forwardEvent(evt);

if (!callBaseClassEarly && !evt->defaultHandled())
    WMLFormControlElement::defaultEventHandler(evt);

}

bool WMLInputElement::willRespondToMouseClickEvents()
{
return true;
// FIXME: Consider implementing willRespondToMouseClickEvents() in InputType if more accurate results are necessary.
/* if (!isDisabledFormControl())
return true;

return WMLFormControlElement::willRespondToMouseClickEvents();*/

}

bool WMLInputElement::isURLAttribute(const Attribute& attribute) const
{
return false;
// return attribute.name() == srcAttr || attribute.name() == formactionAttr || WMLFormControlElement::isURLAttribute(attribute);
}

String WMLInputElement::defaultValue() const
{
return fastGetAttribute(HTMLNames::valueAttr);
}

void WMLInputElement::setDefaultValue(const String &value)
{
// setAttribute(valueAttr, value);
}

int WMLInputElement::maxLength() const
{
return m_maxLength;
}

String WMLInputElement::visibleValue() const
{
return m_inputType->visibleValue();
}

String WMLInputElement::sanitizeValue(const String& proposedValue) const
{
if (proposedValue.isNull())
return proposedValue;
return m_inputType->sanitizeValue(proposedValue);
}

String WMLInputElement::localizeValue(const String& proposedValue) const
{
if (proposedValue.isNull())
return proposedValue;
return m_inputType->localizeValue(proposedValue);
}

bool WMLInputElement::isInRange() const
{
return m_inputType->isInRange(value());
}

bool WMLInputElement::isOutOfRange() const
{
return m_inputType->isOutOfRange(value());
}

bool WMLInputElement::isRequiredFormControl() const
{
return false;
// return m_inputType->supportsRequired() && isRequired();
}

bool WMLInputElement::matchesReadOnlyPseudoClass() const
{
return false;//m_inputType->supportsReadOnly() && isReadOnly();
}

bool WMLInputElement::matchesReadWritePseudoClass() const
{
return false;//m_inputType->supportsReadOnly() && !isReadOnly();
}

void WMLInputElement::updateClearButtonVisibility()
{
//m_inputType->updateClearButtonVisibility();
}

void WMLInputElement::willChangeForm()
{
// removeFromRadioButtonGroup();
// WMLFormControlElement::willChangeForm();
}

void WMLInputElement::didChangeForm()
{
// HTMLTextFormControlElement::didChangeForm();
// addToRadioButtonGroup();
}

Node::InsertionNotificationRequest WMLInputElement::insertedInto(ContainerNode* insertionPoint)
{
WMLFormControlElement::insertedInto(insertionPoint);
return InsertionDone;
}

void WMLInputElement::removedFrom(ContainerNode* insertionPoint)
{
/* if (insertionPoint->inDocument() && !form())
removeFromRadioButtonGroup();
HTMLTextFormControlElement::removedFrom(insertionPoint);
ASSERT(!inDocument());
resetListAttributeTargetObserver();*/
}

/void WMLInputElement::didMoveToNewDocument(Document oldDocument)
{
if (hasImageLoader())
imageLoader()->elementDidMoveToNewDocument();

if (oldDocument) {
    if (isRadioButton())
        oldDocument->formController()->checkedRadioButtons().removeButton(this);
    if (m_hasTouchEventHandler)
        oldDocument->didRemoveEventTargetNode(this);
}

if (m_hasTouchEventHandler)
    document()->didAddTouchEventHandler(this);

HTMLTextFormControlElement::didMoveToNewDocument(oldDocument);

}

void HTMLInputElement::addSubresourceAttributeURLs(ListHashSet& urls) const
{
HTMLTextFormControlElement::addSubresourceAttributeURLs(urls);

addSubresourceURL(urls, src());

}*/

bool WMLInputElement::recalcWillValidate() const
{
return true;//m_inputType->supportsValidation() && WMLFormControlElement::recalcWillValidate();
}

void WMLInputElement::requiredAttributeChanged()
{
// WMLFormControlElement::requiredAttributeChanged();
m_inputType->requiredAttributeChanged();
}
/*
void WMLInputElement::selectColorInColorChooser(const Color& color)
{
if (!m_inputType->isColorControl())
return;
static_cast<ColorInputType*>(m_inputType.get())->didChooseColor(color);
}

HTMLElement* HTMLInputElement::list() const
{
return dataList();
}

HTMLDataListElement* HTMLInputElement::dataList() const
{
if (!m_hasNonEmptyList)
return 0;

if (!m_inputType->shouldRespectListAttribute())
    return 0;

Element* element = treeScope()->getElementById(fastGetAttribute(listAttr));
if (!element)
    return 0;
if (!element->hasTagName(datalistTag))
    return 0;

return static_cast<HTMLDataListElement*>(element);

}

void HTMLInputElement::resetListAttributeTargetObserver()
{
if (inDocument())
m_listAttributeTargetObserver = ListAttributeTargetObserver::create(fastGetAttribute(listAttr), this);
else
m_listAttributeTargetObserver = nullptr;
}

void HTMLInputElement::listAttributeTargetChanged()
{
m_inputType->listAttributeTargetChanged();
}
*/
bool WMLInputElement::isSteppable() const
{
return false;//m_inputType->isSteppable();
}

bool WMLInputElement::isTextButton() const
{
return m_inputType->isTextButton();
}

bool WMLInputElement::isRadioButton() const
{
return m_inputType->isRadioButton();
}

bool WMLInputElement::isSearchField() const
{
return m_inputType->isSearchField();
}

bool WMLInputElement::isInputTypeHidden() const
{
return m_inputType->isHiddenType();
}

bool WMLInputElement::isPasswordField() const
{
return m_inputType->isPasswordField();
}

bool WMLInputElement::isCheckbox() const
{
return m_inputType->isCheckbox();
}

bool WMLInputElement::isRangeControl() const
{
return m_inputType->isRangeControl();
}

bool WMLInputElement::isColorControl() const
{
return m_inputType->isColorControl();
}

bool WMLInputElement::isText() const
{
return m_inputType->isTextType();
}

bool WMLInputElement::isEmailField() const
{
return m_inputType->isEmailField();
}

bool WMLInputElement::isFileUpload() const
{
return m_inputType->isFileUpload();
}

bool WMLInputElement::isImageButton() const
{
return m_inputType->isImageButton();
}

bool WMLInputElement::isNumberField() const
{
return m_inputType->isNumberField();
}

bool WMLInputElement::isSubmitButton() const
{
return m_inputType->isSubmitButton();
}

bool WMLInputElement::isTelephoneField() const
{
return m_inputType->isTelephoneField();
}

bool WMLInputElement::isURLField() const
{
return m_inputType->isURLField();
}

bool WMLInputElement::isDateField() const
{
return m_inputType->isDateField();
}

bool WMLInputElement::isDateTimeLocalField() const
{
return m_inputType->isDateTimeLocalField();
}

bool WMLInputElement::isMonthField() const
{
return m_inputType->isMonthField();
}

bool WMLInputElement::isTimeField() const
{
return m_inputType->isTimeField();
}

bool WMLInputElement::isWeekField() const
{
return m_inputType->isWeekField();
}

bool WMLInputElement::isEnumeratable() const
{
return m_inputType->isEnumeratable();
}

bool WMLInputElement::supportLabels() const
{
return m_inputType->supportLabels();
}

bool WMLInputElement::shouldAppearChecked() const
{
return m_inputType->isCheckable();
}

bool WMLInputElement::supportsPlaceholder() const
{
return m_inputType->supportsPlaceholder();
}

void WMLInputElement::updatePlaceholderText()
{
return m_inputType->updatePlaceholderText();
}

void WMLInputElement::parseMaxLengthAttribute(const AtomicString& value)
{
int maxLength;
if (!parseHTMLInteger(value, maxLength))
maxLength = maximumLength;
if (maxLength < 0 || maxLength > maximumLength)
maxLength = maximumLength;
int oldMaxLength = m_maxLength;
m_maxLength = maxLength;
if (oldMaxLength != maxLength)
updateValueIfNeeded();
setNeedsStyleRecalc();
setNeedsValidityCheck();
}

void WMLInputElement::updateValueIfNeeded()
{
String newValue = sanitizeValue(m_valueIfDirty);
ASSERT(!m_valueIfDirty.isNull() || newValue.isNull());
if (newValue != m_valueIfDirty)
setValue(newValue);
}

String WMLInputElement::defaultToolTip() const
{
return m_inputType->defaultToolTip();
}

bool WMLInputElement::shouldAppearIndeterminate() const
{
return false;//m_inputType->supportsIndeterminateAppearance() && indeterminate();
}

bool WMLInputElement::isInRequiredRadioButtonGroup()
{
/* ASSERT(isRadioButton());
if (CheckedRadioButtons* buttons = checkedRadioButtons())
return buttons->isInRequiredGroup(this);*/
return false;
}

WMLInputElement* WMLInputElement::checkedRadioButtonForGroup() const
{
/*
if (CheckedRadioButtons* buttons = checkedRadioButtons())
return buttons->checkedButtonForGroup(name());*/
return 0;
}

/*
CheckedRadioButtons* WMLInputElement::checkedRadioButtons() const
{
if (!isRadioButton())
return 0;
if (HTMLFormElement* formElement = form())
return &formElement->checkedRadioButtons();
if (inDocument())
return &document()->formController()->checkedRadioButtons();
return 0;
}

inline void WMLInputElement::addToRadioButtonGroup()
{
if (CheckedRadioButtons* buttons = checkedRadioButtons())
buttons->addButton(this);
}

inline void HTMLInputElement::removeFromRadioButtonGroup()
{
if (CheckedRadioButtons* buttons = checkedRadioButtons())
buttons->removeButton(this);
}*/

unsigned WMLInputElement::height() const
{
return m_inputType->height();
}

unsigned WMLInputElement::width() const
{
return m_inputType->width();
}

void WMLInputElement::setHeight(unsigned height)
{
setAttribute(HTMLNames::heightAttr, String::number(height));
}

void WMLInputElement::setWidth(unsigned width)
{
setAttribute(HTMLNames::widthAttr, String::number(width));
}

/PassOwnPtr ListAttributeTargetObserver::create(const AtomicString& id, HTMLInputElement element)
{
return adoptPtr(new ListAttributeTargetObserver(id, element));
}

ListAttributeTargetObserver::ListAttributeTargetObserver(const AtomicString& id, HTMLInputElement* element)
IdTargetObserver(element->treeScope()->idTargetObserverRegistry(), id)
, m_element(element)
{
}

void ListAttributeTargetObserver::idTargetChanged()
{
m_element->listAttributeTargetChanged();
}*/

void WMLInputElement::setRangeText(const String& replacement, ExceptionState& es)
{
if (!m_inputType->supportsSelectionAPI()) {
es.throwDOMException(InvalidStateError);
return;
}

WMLFormControlElement::setRangeText(replacement, es);

}

void WMLInputElement::setRangeText(const String& replacement, unsigned start, unsigned end, const String& selectionMode, ExceptionState& es)
{
if (!m_inputType->supportsSelectionAPI()) {
es.throwDOMException(InvalidStateError);
return;
}

WMLFormControlElement::setRangeText(replacement, start, end, selectionMode, es);

}

bool WMLInputElement::supportsInputModeAttribute() const
{
return m_inputType->supportsInputModeAttribute();
}

Source/core/wml/WMLOptGroupElement.h
inline bool isWMLOptGroupElement(const Node* node)
{
return node->hasTagName(WMLNames::optgroupTag);
}

inline bool isWMLOptGroupElement(const Element* element)
{
return element->hasTagName(WMLNames::optgroupTag);
}

inline WMLOptGroupElement* toWMLOptGroupElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || isWMLOptGroupElement(node));
return static_cast<WMLOptGroupElement*>(node);
}

Source/core/wml/WMLOptGroupElement.cpp
void WMLOptGroupElement::attach(const AttachContext& context)
{
if (parentNode()->renderStyle())
setRenderStyle(styleForRenderer());
WMLFormControlElement::attach(context);
}

void WMLOptGroupElement::detach(AttachContext& context)
{
m_style.clear();
WMLFormControlElement::detach(context);
}
Source/core/wml/WMLOptionElement.h

inline WMLOptionElement* toWMLOptionElement(Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::optionTag));
return static_cast<WMLOptionElement*>(node);
}

inline const WMLOptionElement* toWMLOptionElement(const Node* node)
{
ASSERT_WITH_SECURITY_IMPLICATION(!node || node->hasTagName(WMLNames::optionTag));
return static_cast<const WMLOptionElement*>(node);
}

Source/core/wml/WMLOptionElement.cpp
void WMLOptionElement::attach(const AttachContext& context)
{
if (parentNode()->renderStyle())
setRenderStyle(styleForRenderer());
WMLFormControlElement::attach(context);
}

void WMLOptionElement::detach(AttachContext& context)
{
m_style.clear();
WMLFormControlElement::detach(context);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值