Changeset 48698 in webkit


Ignore:
Timestamp:
Sep 23, 2009 7:55:39 PM (15 years ago)
Author:
eric@webkit.org
Message:

2009-09-23 Kent Tamura <tkent@chromium.org>

Reviewed by Darin Adler.

Tests for maxLength of <textarea>
https://bugs.webkit.org/show_bug.cgi?id=29292

  • fast/forms/script-tests/textarea-maxlength.js: Added.
  • fast/forms/textarea-maxlength-expected.txt: Added.
  • fast/forms/textarea-maxlength.html: Added.

2009-09-23 Kent Tamura <tkent@chromium.org>

Reviewed by Darin Adler.

Test: fast/forms/textarea-maxlength.html

  • dom/InputElement.cpp: (WebCore::InputElement::sanitizeUserInputValue): (WebCore::InputElement::handleBeforeTextInsertedEvent):
  • html/HTMLTextAreaElement.cpp: (WebCore::HTMLTextAreaElement::defaultEventHandler): (WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent): (WebCore::HTMLTextAreaElement::sanitizeUserInputValue): (WebCore::HTMLTextAreaElement::maxLength): (WebCore::HTMLTextAreaElement::setMaxLength):
  • html/HTMLTextAreaElement.h:
  • html/HTMLTextAreaElement.idl:
  • platform/text/PlatformString.h:
  • platform/text/String.cpp: (WebCore::String::numGraphemeClusters): (WebCore::String::numCharactersInGraphemeClusters):
Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r48697 r48698  
     12009-09-23  Kent Tamura  <tkent@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        Tests for maxLength of <textarea>
     6        https://bugs.webkit.org/show_bug.cgi?id=29292
     7
     8        * fast/forms/script-tests/textarea-maxlength.js: Added.
     9        * fast/forms/textarea-maxlength-expected.txt: Added.
     10        * fast/forms/textarea-maxlength.html: Added.
     11
    1122009-09-23  Martin Robinson  <martin.james.robinson@gmail.com>
    213
  • trunk/WebCore/ChangeLog

    r48697 r48698  
     12009-09-23  Kent Tamura  <tkent@chromium.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        - Support for maxLength of <textarea>
     6        - Move numGraphemeClusters() and numCharactersInGraphemeClusters() from InputElement to String.
     7        https://bugs.webkit.org/show_bug.cgi?id=29292
     8
     9        Test: fast/forms/textarea-maxlength.html
     10
     11        * dom/InputElement.cpp:
     12        (WebCore::InputElement::sanitizeUserInputValue):
     13        (WebCore::InputElement::handleBeforeTextInsertedEvent):
     14        * html/HTMLTextAreaElement.cpp:
     15        (WebCore::HTMLTextAreaElement::defaultEventHandler):
     16        (WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent):
     17        (WebCore::HTMLTextAreaElement::sanitizeUserInputValue):
     18        (WebCore::HTMLTextAreaElement::maxLength):
     19        (WebCore::HTMLTextAreaElement::setMaxLength):
     20        * html/HTMLTextAreaElement.h:
     21        * html/HTMLTextAreaElement.idl:
     22        * platform/text/PlatformString.h:
     23        * platform/text/String.cpp:
     24        (WebCore::String::numGraphemeClusters):
     25        (WebCore::String::numCharactersInGraphemeClusters):
     26
    1272009-09-23  Martin Robinson  <martin.james.robinson@gmail.com>
    228
  • trunk/WebCore/dom/InputElement.cpp

    r48449 r48698  
    3535#include "SelectionController.h"
    3636#include "TextIterator.h"
    37 #include "TextBreakIterator.h"
    3837
    3938#if ENABLE(WML)
     
    160159}
    161160
    162 static int numCharactersInGraphemeClusters(StringImpl* s, int numGraphemeClusters)
    163 {
    164     if (!s)
    165         return 0;
    166 
    167     TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
    168     if (!it)
    169         return 0;
    170 
    171     for (int i = 0; i < numGraphemeClusters; ++i) {
    172         if (textBreakNext(it) == TextBreakDone)
    173             return s->length();
    174     }
    175 
    176     return textBreakCurrent(it);
    177 }
    178 
    179161String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue)
    180162{
     
    192174    string.replace('\n', ' ');
    193175
    194     StringImpl* s = string.impl();
    195     int newLength = numCharactersInGraphemeClusters(s, maxLength);
    196     for (int i = 0; i < newLength; ++i) {
    197         const UChar& current = (*s)[i];
     176    unsigned newLength = string.numCharactersInGraphemeClusters(maxLength);
     177    for (unsigned i = 0; i < newLength; ++i) {
     178        const UChar current = string[i];
    198179        if (current < ' ' && current != '\t') {
    199180            newLength = i;
     
    201182        }
    202183    }
    203 
    204     if (newLength < static_cast<int>(string.length()))
    205         return string.left(newLength);
    206 
    207     return string;
    208 }
    209 
    210 static int numGraphemeClusters(StringImpl* s)
    211 {
    212     if (!s)
    213         return 0;
    214 
    215     TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
    216     if (!it)
    217         return 0;
    218 
    219     int num = 0;
    220     while (textBreakNext(it) != TextBreakDone)
    221         ++num;
    222 
    223     return num;
     184    return string.left(newLength);
    224185}
    225186
     
    232193    // because they can be mismatched by sanitizeValue() in
    233194    // RenderTextControlSingleLine::subtreeHasChanged() in some cases.
    234     int oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text().impl());
     195    unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters();
    235196
    236197    // selection() may be a pre-edit text.
    237     int selectionLength = numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).impl());
     198    unsigned selectionLength = plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
    238199    ASSERT(oldLength >= selectionLength);
    239200
    240201    // Selected characters will be removed by the next text event.
    241     int baseLength = oldLength - selectionLength;
    242     int appendableLength = data.maxLength() - baseLength;
     202    unsigned baseLength = oldLength - selectionLength;
     203    unsigned maxLength = static_cast<unsigned>(data.maxLength()); // maxLength() can never be negative.
     204    unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
    243205
    244206    // Truncate the inserted text to avoid violating the maxLength and other constraints.
  • trunk/WebCore/html/HTMLTextAreaElement.cpp

    r47702 r48698  
    2727#include "HTMLTextAreaElement.h"
    2828
     29#include "BeforeTextInsertedEvent.h"
    2930#include "ChromeClient.h"
    3031#include "CSSValueKeywords.h"
     
    3637#include "Frame.h"
    3738#include "HTMLNames.h"
     39#include "InputElement.h"
    3840#include "MappedAttribute.h"
    3941#include "Page.h"
     
    4244#include "ScriptEventListener.h"
    4345#include "Text.h"
     46#include "TextIterator.h"
    4447#include "VisibleSelection.h"
    4548#include <wtf/StdLibExtras.h>
     
    271274    if (renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent() || event->type() == eventNames().blurEvent))
    272275        toRenderTextControlMultiLine(renderer())->forwardEvent(event);
     276    else if (renderer() && event->isBeforeTextInsertedEvent())
     277        handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(event));
    273278
    274279    HTMLFormControlElementWithState::defaultEventHandler(event);
     280}
     281
     282void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) const
     283{
     284    ASSERT(event);
     285    ASSERT(renderer());
     286    bool ok;
     287    unsigned maxLength = getAttribute(maxlengthAttr).string().toUInt(&ok);
     288    if (!ok)
     289        return;
     290
     291    unsigned currentLength = toRenderTextControl(renderer())->text().numGraphemeClusters();
     292    unsigned selectionLength = plainText(document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
     293    ASSERT(currentLength >= selectionLength);
     294    unsigned baseLength = currentLength - selectionLength;
     295    unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
     296    event->setText(sanitizeUserInputValue(event->text(), appendableLength));
     297}
     298
     299String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, unsigned maxLength)
     300{
     301    return proposedValue.left(proposedValue.numCharactersInGraphemeClusters(maxLength));
    275302}
    276303
     
    375402}
    376403
     404unsigned HTMLTextAreaElement::maxLength() const
     405{
     406    return getAttribute(maxlengthAttr).string().toUInt();
     407}
     408
     409void HTMLTextAreaElement::setMaxLength(unsigned newValue)
     410{
     411    setAttribute(maxlengthAttr, String::number(newValue));
     412}
     413
    377414void HTMLTextAreaElement::accessKeyAction(bool)
    378415{
  • trunk/WebCore/html/HTMLTextAreaElement.h

    r48038 r48698  
    2929namespace WebCore {
    3030
     31class BeforeTextInsertedEvent;
    3132class VisibleSelection;
    3233
     
    7980    void setDefaultValue(const String&);
    8081    int textLength() const { return value().length(); }
     82    unsigned maxLength() const;
     83    void setMaxLength(unsigned);
    8184   
    8285    void rendererWillBeDestroyed();
     
    100103    enum WrapMethod { NoWrap, SoftWrap, HardWrap };
    101104
     105    void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const;
     106    static String sanitizeUserInputValue(const String&, unsigned maxLength);
    102107    void updateValue() const;
    103108    void updatePlaceholderVisibility(bool placeholderValueChanged);
  • trunk/WebCore/html/HTMLTextAreaElement.idl

    r48038 r48698  
    3535                 attribute  boolean              disabled;
    3636                 attribute  boolean              autofocus;
     37                 attribute  unsigned long        maxLength;
    3738                 attribute  [ConvertNullToNullString] DOMString            name;
    3839                 attribute  [ConvertNullToNullString, Reflect] DOMString   placeholder;
  • trunk/WebCore/platform/text/PlatformString.h

    r47144 r48698  
    255255    WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; }
    256256
     257    // Counts the number of grapheme clusters. A surrogate pair or a sequence
     258    // of a non-combining character and following combining characters is
     259    // counted as 1 grapheme cluster.
     260    unsigned numGraphemeClusters() const;
     261    // Returns the number of characters which will be less than or equal to
     262    // the specified grapheme cluster length.
     263    unsigned numCharactersInGraphemeClusters(unsigned) const;
     264
    257265private:
    258266    RefPtr<StringImpl> m_impl;
  • trunk/WebCore/platform/text/String.cpp

    r46566 r48698  
    2626#include "FloatConversion.h"
    2727#include "StringBuffer.h"
     28#include "TextBreakIterator.h"
    2829#include "TextEncoding.h"
    2930#include <wtf/dtoa.h>
     
    922923}
    923924
     925unsigned String::numGraphemeClusters() const
     926{
     927    TextBreakIterator* it = characterBreakIterator(characters(), length());
     928    if (!it)
     929        return length();
     930
     931    unsigned num = 0;
     932    while (textBreakNext(it) != TextBreakDone)
     933        ++num;
     934    return num;
     935}
     936
     937unsigned String::numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const
     938{
     939    TextBreakIterator* it = characterBreakIterator(characters(), length());
     940    if (!it)
     941        return min(length(), numGraphemeClusters);
     942
     943    for (unsigned i = 0; i < numGraphemeClusters; ++i) {
     944        if (textBreakNext(it) == TextBreakDone)
     945            return length();
     946    }
     947    return textBreakCurrent(it);
     948}
     949
    924950} // namespace WebCore
    925951
Note: See TracChangeset for help on using the changeset viewer.