WebCore:

2008-03-16  Darin Adler  <darin@apple.com>

        Reviewed by Mark Rowe.

        - http://bugs.webkit.org/show_bug.cgi?id=17881
          a little cleanup for HTMLTextAreaElement

        Tests: fast/forms/textarea-default-value-leading-newline.html
               fast/forms/textarea-linewrap-dynamic.html

        * html/HTMLTextAreaElement.cpp:
        (WebCore::HTMLTextAreaElement::HTMLTextAreaElement): Tweaked names/
        (WebCore::HTMLTextAreaElement::selectionStart): Ditto, also use early return
        and check for < 0 rather than -1 specifically.
        (WebCore::HTMLTextAreaElement::selectionEnd): Ditto.
        (WebCore::HTMLTextAreaElement::setSelectionStart): Early return.
        (WebCore::HTMLTextAreaElement::setSelectionEnd): Ditto.
        (WebCore::HTMLTextAreaElement::select): Ditto.
        (WebCore::HTMLTextAreaElement::setSelectionRange): Ditto.
        (WebCore::HTMLTextAreaElement::parseMappedAttribute): Changed value parsing
        to treat unknown values as meaning "default" rather than "leave value as-is".
        Only call setNeedsLayoutAndPrefWidthsRecalc when mode changed.
        (WebCore::HTMLTextAreaElement::createRenderer): Removed name of unused argument.
        (WebCore::HTMLTextAreaElement::appendFormData): Updated for name changes.
        (WebCore::HTMLTextAreaElement::isKeyboardFocusable): Got rid of unnneeded explicit
        class name in isFocusable call.
        (WebCore::HTMLTextAreaElement::isMouseFocusable): Ditto.
        (WebCore::HTMLTextAreaElement::updateFocusAppearance): Tweaked formatting.
        (WebCore::HTMLTextAreaElement::defaultEventHandler): Ditto.
        (WebCore::HTMLTextAreaElement::updateValue): Early return.
        (WebCore::HTMLTextAreaElement::setValue): Got rid of intermediate value to
        eliminate on small refcount churn.
        (WebCore::HTMLTextAreaElement::defaultValue): Got rid of unneeded redundant
        string length checks, since String already checks all indexing and returns 0.
        (WebCore::HTMLTextAreaElement::setDefaultValue): Added code to normalize
        line endings and add a leading line ending to fix cases where the first
        character is a newline.
        (WebCore::HTMLTextAreaElement::accessKeyAction): Removed name of unused arg.
        (WebCore::HTMLTextAreaElement::accessKey): Changed return value to avoid
        refcount churn.
        (WebCore::HTMLTextAreaElement::selection): Updated names and use < 0 instead
        of -1 specifically.

        * html/HTMLTextAreaElement.h: Replaced wrap function with more-specific
        shouldWrapText one. Changed return value of accessKey. Made WrapMethod enum
        provate and renamed the values. Renamed cachedSelStart and cachedSelEnd to
        m_cachedSelectionStart and m_cachedSelectionEnd.

        * rendering/RenderTextControl.cpp:
        (WebCore::RenderTextControl::createInnerTextStyle): Updated for change to
        HTMLTextAreaElement wrap function.

LayoutTests:

2008-03-16  Darin Adler  <darin@apple.com>

        Reviewed by Mark Rowe.

        - test for bug fixes in http://bugs.webkit.org/show_bug.cgi?id=17881
          a little cleanup for HTMLTextAreaElement

        * fast/forms/textarea-default-value-leading-newline-expected.txt: Added.
        * fast/forms/textarea-default-value-leading-newline.html: Copied from fast/forms/textarea-crlf.html.

        * fast/forms/textarea-hard-linewrap-expected.txt: Updated.
        * fast/forms/textarea-hard-linewrap.html: Cleaned up a bit.

        * fast/forms/textarea-linewrap-dynamic-expected.txt: Added.
        * fast/forms/textarea-linewrap-dynamic.html: Copied from fast/forms/textarea-hard-linewrap.html.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31086 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index e8653c6..f66e724 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2008-03-16  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mark Rowe.
