void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) const
{
    ASSERT(event);
    ASSERT(renderer());
    int signedMaxLength = maxLength();
    if (signedMaxLength < 0)
        return;
    unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);

    const String& currentValue = innerTextValue();
    unsigned numberOfLineBreaksInCurrentValue = numberOfLineBreaks(currentValue);
    if (upperBoundForLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue)
        + upperBoundForLengthForSubmission(event->text(), numberOfLineBreaks(event->text())) < unsignedMaxLength)
        return;

    unsigned currentLength = computeLengthForSubmission(currentValue, numberOfLineBreaksInCurrentValue);
    // 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 = focused() ? computeLengthForSubmission(plainText(document().frame()->selection().selection().toNormalizedRange().get())) : 0;
    ASSERT(currentLength >= selectionLength);
    unsigned baseLength = currentLength - selectionLength;
    unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLength - baseLength : 0;
    event->setText(sanitizeUserInputValue(event->text(), appendableLength));
}
void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) const
{
    ASSERT(event);
    ASSERT(layoutObject());
    int signedMaxLength = maxLength();
    if (signedMaxLength < 0)
        return;
    unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);

    const String& currentValue = innerEditorValue();
    unsigned currentLength = computeLengthForSubmission(currentValue);
    if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxLength)
        return;

    // 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 = 0;
    if (focused()) {
        const EphemeralRange range = document().frame()->selection().selection().toNormalizedEphemeralRange();
        selectionLength = computeLengthForSubmission(plainText(range));
    }
    ASSERT(currentLength >= selectionLength);
    unsigned baseLength = currentLength - selectionLength;
    unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLength - baseLength : 0;
    event->setText(sanitizeUserInputValue(event->text(), appendableLength));
}
String HTMLTextAreaElement::validationMessage() const
{
    if (!willValidate())
        return String();

    if (customError())
        return customValidationMessage();

    if (valueMissing())
        return locale().queryString(blink::WebLocalizedString::ValidationValueMissing);

    if (tooLong())
        return locale().validationMessageTooLongText(computeLengthForSubmission(value()), maxLength());

    if (tooShort())
        return locale().validationMessageTooShortText(computeLengthForSubmission(value()), minLength());

    return String();
}
bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // longer than maxLength.
    if (check == CheckDirtyFlag && !m_wasModifiedByUser)
        return false;

    int max = maxLength();
    if (max < 0)
        return false;
    return computeLengthForSubmission(value) > static_cast<unsigned>(max);
}
bool HTMLTextAreaElement::tooLong(const String* value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // longer than maxLength.
    if (check == CheckDirtyFlag && !lastChangeWasUserEdit())
        return false;

    int max = maxLength();
    if (max < 0)
        return false;
    return computeLengthForSubmission(value ? *value : this->value()) > static_cast<unsigned>(max);
}
bool HTMLTextAreaElement::tooShort(const String* value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // shorter than minLength.
    if (check == CheckDirtyFlag && !lastChangeWasUserEdit())
        return false;

    int min = minLength();
    if (min <= 0)
        return false;
    // An empty string is excluded from minlength check.
    unsigned len = computeLengthForSubmission(value ? *value : this->value());
    return len > 0 && len < static_cast<unsigned>(min);
}
bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag check) const
{
    // Return false for the default value or value set by script even if it is
    // longer than maxLength.
    if (check == CheckDirtyFlag && !m_wasModifiedByUser)
        return false;

    int max = maxLength();
    if (max < 0)
        return false;
    unsigned unsignedMax = static_cast<unsigned>(max);
    unsigned numberOfLineBreaksInValue = numberOfLineBreaks(value);
    return upperBoundForLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax
        && computeLengthForSubmission(value, numberOfLineBreaksInValue) > unsignedMax;
}
String HTMLTextAreaElement::validationMessage() const
{
    if (!willValidate())
        return String();

    if (customError())
        return customValidationMessage();

    if (valueMissing())
        return validationMessageValueMissingText();

    if (tooLong())
        return validationMessageTooLongText(computeLengthForSubmission(value()), maxLength());

    return String();
}