summaryrefslogtreecommitdiffstats
path: root/WebCore/wml/WMLInputElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/wml/WMLInputElement.cpp')
-rw-r--r--WebCore/wml/WMLInputElement.cpp225
1 files changed, 204 insertions, 21 deletions
diff --git a/WebCore/wml/WMLInputElement.cpp b/WebCore/wml/WMLInputElement.cpp
index 05da2a7..9a44013 100644
--- a/WebCore/wml/WMLInputElement.cpp
+++ b/WebCore/wml/WMLInputElement.cpp
@@ -23,7 +23,6 @@
#if ENABLE(WML)
#include "WMLInputElement.h"
-#include "Document.h"
#include "EventNames.h"
#include "FormDataList.h"
#include "Frame.h"
@@ -31,6 +30,9 @@
#include "KeyboardEvent.h"
#include "RenderTextControlSingleLine.h"
#include "TextEvent.h"
+#include "WMLDocument.h"
+#include "WMLNames.h"
+#include "WMLPageState.h"
namespace WebCore {
@@ -38,6 +40,8 @@ WMLInputElement::WMLInputElement(const QualifiedName& tagName, Document* doc)
: WMLFormControlElementWithState(tagName, doc)
, m_data(this, this)
, m_isPasswordField(false)
+ , m_isEmptyOk(false)
+ , m_numOfCharsAllowedByMask(0)
{
}
@@ -47,30 +51,20 @@ WMLInputElement::~WMLInputElement()
document()->unregisterForDocumentActivationCallbacks(this);
}
-static inline bool isInputFocusable(RenderObject* renderer)
+static const AtomicString& formatCodes()
{
- if (!renderer || !renderer->isBox())
- return false;
-
- if (toRenderBox(renderer)->size().isEmpty())
- return false;
-
- if (RenderStyle* style = renderer->style()) {
- if (style->visibility() != VISIBLE)
- return false;
- }
-
- return true;
+ DEFINE_STATIC_LOCAL(AtomicString, codes, ("AaNnXxMm"));
+ return codes;
}
bool WMLInputElement::isKeyboardFocusable(KeyboardEvent*) const
{
- return isInputFocusable(renderer());
+ return WMLFormControlElementWithState::isFocusable();
}
bool WMLInputElement::isMouseFocusable() const
{
- return isInputFocusable(renderer());
+ return WMLFormControlElementWithState::isFocusable();
}
void WMLInputElement::dispatchFocusEvent()
@@ -81,6 +75,18 @@ void WMLInputElement::dispatchFocusEvent()
void WMLInputElement::dispatchBlurEvent()
{
+ // Firstly check if it is allowed to leave this input field
+ String val = value();
+ if ((!m_isEmptyOk && val.isEmpty()) || !isConformedToInputMask(val)) {
+ updateFocusAppearance(true);
+ return;
+ }
+
+ // update the name variable of WML input elmenet
+ String nameVariable = name();
+ if (!nameVariable.isEmpty())
+ wmlPageStateForDocument(document())->storeVariable(nameVariable, val);
+
InputElement::dispatchBlurEvent(m_data, document());
WMLElement::dispatchBlurEvent();
}
@@ -168,7 +174,7 @@ void WMLInputElement::restoreState(const String& state)
void WMLInputElement::select()
{
- if (RenderTextControl* r = static_cast<RenderTextControl*>(renderer()))
+ if (RenderTextControl* r = toRenderTextControl(renderer()))
r->select();
}
@@ -194,12 +200,14 @@ void WMLInputElement::parseMappedAttribute(MappedAttribute* attr)
InputElement::parseMaxLengthAttribute(m_data, attr);
else if (attr->name() == HTMLNames::sizeAttr)
InputElement::parseSizeAttribute(m_data, attr);
+ else if (attr->name() == WMLNames::formatAttr)
+ m_formatMask = validateInputMask(parseValueForbiddingVariableReferences(attr->value()));
+ else if (attr->name() == WMLNames::emptyokAttr)
+ m_isEmptyOk = (attr->value() == "true");
else
WMLElement::parseMappedAttribute(attr);
// FIXME: Handle 'accesskey' attribute
- // FIXME: Handle 'format' attribute
- // FIXME: Handle 'emptyok' attribute
// FIXME: Handle 'tabindex' attribute
// FIXME: Handle 'title' attribute
}
@@ -226,6 +234,13 @@ void WMLInputElement::attach()
// on the renderer.
if (renderer())
renderer()->updateFromElement();
+
+ // FIXME: maybe this is not a good place to do this since it is possible
+ // to cause unexpected several times initialise of <input> if we force the
+ // node to be reattached. But placing it here can ensure the run-webkit-tests
+ // get expected result,i.e. multiple-times initialise is expected when making
+ // layout test for WMLInputElement
+ init();
}
void WMLInputElement::detach()
@@ -252,8 +267,14 @@ void WMLInputElement::defaultEventHandler(Event* evt)
{
bool clickDefaultFormButton = false;
- if (evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n")
- clickDefaultFormButton = true;
+ if (evt->type() == eventNames().textInputEvent && evt->isTextEvent()) {
+ TextEvent* textEvent = static_cast<TextEvent*>(evt);
+ if (textEvent->data() == "\n")
+ clickDefaultFormButton = true;
+ else if (renderer() && !isConformedToInputMask(textEvent->data()[0], toRenderTextControl(renderer())->text().length() + 1))
+ // If the inputed char doesn't conform to the input mask, stop handling
+ return;
+ }
if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame()
&& document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) {
@@ -338,6 +359,168 @@ void WMLInputElement::didMoveToNewOwnerDocument()
WMLElement::didMoveToNewOwnerDocument();
}
+void WMLInputElement::init()
+{
+ String nameVariable = name();
+ String variableValue;
+ WMLPageState* pageSate = wmlPageStateForDocument(document());
+ ASSERT(pageSate);
+ if (!nameVariable.isEmpty())
+ variableValue = pageSate->getVariable(nameVariable);
+
+ if (variableValue.isEmpty() || !isConformedToInputMask(variableValue)) {
+ String val = value();
+ if (isConformedToInputMask(val))
+ variableValue = val;
+ else
+ variableValue = "";
+
+ pageSate->storeVariable(nameVariable, variableValue);
+ }
+ setValue(variableValue);
+
+ if (!hasAttribute(WMLNames::emptyokAttr)) {
+ if (m_formatMask.isEmpty() ||
+ // check if the format codes is just "*f"
+ (m_formatMask.length() == 2 && m_formatMask[0] == '*' && formatCodes().find(m_formatMask[1]) != -1))
+ m_isEmptyOk = true;
+ }
+}
+
+String WMLInputElement::validateInputMask(const String& inputMask)
+{
+ bool isValid = true;
+ bool hasWildcard = false;
+ unsigned escapeCharCount = 0;
+ unsigned maskLength = inputMask.length();
+ UChar formatCode;
+
+ for (unsigned i = 0; i < maskLength; ++i) {
+ formatCode = inputMask[i];
+ if (formatCodes().find(formatCode) == -1) {
+ if (formatCode == '*' || (WTF::isASCIIDigit(formatCode) && formatCode != '0')) {
+ // validate codes which ends with '*f' or 'nf'
+ formatCode = inputMask[++i];
+ if ((i + 1 != maskLength) || formatCodes().find(formatCode) == -1) {
+ isValid = false;
+ break;
+ }
+ hasWildcard = true;
+ } else if (formatCode == '\\') {
+ //skip over the next mask character
+ ++i;
+ ++escapeCharCount;
+ } else {
+ isValid = false;
+ break;
+ }
+ }
+ }
+
+ if (!isValid)
+ return String();
+
+ // calculate the number of characters allowed to be entered by input mask
+ m_numOfCharsAllowedByMask = maskLength;
+
+ if (escapeCharCount)
+ m_numOfCharsAllowedByMask -= escapeCharCount;
+
+ if (hasWildcard) {
+ formatCode = inputMask[maskLength - 2];
+ if (formatCode == '*')
+ m_numOfCharsAllowedByMask = m_data.maxLength();
+ else {
+ unsigned leftLen = String(&formatCode).toInt();
+ m_numOfCharsAllowedByMask = leftLen + m_numOfCharsAllowedByMask - 2;
+ }
+ }
+
+ return inputMask;
+}
+
+bool WMLInputElement::isConformedToInputMask(const String& inputChars)
+{
+ for (unsigned i = 0; i < inputChars.length(); ++i)
+ if (!isConformedToInputMask(inputChars[i], i + 1, false))
+ return false;
+
+ return true;
+}
+
+bool WMLInputElement::isConformedToInputMask(UChar inChar, unsigned inputCharCount, bool isUserInput)
+{
+ if (m_formatMask.isEmpty())
+ return true;
+
+ if (inputCharCount > m_numOfCharsAllowedByMask)
+ return false;
+
+ unsigned maskIndex = 0;
+ if (isUserInput) {
+ unsigned cursorPosition = 0;
+ if (renderer())
+ cursorPosition = toRenderTextControl(renderer())->selectionStart();
+ else
+ cursorPosition = m_data.cachedSelectionStart();
+
+ maskIndex = cursorPositionToMaskIndex(cursorPosition);
+ } else
+ maskIndex = cursorPositionToMaskIndex(inputCharCount - 1);
+
+ bool ok = true;
+ UChar mask = m_formatMask[maskIndex];
+ // match the inputed character with input mask
+ switch (mask) {
+ case 'A':
+ ok = !WTF::isASCIIDigit(inChar) && !WTF::isASCIILower(inChar) && WTF::isASCIIPrintable(inChar);
+ break;
+ case 'a':
+ ok = !WTF::isASCIIDigit(inChar) && !WTF::isASCIIUpper(inChar) && WTF::isASCIIPrintable(inChar);
+ break;
+ case 'N':
+ ok = WTF::isASCIIDigit(inChar);
+ break;
+ case 'n':
+ ok = !WTF::isASCIIAlpha(inChar) && WTF::isASCIIPrintable(inChar);
+ break;
+ case 'X':
+ ok = !WTF::isASCIILower(inChar) && WTF::isASCIIPrintable(inChar);
+ break;
+ case 'x':
+ ok = !WTF::isASCIIUpper(inChar) && WTF::isASCIIPrintable(inChar);
+ break;
+ case 'M':
+ ok = WTF::isASCIIPrintable(inChar);
+ break;
+ case 'm':
+ ok = WTF::isASCIIPrintable(inChar);
+ break;
+ default:
+ ok = (mask == inChar);
+ break;
+ }
+
+ return ok;
+}
+
+unsigned WMLInputElement::cursorPositionToMaskIndex(unsigned cursorPosition)
+{
+ UChar mask;
+ int index = -1;
+ do {
+ mask = m_formatMask[++index];
+ if (mask == '\\')
+ ++index;
+ else if (mask == '*' || (WTF::isASCIIDigit(mask) && mask != '0')) {
+ index = m_formatMask.length() - 1;
+ break;
+ }
+ } while (cursorPosition--);
+
+ return index;
+}
+
}
#endif