+
+        - test for bug fixes in http://bugs.webkit.org/show_bug.cgi?id=17881
+          a little cleanup for HTMLTextAreaElement
+
+        * fast/forms/textarea-default-value-leading-newline-expected.txt: Added.
+        * fast/forms/textarea-default-value-leading-newline.html: Copied from fast/forms/textarea-crlf.html.
+
+        * fast/forms/textarea-hard-linewrap-expected.txt: Updated.
+        * fast/forms/textarea-hard-linewrap.html: Cleaned up a bit.
+
+        * fast/forms/textarea-linewrap-dynamic-expected.txt: Added.
+        * fast/forms/textarea-linewrap-dynamic.html: Copied from fast/forms/textarea-hard-linewrap.html.
+
 2008-03-16  Antti Koivisto  <antti@apple.com>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/forms/textarea-default-value-leading-newline-expected.txt b/LayoutTests/fast/forms/textarea-default-value-leading-newline-expected.txt
new file mode 100644
index 0000000..5114372
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-default-value-leading-newline-expected.txt
@@ -0,0 +1,9 @@
+This test attempts to set a leading newline in a text area's default value.
+
+If the test passes, you should see a 3 lines saying "Passed" below.
+
+
+Passed
+Passed
+Passed
+
diff --git a/LayoutTests/fast/forms/textarea-default-value-leading-newline.html b/LayoutTests/fast/forms/textarea-default-value-leading-newline.html
new file mode 100644
index 0000000..4a4bd9c
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-default-value-leading-newline.html
@@ -0,0 +1,44 @@
+<html>
+    <head>
+        <script type="text/javascript">
+            function print(message)
+            {
+                var paragraph = document.createElement("li");
+                paragraph.appendChild(document.createTextNode(message));
+                document.getElementById("console").appendChild(paragraph);
+            }
+            function test()
+            {
+                if (window.layoutTestController) {
+                    layoutTestController.dumpAsText();
+                }
+                var elt = document.getElementById("text");
+                elt.defaultValue = "\ntesting";
+                compare(elt.defaultValue, "\ntesting");
+                elt.defaultValue = "\n\ntesting";
+                compare(elt.defaultValue, "\n\ntesting");
+                elt.defaultValue = "\n\n\ntesting";
+                compare(elt.defaultValue, "\n\n\ntesting");
+                elt.defaultValue = "";
+            }
+            function compare(val, exp)
+            {
+                if (val == exp) {
+                    print("Passed");
+                } else {
+                    print("Failed");
+                }
+            }
+        </script>
+    </head>
+    <body onload="test();">
+        <p>This test attempts to set a leading newline in a text area's default value.</p>
+        <p>If the test passes, you should see a 3 lines saying "Passed" below.</p>
+        <hr>
+        <form>
+            <textarea id="text"></textarea>
+        </form>
+        <hr>
+        <p><ol id="console"></ol></p>
+    </body>
+</html>
diff --git a/LayoutTests/fast/forms/textarea-hard-linewrap-expected.txt b/LayoutTests/fast/forms/textarea-hard-linewrap-expected.txt
index 3a1fc8b..1264df0 100644
--- a/LayoutTests/fast/forms/textarea-hard-linewrap-expected.txt
+++ b/LayoutTests/fast/forms/textarea-hard-linewrap-expected.txt
@@ -1,6 +1,6 @@
 This tests that a textarea's default value is submitted with hard line wraps (carriage returns where line wraps appear in the textarea).
 
-Due to a bug, the textarea is actually a bit wider than we specify via the cols attribute, so, the number and position of the carriage returns in the submitted data is not what you'd expect. The expected results for this testcase should be updated when http://bugzilla.opendarwin.org/show_bug.cgi?id=7505 is fixed.
+Due to a bug, the textarea is actually a bit wider than we specify via the cols attribute, so, the number and position of the carriage returns in the submitted data is not what you'd expect. The expected results for this testcase should be updated when bug 7505 is fixed.
 
  
 Success
