Changeset 48698 in webkit
- Timestamp:
- Sep 23, 2009 7:55:39 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r48697 r48698 1 2009-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 1 12 2009-09-23 Martin Robinson <martin.james.robinson@gmail.com> 2 13 -
trunk/WebCore/ChangeLog
r48697 r48698 1 2009-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 1 27 2009-09-23 Martin Robinson <martin.james.robinson@gmail.com> 2 28 -
trunk/WebCore/dom/InputElement.cpp
r48449 r48698 35 35 #include "SelectionController.h" 36 36 #include "TextIterator.h" 37 #include "TextBreakIterator.h"38 37 39 38 #if ENABLE(WML) … … 160 159 } 161 160 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 179 161 String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue) 180 162 { … … 192 174 string.replace('\n', ' '); 193 175 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]; 198 179 if (current < ' ' && current != '\t') { 199 180 newLength = i; … … 201 182 } 202 183 } 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); 224 185 } 225 186 … … 232 193 // because they can be mismatched by sanitizeValue() in 233 194 // RenderTextControlSingleLine::subtreeHasChanged() in some cases. 234 int oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text().impl());195 unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters(); 235 196 236 197 // 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(); 238 199 ASSERT(oldLength >= selectionLength); 239 200 240 201 // 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; 243 205 244 206 // Truncate the inserted text to avoid violating the maxLength and other constraints. -
trunk/WebCore/html/HTMLTextAreaElement.cpp
r47702 r48698 27 27 #include "HTMLTextAreaElement.h" 28 28 29 #include "BeforeTextInsertedEvent.h" 29 30 #include "ChromeClient.h" 30 31 #include "CSSValueKeywords.h" … … 36 37 #include "Frame.h" 37 38 #include "HTMLNames.h" 39 #include "InputElement.h" 38 40 #include "MappedAttribute.h" 39 41 #include "Page.h" … … 42 44 #include "ScriptEventListener.h" 43 45 #include "Text.h" 46 #include "TextIterator.h" 44 47 #include "VisibleSelection.h" 45 48 #include <wtf/StdLibExtras.h> … … 271 274 if (renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent() || event->type() == eventNames().blurEvent)) 272 275 toRenderTextControlMultiLine(renderer())->forwardEvent(event); 276 else if (renderer() && event->isBeforeTextInsertedEvent()) 277 handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(event)); 273 278 274 279 HTMLFormControlElementWithState::defaultEventHandler(event); 280 } 281 282 void 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 299 String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, unsigned maxLength) 300 { 301 return proposedValue.left(proposedValue.numCharactersInGraphemeClusters(maxLength)); 275 302 } 276 303 … … 375 402 } 376 403 404 unsigned HTMLTextAreaElement::maxLength() const 405 { 406 return getAttribute(maxlengthAttr).string().toUInt(); 407 } 408 409 void HTMLTextAreaElement::setMaxLength(unsigned newValue) 410 { 411 setAttribute(maxlengthAttr, String::number(newValue)); 412 } 413 377 414 void HTMLTextAreaElement::accessKeyAction(bool) 378 415 { -
trunk/WebCore/html/HTMLTextAreaElement.h
r48038 r48698 29 29 namespace WebCore { 30 30 31 class BeforeTextInsertedEvent; 31 32 class VisibleSelection; 32 33 … … 79 80 void setDefaultValue(const String&); 80 81 int textLength() const { return value().length(); } 82 unsigned maxLength() const; 83 void setMaxLength(unsigned); 81 84 82 85 void rendererWillBeDestroyed(); … … 100 103 enum WrapMethod { NoWrap, SoftWrap, HardWrap }; 101 104 105 void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const; 106 static String sanitizeUserInputValue(const String&, unsigned maxLength); 102 107 void updateValue() const; 103 108 void updatePlaceholderVisibility(bool placeholderValueChanged); -
trunk/WebCore/html/HTMLTextAreaElement.idl
r48038 r48698 35 35 attribute boolean disabled; 36 36 attribute boolean autofocus; 37 attribute unsigned long maxLength; 37 38 attribute [ConvertNullToNullString] DOMString name; 38 39 attribute [ConvertNullToNullString, Reflect] DOMString placeholder; -
trunk/WebCore/platform/text/PlatformString.h
r47144 r48698 255 255 WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; } 256 256 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 257 265 private: 258 266 RefPtr<StringImpl> m_impl; -
trunk/WebCore/platform/text/String.cpp
r46566 r48698 26 26 #include "FloatConversion.h" 27 27 #include "StringBuffer.h" 28 #include "TextBreakIterator.h" 28 29 #include "TextEncoding.h" 29 30 #include <wtf/dtoa.h> … … 922 923 } 923 924 925 unsigned 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 937 unsigned 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 924 950 } // namespace WebCore 925 951
Note: See TracChangeset
for help on using the changeset viewer.