| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) | 7 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 using namespace HTMLNames; | 53 using namespace HTMLNames; |
| 54 | 54 |
| 55 static const int defaultRows = 2; | 55 static const int defaultRows = 2; |
| 56 static const int defaultCols = 20; | 56 static const int defaultCols = 20; |
| 57 | 57 |
| 58 // On submission, LF characters are converted into CRLF. | 58 // On submission, LF characters are converted into CRLF. |
| 59 // This function returns number of characters considering this. | 59 // This function returns number of characters considering this. |
| 60 static inline unsigned computeLengthForSubmission(const String& text, unsigned n
umberOfLineBreaks) | 60 static inline unsigned computeLengthForSubmission(const String& text, unsigned n
umberOfLineBreaks) |
| 61 { | 61 { |
| 62 return numGraphemeClusters(text) + numberOfLineBreaks; | 62 return text.length() + numberOfLineBreaks; |
| 63 } | 63 } |
| 64 | 64 |
| 65 static unsigned numberOfLineBreaks(const String& text) | 65 static unsigned numberOfLineBreaks(const String& text) |
| 66 { | 66 { |
| 67 unsigned length = text.length(); | 67 unsigned length = text.length(); |
| 68 unsigned count = 0; | 68 unsigned count = 0; |
| 69 for (unsigned i = 0; i < length; i++) { | 69 for (unsigned i = 0; i < length; i++) { |
| 70 if (text[i] == '\n') | 70 if (text[i] == '\n') |
| 71 count++; | 71 count++; |
| 72 } | 72 } |
| 73 return count; | 73 return count; |
| 74 } | 74 } |
| 75 | 75 |
| 76 static inline unsigned computeLengthForSubmission(const String& text) | 76 static inline unsigned computeLengthForSubmission(const String& text) |
| 77 { | 77 { |
| 78 return numGraphemeClusters(text) + numberOfLineBreaks(text); | 78 return text.length() + numberOfLineBreaks(text); |
| 79 } | |
| 80 | |
| 81 static inline unsigned upperBoundForLengthForSubmission(const String& text, unsi
gned numberOfLineBreaks) | |
| 82 { | |
| 83 return text.length() + numberOfLineBreaks; | |
| 84 } | 79 } |
| 85 | 80 |
| 86 HTMLTextAreaElement::HTMLTextAreaElement(const QualifiedName& tagName, Document*
document, HTMLFormElement* form) | 81 HTMLTextAreaElement::HTMLTextAreaElement(const QualifiedName& tagName, Document*
document, HTMLFormElement* form) |
| 87 : HTMLTextFormControlElement(tagName, document, form) | 82 : HTMLTextFormControlElement(tagName, document, form) |
| 88 , m_rows(defaultRows) | 83 , m_rows(defaultRows) |
| 89 , m_cols(defaultCols) | 84 , m_cols(defaultCols) |
| 90 , m_wrap(SoftWrap) | 85 , m_wrap(SoftWrap) |
| 91 , m_placeholder(0) | 86 , m_placeholder(0) |
| 92 , m_isDirty(false) | 87 , m_isDirty(false) |
| 93 , m_wasModifiedByUser(false) | 88 , m_wasModifiedByUser(false) |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
event) const | 282 void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*
event) const |
| 288 { | 283 { |
| 289 ASSERT(event); | 284 ASSERT(event); |
| 290 ASSERT(renderer()); | 285 ASSERT(renderer()); |
| 291 int signedMaxLength = maxLength(); | 286 int signedMaxLength = maxLength(); |
| 292 if (signedMaxLength < 0) | 287 if (signedMaxLength < 0) |
| 293 return; | 288 return; |
| 294 unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); | 289 unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength); |
| 295 | 290 |
| 296 const String& currentValue = innerTextValue(); | 291 const String& currentValue = innerTextValue(); |
| 297 unsigned numberOfLineBreaksInCurrentValue = numberOfLineBreaks(currentValue)
; | 292 unsigned currentLength = computeLengthForSubmission(currentValue); |
| 298 if (upperBoundForLengthForSubmission(currentValue, numberOfLineBreaksInCurre
ntValue) | 293 if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxL
ength) |
| 299 + upperBoundForLengthForSubmission(event->text(), numberOfLineBreaks(eve
nt->text())) < unsignedMaxLength) | |
| 300 return; | 294 return; |
| 301 | 295 |
| 302 unsigned currentLength = computeLengthForSubmission(currentValue, numberOfLi
neBreaksInCurrentValue); | |
| 303 // selectionLength represents the selection length of this text field to be | 296 // selectionLength represents the selection length of this text field to be |
| 304 // removed by this insertion. | 297 // removed by this insertion. |
| 305 // If the text field has no focus, we don't need to take account of the | 298 // If the text field has no focus, we don't need to take account of the |
| 306 // selection length. The selection is the source of text drag-and-drop in | 299 // selection length. The selection is the source of text drag-and-drop in |
| 307 // that case, and nothing in the text field will be removed. | 300 // that case, and nothing in the text field will be removed. |
| 308 unsigned selectionLength = focused() ? computeLengthForSubmission(plainText(
document()->frame()->selection()->selection().toNormalizedRange().get())) : 0; | 301 unsigned selectionLength = focused() ? computeLengthForSubmission(plainText(
document()->frame()->selection()->selection().toNormalizedRange().get())) : 0; |
| 309 ASSERT(currentLength >= selectionLength); | 302 ASSERT(currentLength >= selectionLength); |
| 310 unsigned baseLength = currentLength - selectionLength; | 303 unsigned baseLength = currentLength - selectionLength; |
| 311 unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLeng
th - baseLength : 0; | 304 unsigned appendableLength = unsignedMaxLength > baseLength ? unsignedMaxLeng
th - baseLength : 0; |
| 312 event->setText(sanitizeUserInputValue(event->text(), appendableLength)); | 305 event->setText(sanitizeUserInputValue(event->text(), appendableLength)); |
| 313 } | 306 } |
| 314 | 307 |
| 315 String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue,
unsigned maxLength) | 308 String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue,
unsigned maxLength) |
| 316 { | 309 { |
| 317 return proposedValue.left(numCharactersInGraphemeClusters(proposedValue, max
Length)); | 310 if (maxLength > 0 && U16_IS_LEAD(proposedValue[maxLength - 1])) |
| 311 --maxLength; |
| 312 return proposedValue.left(maxLength); |
| 318 } | 313 } |
| 319 | 314 |
| 320 HTMLElement* HTMLTextAreaElement::innerTextElement() const | 315 HTMLElement* HTMLTextAreaElement::innerTextElement() const |
| 321 { | 316 { |
| 322 Node* node = userAgentShadowRoot()->firstChild(); | 317 Node* node = userAgentShadowRoot()->firstChild(); |
| 323 ASSERT(!node || node->hasTagName(divTag)); | 318 ASSERT(!node || node->hasTagName(divTag)); |
| 324 return toHTMLElement(node); | 319 return toHTMLElement(node); |
| 325 } | 320 } |
| 326 | 321 |
| 327 void HTMLTextAreaElement::rendererWillBeDestroyed() | 322 void HTMLTextAreaElement::rendererWillBeDestroyed() |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag che
ck) const | 472 bool HTMLTextAreaElement::tooLong(const String& value, NeedsToCheckDirtyFlag che
ck) const |
| 478 { | 473 { |
| 479 // Return false for the default value or value set by script even if it is | 474 // Return false for the default value or value set by script even if it is |
| 480 // longer than maxLength. | 475 // longer than maxLength. |
| 481 if (check == CheckDirtyFlag && !m_wasModifiedByUser) | 476 if (check == CheckDirtyFlag && !m_wasModifiedByUser) |
| 482 return false; | 477 return false; |
| 483 | 478 |
| 484 int max = maxLength(); | 479 int max = maxLength(); |
| 485 if (max < 0) | 480 if (max < 0) |
| 486 return false; | 481 return false; |
| 487 unsigned unsignedMax = static_cast<unsigned>(max); | 482 return computeLengthForSubmission(value) > static_cast<unsigned>(max); |
| 488 unsigned numberOfLineBreaksInValue = numberOfLineBreaks(value); | |
| 489 return upperBoundForLengthForSubmission(value, numberOfLineBreaksInValue) >
unsignedMax | |
| 490 && computeLengthForSubmission(value, numberOfLineBreaksInValue) > unsign
edMax; | |
| 491 } | 483 } |
| 492 | 484 |
| 493 bool HTMLTextAreaElement::isValidValue(const String& candidate) const | 485 bool HTMLTextAreaElement::isValidValue(const String& candidate) const |
| 494 { | 486 { |
| 495 return !valueMissing(candidate) && !tooLong(candidate, IgnoreDirtyFlag); | 487 return !valueMissing(candidate) && !tooLong(candidate, IgnoreDirtyFlag); |
| 496 } | 488 } |
| 497 | 489 |
| 498 void HTMLTextAreaElement::accessKeyAction(bool) | 490 void HTMLTextAreaElement::accessKeyAction(bool) |
| 499 { | 491 { |
| 500 focus(); | 492 focus(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 RefPtr<HTMLDivElement> placeholder = HTMLDivElement::create(document()); | 542 RefPtr<HTMLDivElement> placeholder = HTMLDivElement::create(document()); |
| 551 m_placeholder = placeholder.get(); | 543 m_placeholder = placeholder.get(); |
| 552 m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", Atomi
cString::ConstructFromLiteral)); | 544 m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", Atomi
cString::ConstructFromLiteral)); |
| 553 userAgentShadowRoot()->insertBefore(m_placeholder, innerTextElement()->n
extSibling(), ASSERT_NO_EXCEPTION); | 545 userAgentShadowRoot()->insertBefore(m_placeholder, innerTextElement()->n
extSibling(), ASSERT_NO_EXCEPTION); |
| 554 } | 546 } |
| 555 m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION); | 547 m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION); |
| 556 fixPlaceholderRenderer(m_placeholder, innerTextElement()); | 548 fixPlaceholderRenderer(m_placeholder, innerTextElement()); |
| 557 } | 549 } |
| 558 | 550 |
| 559 } | 551 } |
| OLD | NEW |