diff --git a/LayoutTests/fast/forms/textarea-hard-linewrap.html b/LayoutTests/fast/forms/textarea-hard-linewrap.html
index 0a0efd2..775e487 100644
--- a/LayoutTests/fast/forms/textarea-hard-linewrap.html
+++ b/LayoutTests/fast/forms/textarea-hard-linewrap.html
@@ -1,36 +1,28 @@
 <html>
-<head>
-<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
-<title>Charsets and submitting forms</title>
-</head>
 <body>
 <p>This tests that a textarea's default value is submitted with hard line wraps (carriage returns where line wraps appear in the textarea).</p>
-<p>Due to a bug, the textarea is actually a bit wider than we specify via the cols attribute, so, the number and position of the carriage returns in the submitted data is not what you'd expect.  The expected results for this testcase should be updated when <a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=7505">http://bugzilla.opendarwin.org/show_bug.cgi?id=7505</a> is fixed.</p>
+<p>Due to a bug, the textarea is actually a bit wider than we specify via the cols attribute, so, the number and position of the carriage returns in the submitted data is not what you'd expect.
+The expected results for this testcase should be updated when <a href="http://bugs.webkit.org/show_bug.cgi?id=7505">bug 7505</a> is fixed.</p>
 <form name="f" method="?" action="textarea-hard-linewrap.html">
 <textarea id="textarea" name="textarea" wrap="hard" cols="5">123456789</textarea>
 <input type="submit">
 </form>
 <script>
 if (document.URL.indexOf('?') == -1) {
-
     if (window.layoutTestController) {
         window.layoutTestController.dumpAsText();
         window.layoutTestController.waitUntilDone();
     }
-    
     document.f.submit();
-        
 } else {
     var formData = document.URL.substring(document.URL.indexOf('?') + 1, document.URL.length);
     if (formData == "textarea=1234567%0D%0A89")
         document.write("Success");
     else
-        document.write("Failure.  The form data that should have been submitted: textarea=1234567%0D%0A89<br>This is what was actually submitted: " + formData);
-    
+        document.write("Failure.  The form data that should have been submitted: textarea=1234567%0D%0A89<br>This is what was actually submitted: " + formData);    
     if (window.layoutTestController)
         window.layoutTestController.notifyDone();
 }
-
 </script>
 </body>
 </html>
diff --git a/LayoutTests/fast/forms/textarea-linewrap-dynamic-expected.txt b/LayoutTests/fast/forms/textarea-linewrap-dynamic-expected.txt
new file mode 100644
index 0000000..edf5495
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-linewrap-dynamic-expected.txt
@@ -0,0 +1,4 @@
+This tests that a textarea where the wrap attribute is removed reverts to normal wrapping behavior.
+
+ 
+Success
diff --git a/LayoutTests/fast/forms/textarea-linewrap-dynamic.html b/LayoutTests/fast/forms/textarea-linewrap-dynamic.html
new file mode 100644
index 0000000..0b3ca4b
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-linewrap-dynamic.html
@@ -0,0 +1,27 @@
+<html>
+<body>
+<p>This tests that a textarea where the wrap attribute is removed reverts to normal wrapping behavior.</p>
+<form name="f" method="?" action="textarea-linewrap-dynamic.html">
+<textarea id="textarea" name="textarea" wrap="hard" cols="5">123456789</textarea>
+<input type="submit">
+</form>
+<script>
+if (document.URL.indexOf('?') == -1) {
+    if (window.layoutTestController) {
+        window.layoutTestController.dumpAsText();
+        window.layoutTestController.waitUntilDone();
+    }
+    document.getElementById("textarea").removeAttribute("wrap");
+    document.f.submit();
+} else {
+    var formData = document.URL.substring(document.URL.indexOf('?') + 1, document.URL.length);
+    if (formData == "textarea=123456789")
+        document.write("Success");
+    else
+        document.write("Failure.  The form data that should have been submitted: textarea=123456789<br>This is what was actually submitted: " + formData);    
+    if (window.layoutTestController)
+        window.layoutTestController.notifyDone();
+}
+</script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a3b9ca4..28e8af1 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,55 @@
+2008-03-16  Darin Adler  <darin@apple.com>
+
+        Reviewed by Mark Rowe.
+
+        - http://bugs.webkit.org/show_bug.cgi?id=17881
+          a little cleanup for HTMLTextAreaElement
+
+        Tests: fast/forms/textarea-default-value-leading-newline.html
+               fast/forms/textarea-linewrap-dynamic.html
+
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::HTMLTextAreaElement): Tweaked names/
+        (WebCore::HTMLTextAreaElement::selectionStart): Ditto, also use early return
+        and check for < 0 rather than -1 specifically.
+        (WebCore::HTMLTextAreaElement::selectionEnd): Ditto.
+        (WebCore::HTMLTextAreaElement::setSelectionStart): Early return.
+        (WebCore::HTMLTextAreaElement::setSelectionEnd): Ditto.
+        (WebCore::HTMLTextAreaElement::select): Ditto.
+        (WebCore::HTMLTextAreaElement::setSelectionRange): Ditto.
+        (WebCore::HTMLTextAreaElement::parseMappedAttribute): Changed value parsing
+        to treat unknown values as meaning "default" rather than "leave value as-is".
+        Only call setNeedsLayoutAndPrefWidthsRecalc when mode changed.
+        (WebCore::HTMLTextAreaElement::createRenderer): Removed name of unused argument.
+        (WebCore::HTMLTextAreaElement::appendFormData): Updated for name changes.
+        (WebCore::HTMLTextAreaElement::isKeyboardFocusable): Got rid of unnneeded explicit
+        class name in isFocusable call.
+        (WebCore::HTMLTextAreaElement::isMouseFocusable): Ditto.
+        (WebCore::HTMLTextAreaElement::updateFocusAppearance): Tweaked formatting.
+        (WebCore::HTMLTextAreaElement::defaultEventHandler): Ditto.
+        (WebCore::HTMLTextAreaElement::updateValue): Early return.
+        (WebCore::HTMLTextAreaElement::setValue): Got rid of intermediate value to
+        eliminate on small refcount churn.
+        (WebCore::HTMLTextAreaElement::defaultValue): Got rid of unneeded redundant
+        string length checks, since String already checks all indexing and returns 0.
+        (WebCore::HTMLTextAreaElement::setDefaultValue): Added code to normalize
+        line endings and add a leading line ending to fix cases where the first
+        character is a newline.
+        (WebCore::HTMLTextAreaElement::accessKeyAction): Removed name of unused arg.
+        (WebCore::HTMLTextAreaElement::accessKey): Changed return value to avoid
+        refcount churn.
+        (WebCore::HTMLTextAreaElement::selection): Updated names and use < 0 instead
+        of -1 specifically.
+
+        * html/HTMLTextAreaElement.h: Replaced wrap function with more-specific
+        shouldWrapText one. Changed return value of accessKey. Made WrapMethod enum
+        provate and renamed the values. Renamed cachedSelStart and cachedSelEnd to
+        m_cachedSelectionStart and m_cachedSelectionEnd.
+
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::createInnerTextStyle): Updated for change to
+        HTMLTextAreaElement wrap function.
+
 2008-03-16  Antti Koivisto  <antti@apple.com>
 
         Reviewed by Mitz.
diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp
index 5f42a44..de165b3 100644
--- a/WebCore/html/HTMLTextAreaElement.cpp
+++ b/WebCore/html/HTMLTextAreaElement.cpp
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
  *
@@ -47,13 +47,13 @@
 static const int defaultRows = 2;
 static const int defaultCols = 20;
 
-HTMLTextAreaElement::HTMLTextAreaElement(Document* doc, HTMLFormElement* f)
-    : HTMLFormControlElementWithState(textareaTag, doc, f)
+HTMLTextAreaElement::HTMLTextAreaElement(Document* document, HTMLFormElement* form)
+    : HTMLFormControlElementWithState(textareaTag, document, form)
     , m_rows(defaultRows)
     , m_cols(defaultCols)
-    , m_wrap(ta_Virtual)
-    , cachedSelStart(-1)
-    , cachedSelEnd(-1)
+    , m_wrap(SoftWrap)
+    , m_cachedSelectionStart(-1)
+    , m_cachedSelectionEnd(-1)
 {
     setValueMatchesRenderer();
 }
@@ -77,46 +77,48 @@
 
 int HTMLTextAreaElement::selectionStart()
 {
-    if (renderer()) {
-        if (document()->focusedNode() != this && cachedSelStart != -1)
-            return cachedSelStart;
-        return static_cast<RenderTextControl *>(renderer())->selectionStart();
-    }
-    return 0;
+    if (!renderer())
+        return 0;
+    if (document()->focusedNode() != this && m_cachedSelectionStart >= 0)
+        return m_cachedSelectionStart;
+    return static_cast<RenderTextControl*>(renderer())->selectionStart();
 }
 
 int HTMLTextAreaElement::selectionEnd()
 {
-    if (renderer()) {
-        if (document()->focusedNode() != this && cachedSelEnd != -1)
-            return cachedSelEnd;
-        return static_cast<RenderTextControl *>(renderer())->selectionEnd();
-    }
-    return 0;
+    if (!renderer())
+        return 0;
+    if (document()->focusedNode() != this && m_cachedSelectionEnd >= 0)
+        return m_cachedSelectionEnd;
+    return static_cast<RenderTextControl*>(renderer())->selectionEnd();
 }
 
 void HTMLTextAreaElement::setSelectionStart(int start)
 {
-    if (renderer())
-        static_cast<RenderTextControl*>(renderer())->setSelectionStart(start);
+    if (!renderer())
+        return;
+    static_cast<RenderTextControl*>(renderer())->setSelectionStart(start);
 }
 
 void HTMLTextAreaElement::setSelectionEnd(int end)
 {
-    if (renderer())
-        static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end);
+    if (!renderer())
+        return;
+    static_cast<RenderTextControl*>(renderer())->setSelectionEnd(end);
 }
 
 void HTMLTextAreaElement::select()
 {
-    if (renderer())
-        static_cast<RenderTextControl *>(renderer())->select();
+    if (!renderer())
+        return;
+    static_cast<RenderTextControl*>(renderer())->select();
 }
 
 void HTMLTextAreaElement::setSelectionRange(int start, int end)
 {
-    if (renderer())
-        static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end);
+    if (!renderer())
+        return;
+    static_cast<RenderTextControl*>(renderer())->setSelectionRange(start, end);
 }
 
 void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -125,7 +127,7 @@
     HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
 }
     
-void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute *attr)
+void HTMLTextAreaElement::parseMappedAttribute(MappedAttribute* attr)
 {
     if (attr->name() == rowsAttr) {
         int rows = attr->value().toInt();
@@ -146,18 +148,20 @@
                 renderer()->setNeedsLayoutAndPrefWidthsRecalc();
         }
     } else if (attr->name() == wrapAttr) {
-        // virtual / physical is Netscape extension of HTML 3.0, now deprecated
-        // soft/ hard / off is recommendation for HTML 4 extension by IE and NS 4
-        if (equalIgnoringCase(attr->value(), "virtual") || equalIgnoringCase(attr->value(), "soft"))
-            m_wrap = ta_Virtual;
-        else if (equalIgnoringCase(attr->value(), "physical") || equalIgnoringCase(attr->value(), "hard"))
-            m_wrap = ta_Physical;
-        else if (equalIgnoringCase(attr->value(), "on" ))
-            m_wrap = ta_Physical;
+        // The virtual/physical values were a Netscape extension of HTML 3.0, now deprecated.
+        // The soft/hard /off values are a recommendation for HTML 4 extension by IE and NS 4.
+        WrapMethod wrap;
+        if (equalIgnoringCase(attr->value(), "physical") || equalIgnoringCase(attr->value(), "hard") || equalIgnoringCase(attr->value(), "on"))
+            wrap = HardWrap;
         else if (equalIgnoringCase(attr->value(), "off"))
-            m_wrap = ta_NoWrap;
-        if (renderer())
-            renderer()->setNeedsLayoutAndPrefWidthsRecalc();
+            wrap = NoWrap;
+        else
+            wrap = SoftWrap;
+        if (wrap != m_wrap) {
+            m_wrap = wrap;
+            if (renderer())
+                renderer()->setNeedsLayoutAndPrefWidthsRecalc();
+        }
     } else if (attr->name() == accesskeyAttr) {
         // ignore for the moment
     } else if (attr->name() == alignAttr) {
@@ -175,7 +179,7 @@
         HTMLFormControlElementWithState::parseMappedAttribute(attr);
 }
 
-RenderObject* HTMLTextAreaElement::createRenderer(RenderArena* arena, RenderStyle* style)
+RenderObject* HTMLTextAreaElement::createRenderer(RenderArena* arena, RenderStyle*)
 {
     return new (arena) RenderTextControl(this, true);
 }
@@ -184,10 +188,12 @@
 {
     if (name().isEmpty())
         return false;
-        
-    bool hardWrap = renderer() && wrap() == ta_Physical;
-    String v = hardWrap ? static_cast<RenderTextControl*>(renderer())->textWithHardLineBreaks() : value();
-    encoding.appendData(name(), v);
+
+    // FIXME: It's not acceptable to ignore the HardWrap setting when there is no renderer.
+    // While we have no evidence this has ever been a practical problem, it would be best to fix it some day.
+    RenderTextControl* control = static_cast<RenderTextControl*>(renderer());
+    const String& text = (m_wrap == HardWrap && control) ? control->textWithHardLineBreaks() : value();
+    encoding.appendData(name(), text);
     return true;
 }
 
@@ -198,38 +204,39 @@
 
 bool HTMLTextAreaElement::isKeyboardFocusable(KeyboardEvent*) const
 {
-    // If text areas can be focused, then they should always be keyboard focusable
-    return HTMLFormControlElementWithState::isFocusable();
+    // If a given text area can be focused at all, then it will always be keyboard focusable.
+    return isFocusable();
 }
 
 bool HTMLTextAreaElement::isMouseFocusable() const
 {
-    return HTMLFormControlElementWithState::isFocusable();
+    return isFocusable();
 }
 
 void HTMLTextAreaElement::updateFocusAppearance(bool restorePreviousSelection)
 {
     ASSERT(renderer());
     
-    if (!restorePreviousSelection || cachedSelStart == -1) {
+    if (!restorePreviousSelection || m_cachedSelectionStart < 0) {
         // If this is the first focus, set a caret at the beginning of the text.  
-        // This matches some browsers' behavior; see Bugzilla Bug 11746 Comment #15.
+        // This matches some browsers' behavior; see bug 11746 Comment #15.
         // http://bugs.webkit.org/show_bug.cgi?id=11746#c15
         setSelectionRange(0, 0);
-    } else
+    } else {
         // Restore the cached selection.  This matches other browsers' behavior.
-        setSelectionRange(cachedSelStart, cachedSelEnd); 
+        setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd);
+    }
 
     if (document()->frame())
         document()->frame()->revealSelection();
 }
 
-void HTMLTextAreaElement::defaultEventHandler(Event *evt)
+void HTMLTextAreaElement::defaultEventHandler(Event* event)
 {
-    if (renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == blurEvent))
-        static_cast<RenderTextControl*>(renderer())->forwardEvent(evt);
+    if (renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent() || event->type() == blurEvent))
+        static_cast<RenderTextControl*>(renderer())->forwardEvent(event);
 
-    HTMLFormControlElementWithState::defaultEventHandler(evt);
+    HTMLFormControlElementWithState::defaultEventHandler(event);
 }
 
 void HTMLTextAreaElement::rendererWillBeDestroyed()
@@ -239,11 +246,12 @@
 
 void HTMLTextAreaElement::updateValue() const
 {
-    if (!valueMatchesRenderer()) {
-        ASSERT(renderer());
-        m_value = static_cast<RenderTextControl*>(renderer())->text();
-        setValueMatchesRenderer();
-    }
+    if (valueMatchesRenderer())
+        return;
+
+    ASSERT(renderer());
+    m_value = static_cast<RenderTextControl*>(renderer())->text();
+    setValueMatchesRenderer();
 }
 
 String HTMLTextAreaElement::value() const
@@ -256,17 +264,16 @@
 {
     // Code elsewhere normalizes line endings added by the user via the keyboard or pasting.
     // We must normalize line endings coming from JS.
-    String valueWithNormalizedLineEndings = value;
-    valueWithNormalizedLineEndings.replace("\r\n", "\n");
-    valueWithNormalizedLineEndings.replace("\r", "\n");
-    
-    m_value = valueWithNormalizedLineEndings;
+    m_value = value;
+    m_value.replace("\r\n", "\n");
+    m_value.replace('\r', '\n');
+
     setValueMatchesRenderer();
     if (inDocument())
         document()->updateRendering();
     if (renderer())
         renderer()->updateFromElement();
-    
+
     // Set the caret to the end of the text value.
     if (document()->focusedNode() == this) {
         unsigned endOfString = m_value.length();
@@ -278,45 +285,57 @@
 
 String HTMLTextAreaElement::defaultValue() const
 {
-    String val = "";
+    String value = "";
 
     // Since there may be comments, ignore nodes other than text nodes.
-    for (Node* n = firstChild(); n; n = n->nextSibling())
+    for (Node* n = firstChild(); n; n = n->nextSibling()) {
         if (n->isTextNode())
-            val += static_cast<Text*>(n)->data();
+            value += static_cast<Text*>(n)->data();
+    }
 
-    // FIXME: We should only drop the first carriage return for the default
-    // value in the original source, not defaultValues set from JS. This code
-    // will do both.
-    if (val.length() >= 2 && val[0] == '\r' && val[1] == '\n')
-        val.remove(0, 2);
-    else if (val.length() >= 1 && (val[0] == '\r' || val[0] == '\n'))
-        val.remove(0, 1);
+    UChar firstCharacter = value[0];
+    if (firstCharacter == '\r' && value[1] == '\n')
+        value.remove(0, 2);
+    else if (firstCharacter == '\r' || firstCharacter == '\n')
+        value.remove(0, 1);
 
-    return val;
+    return value;
 }
 
 void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
 {
-    // To preserve comments, remove all the text nodes, then add a single one.
+    // To preserve comments, remove only the text nodes, then add a single text node.
+
     Vector<RefPtr<Node> > textNodes;
-    for (Node* n = firstChild(); n; n = n->nextSibling())
+    for (Node* n = firstChild(); n; n = n->nextSibling()) {
         if (n->isTextNode())
             textNodes.append(n);
-    ExceptionCode ec = 0;
+    }
+    ExceptionCode ec;
     size_t size = textNodes.size();
     for (size_t i = 0; i < size; ++i)
         removeChild(textNodes[i].get(), ec);
-    insertBefore(document()->createTextNode(defaultValue), firstChild(), ec);
-    setValue(defaultValue);
+
+    // Normalize line endings.
+    // Add an extra line break if the string starts with one, since
+    // the code to read default values from the DOM strips the leading one.
+    String value = defaultValue;
+    value.replace("\r\n", "\n");
+    value.replace('\r', '\n');
+    if (value[0] == '\n')
+        value = "\n" + value;
+
+    insertBefore(document()->createTextNode(value), firstChild(), ec);
+
+    setValue(value);
 }
 
-void HTMLTextAreaElement::accessKeyAction(bool sendToAnyElement)
+void HTMLTextAreaElement::accessKeyAction(bool)
 {
     focus();
 }
 
-String HTMLTextAreaElement::accessKey() const
+const AtomicString& HTMLTextAreaElement::accessKey() const
 {
     return getAttribute(accesskeyAttr);
 }
@@ -338,9 +357,9 @@
 
 Selection HTMLTextAreaElement::selection() const
 {
-    if (!renderer() || cachedSelStart == -1 || cachedSelEnd == -1)
+    if (!renderer() || m_cachedSelectionStart < 0 || m_cachedSelectionEnd < 0)
         return Selection();
-    return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd);
+    return static_cast<RenderTextControl*>(renderer())->selection(m_cachedSelectionStart, m_cachedSelectionEnd);
 }
 
 bool HTMLTextAreaElement::shouldUseInputMethod() const
diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h
index 7d1fe3f..de738b9 100644
--- a/WebCore/html/HTMLTextAreaElement.h
+++ b/WebCore/html/HTMLTextAreaElement.h
@@ -32,8 +32,6 @@
 
 class HTMLTextAreaElement : public HTMLFormControlElementWithState {
 public:
-    enum WrapMethod { ta_NoWrap, ta_Virtual, ta_Physical };
-
     HTMLTextAreaElement(Document*, HTMLFormElement* = 0);
 
     virtual bool checkDTD(const Node* newChild) { return newChild->isTextNode(); }
@@ -41,7 +39,7 @@
     int cols() const { return m_cols; }
     int rows() const { return m_rows; }
 
-    WrapMethod wrap() const { return m_wrap; }
+    bool shouldWrapText() const { return m_wrap != NoWrap; }
 
     virtual bool isEnumeratable() const { return true; }
 
@@ -80,25 +78,28 @@
     
     virtual void accessKeyAction(bool sendToAnyElement);
     
-    String accessKey() const;
+    const AtomicString& accessKey() const;
     void setAccessKey(const String&);
 
     void setCols(int);
     void setRows(int);
     
-    void cacheSelection(int s, int e) { cachedSelStart = s; cachedSelEnd = e; };
+    void cacheSelection(int s, int e) { m_cachedSelectionStart = s; m_cachedSelectionEnd = e; };
     Selection selection() const;
 
     virtual bool shouldUseInputMethod() const;
+
 private:
+    enum WrapMethod { NoWrap, SoftWrap, HardWrap };
+
     void updateValue() const;
 
     int m_rows;
     int m_cols;
     WrapMethod m_wrap;
     mutable String m_value;
-    int cachedSelStart;
-    int cachedSelEnd;
+    int m_cachedSelectionStart;
+    int m_cachedSelectionEnd;
 };
 
 } //namespace
diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp
index ed9280f..8cb9e90 100644
--- a/WebCore/rendering/RenderTextControl.cpp
+++ b/WebCore/rendering/RenderTextControl.cpp
@@ -175,8 +175,8 @@
         textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
         textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
 
-        // Set word wrap property based on wrap attribute
-        if (static_cast<HTMLTextAreaElement*>(element)->wrap() == HTMLTextAreaElement::ta_NoWrap) {
+        // Set word wrap property based on wrap attribute.
+        if (!static_cast<HTMLTextAreaElement*>(element)->shouldWrapText()) {
             textBlockStyle->setWhiteSpace(PRE);
             textBlockStyle->setWordWrap(NormalWordWrap);
         } else {