LayoutTests:
authoradele <adele@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2006 20:01:16 +0000 (20:01 +0000)
committeradele <adele@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Jul 2006 20:01:16 +0000 (20:01 +0000)
        Reviewed by Darin.

        * editing/selection/select-all-iframe-expected.txt:
        * editing/selection/select-from-textfield-outwards-expected.checksum: Added.
        * editing/selection/select-from-textfield-outwards-expected.png: Added.
        * editing/selection/select-from-textfield-outwards-expected.txt: Added.
        * editing/selection/select-from-textfield-outwards.html: Added.
        * fast/events/drag-outside-window-expected.txt:

WebCore:

        Reviewed by Darin.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9312
          REGRESSION: Selection bug in new text fields when selecting past the first letter

        Test: editing/selection/select-from-textfield-outwards.html

        * editing/Selection.cpp:
        (WebCore::Selection::adjustForEditableContent): Added code to handle the case
        where the selection starts (resp. ends) in the last (resp. first) visual position
        inside an editable root.
        * editing/htmlediting.cpp:
        (WebCore::comparePositions): Fixed the case of comparing a position inside a shadow
        tree with a position in the shadow ancestor.
        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::positionForCoordinates): For coordinates outside a replaced
        object, return the position just before (after) the element if the coordinates are above or
        to the left (below or to the right).
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::caretMaxOffset): Changed to return 1 for replaced objects.
        * rendering/RenderText.cpp:
        (WebCore::RenderText::positionForCoordinates): Changed to return the last position
        in the lowest text box if the y coordinate is below all text boxes.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15558 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/editing/selection/select-all-iframe-expected.txt
LayoutTests/editing/selection/select-from-textfield-outwards-expected.checksum [new file with mode: 0644]
LayoutTests/editing/selection/select-from-textfield-outwards-expected.png [new file with mode: 0644]
LayoutTests/editing/selection/select-from-textfield-outwards-expected.txt [new file with mode: 0644]
LayoutTests/editing/selection/select-from-textfield-outwards.html [new file with mode: 0644]
LayoutTests/fast/events/drag-outside-window-expected.txt
WebCore/ChangeLog
WebCore/editing/Selection.cpp
WebCore/editing/htmlediting.cpp
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderObject.cpp
WebCore/rendering/RenderText.cpp

index ec51531b0e6f6624475628b327f92b821b086175..cd8341a7fbb729c20a4dcd4e0f6573870e03da7c 100644 (file)
@@ -1,3 +1,14 @@
+2006-07-21  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Darin.
+
+        * editing/selection/select-all-iframe-expected.txt:
+        * editing/selection/select-from-textfield-outwards-expected.checksum: Added.
+        * editing/selection/select-from-textfield-outwards-expected.png: Added.
+        * editing/selection/select-from-textfield-outwards-expected.txt: Added.
+        * editing/selection/select-from-textfield-outwards.html: Added.
+        * fast/events/drag-outside-window-expected.txt:
+
 2006-07-21  Geoffrey Garen  <ggaren@apple.com>
 
         Test for undetectable style.filter property.
index 9dcb402c2730bd9101f4523b3b35cb7b27f27228..766b225cd8480babdc60fdfbaf94f2d8b123ec28 100644 (file)
@@ -1,8 +1,9 @@
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of BODY > HTML > #document to 4 of BODY > HTML > #document
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 11 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 11 of #text > DIV > BODY > HTML > #document to 11 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV > BODY > HTML > #document to 11 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 11 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 11 of #text > DIV > BODY > HTML > #document
 EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
diff --git a/LayoutTests/editing/selection/select-from-textfield-outwards-expected.checksum b/LayoutTests/editing/selection/select-from-textfield-outwards-expected.checksum
new file mode 100644 (file)
index 0000000..40e8ad3
--- /dev/null
@@ -0,0 +1 @@
+cdca9cd2b9c97bee9ebba8c8454f6bbd
\ No newline at end of file
diff --git a/LayoutTests/editing/selection/select-from-textfield-outwards-expected.png b/LayoutTests/editing/selection/select-from-textfield-outwards-expected.png
new file mode 100644 (file)
index 0000000..8572e83
Binary files /dev/null and b/LayoutTests/editing/selection/select-from-textfield-outwards-expected.png differ
diff --git a/LayoutTests/editing/selection/select-from-textfield-outwards-expected.txt b/LayoutTests/editing/selection/select-from-textfield-outwards-expected.txt
new file mode 100644 (file)
index 0000000..e90a639
--- /dev/null
@@ -0,0 +1,59 @@
+ALERT: middle
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 11 of #text > DIV to 11 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 11 of #text > DIV toDOMRange:range from 11 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+ALERT: left
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 12 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+ALERT: right
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+ALERT: way up
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 17 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+ALERT: up
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 0 of #text > DIV to 12 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+ALERT: down
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV to 12 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
+ALERT: way down
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 11 of #text > DIV to 17 of #text > DIV toDOMRange:range from 11 of #text > DIV to 17 of #text > DIV affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x576
+      RenderBlock {P} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 104x18
+          text run at (0,0) width 104: "This is a test for "
+        RenderInline {I} at (0,0) size 755x36
+          RenderInline {A} at (0,0) size 348x18 [color=#0000EE]
+            RenderText {#text} at (104,0) size 348x18
+              text run at (104,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=9312"
+          RenderText {#text} at (452,0) size 755x36
+            text run at (452,0) width 4: " "
+            text run at (456,0) width 299: "REGRESSION: Selection bug in new text fields"
+            text run at (0,18) width 210: "when selecting past the first letter"
+        RenderText {#text} at (210,18) size 4x18
+          text run at (210,18) width 4: "."
+      RenderBlock {HR} at (0,52) size 784x2 [border: (1px inset #000000)]
+      RenderBlock {P} at (0,70) size 784x54
+        RenderText {#text} at (0,0) size 778x54
+          text run at (0,0) width 778: "Curabitur pretium, quam quis semper malesuada, est libero feugiat libero, vel fringilla orci nibh sed neque. Quisque eu nulla"
+          text run at (0,18) width 732: "non nisi molestie accumsan. Etiam tellus urna, laoreet ac, laoreet non, suscipit sed, sapien. Phasellus vehicula, sem at"
+          text run at (0,36) width 541: "posuere vehicula, augue nibh molestie nisl, nec ullamcorper lacus ante vulputate pede."
+      RenderBlock (anonymous) at (0,140) size 784x92
+        RenderTextField {INPUT} at (20,20) size 330x52 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {P} at (0,248) size 784x54
+        RenderText {#text} at (0,0) size 769x54
+          text run at (0,0) width 754: "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris viverra augue vitae purus."
+          text run at (0,18) width 769: "Morbi sed sem. Donec dui nisi, ultrices non, pretium quis, hendrerit non, est. Donec tellus. Donec eget dui id eros pharetra"
+          text run at (0,36) width 733: "rutrum. Suspendisse sodales lectus sit amet nulla. Morbi tortor arcu, convallis blandit, elementum eu, aliquet a, tellus."
+layer at (40,180) size 306x28
+  RenderBlock {DIV} at (12,12) size 306x28
+    RenderText {#text} at (1,0) size 224x28
+      text run at (1,0) width 224: "Lorem ipsum dolor"
+selection start: position 11 of child 0 {#text} of child 0 {DIV} of child 7 {INPUT} of child 1 {BODY} of child 0 {HTML} of document
+selection end:   position 17 of child 0 {#text} of child 0 {DIV} of child 7 {INPUT} of child 1 {BODY} of child 0 {HTML} of document
diff --git a/LayoutTests/editing/selection/select-from-textfield-outwards.html b/LayoutTests/editing/selection/select-from-textfield-outwards.html
new file mode 100644 (file)
index 0000000..b9d510b
--- /dev/null
@@ -0,0 +1,48 @@
+<html>
+<head>
+<script src=../editing.js type="text/javascript"></script>
+<script>
+function editingTest() {
+    if (!window.layoutTestController)
+        return;
+
+    var field = document.getElementById('target');
+    var middleX = field.offsetLeft + field.offsetWidth / 2;
+    var middleY = field.offsetTop + field.offsetHeight / 2;
+    
+    alert("middle");
+    eventSender.mouseMoveTo(middleX, middleY);
+    eventSender.mouseDown();
+    eventSender.leapForward(1000);
+    eventSender.mouseUp();
+    eventSender.mouseDown();
+    alert("left");
+    eventSender.mouseMoveTo(0, middleY);
+    alert("right");
+    eventSender.mouseMoveTo(document.body.offsetWidth, middleY);
+    alert("way up");
+    eventSender.mouseMoveTo(middleX, middleY - 2 * field.offsetHeight);
+    alert("up");
+    eventSender.mouseMoveTo(middleX, middleY - field.offsetHeight);
+    alert("down");
+    eventSender.mouseMoveTo(middleX, middleY + field.offsetHeight);
+    alert("way down");
+    eventSender.mouseMoveTo(middleX, middleY + 2 * field.offsetHeight);
+}
+</script>
+</head>
+<body onLoad="runEditingTest();">
+    <p>
+        This is a test for <i><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=9312">http://bugzilla.opendarwin.org/show_bug.cgi?id=9312</a>
+        REGRESSION: Selection bug in new text fields when selecting past the first letter</i>.
+    </p>
+    <hr>
+    <p>
+        Curabitur pretium, quam quis semper malesuada, est libero feugiat libero, vel fringilla orci nibh sed neque. Quisque eu nulla non nisi molestie accumsan. Etiam tellus urna, laoreet ac, laoreet non, suscipit sed, sapien. Phasellus vehicula, sem at posuere vehicula, augue nibh molestie nisl, nec ullamcorper lacus ante vulputate pede.
+    </p>
+    <input id="target" value="Lorem ipsum dolor" style="font-size: 24px; padding: 10px; margin: 20px;">
+    <p>
+        Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris viverra augue vitae purus. Morbi sed sem. Donec dui nisi, ultrices non, pretium quis, hendrerit non, est. Donec tellus. Donec eget dui id eros pharetra rutrum. Suspendisse sodales lectus sit amet nulla. Morbi tortor arcu, convallis blandit, elementum eu, aliquet a, tellus.
+    </p>
+</body>
+</html>
index 72a32ae14edeec697d236f4ceecae23005aabcd9..d2b9809e9ead6ec9a2c23be976f1753db4eb0f11 100644 (file)
@@ -1,5 +1,5 @@
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 31 of #text > P > BODY > HTML > #document to 31 of #text > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document toDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 31 of #text > P > BODY > HTML > #document to 31 of #text > P > BODY > HTML > #document toDOMRange:range from 31 of #text > P > BODY > HTML > #document to 31 of #text > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 ALERT: Test result: PASS
 
index 974d86ab5bf6facd24ea941d9599a76c53fa2bfe..7240cec202085353877d779878f731821448b076 100644 (file)
@@ -1,3 +1,29 @@
+2006-07-21  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Darin.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9312
+          REGRESSION: Selection bug in new text fields when selecting past the first letter
+
+        Test: editing/selection/select-from-textfield-outwards.html
+
+        * editing/Selection.cpp:
+        (WebCore::Selection::adjustForEditableContent): Added code to handle the case
+        where the selection starts (resp. ends) in the last (resp. first) visual position
+        inside an editable root.
+        * editing/htmlediting.cpp:
+        (WebCore::comparePositions): Fixed the case of comparing a position inside a shadow
+        tree with a position in the shadow ancestor.
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::positionForCoordinates): For coordinates outside a replaced
+        object, return the position just before (after) the element if the coordinates are above or
+        to the left (below or to the right).
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::caretMaxOffset): Changed to return 1 for replaced objects.
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::positionForCoordinates): Changed to return the last position
+        in the lowest text box if the y coordinate is below all text boxes.
+
 2006-07-21  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Darin.
index ea2debab5739f4f1f7de2be1ffd6821e30ebde1d..fc401444af70d56a69e64a3e55f489f7ddbd6976 100644 (file)
@@ -336,6 +336,8 @@ void Selection::adjustForEditableContent()
         if (endRoot || endEditableAncestor != baseEditableAncestor) {
             
             Position p = previousVisuallyDistinctCandidate(m_end);
+            if (p.isNull() && endRoot && endRoot->isShadowNode())
+                p = Position(endRoot->shadowParentNode(), maxDeepOffset(endRoot->shadowParentNode()));
             while (p.isNotNull() && !(lowestEditableAncestor(p.node()) == baseEditableAncestor && !isEditablePosition(p))) {
                 Node* root = editableRootForPosition(p);
                 Node* shadowParent = root && root->isShadowNode() ? root->shadowParentNode() : 0;
@@ -360,6 +362,8 @@ void Selection::adjustForEditableContent()
         Node* startEditableAncestor = lowestEditableAncestor(m_start.node());      
         if (startRoot || startEditableAncestor != baseEditableAncestor) {
             Position p = nextVisuallyDistinctCandidate(m_start);
+            if (p.isNull() && startRoot && startRoot->isShadowNode())
+                p = Position(startRoot->shadowParentNode(), 0);
             while (p.isNotNull() && !(lowestEditableAncestor(p.node()) == baseEditableAncestor && !isEditablePosition(p))) {
                 Node* root = editableRootForPosition(p);
                 Node* shadowParent = root && root->isShadowNode() ? root->shadowParentNode() : 0;
index b282672c89fe24147ce9480185656be3a1979154..b3104fd94a713a9ff23170fd4c2aab8bb98814e1 100644 (file)
@@ -100,18 +100,22 @@ int comparePositions(const Position& a, const Position& b)
     if (shadowAncestorB == nodeB)
         shadowAncestorB = 0;
 
+    int bias = 0;
     if (shadowAncestorA != shadowAncestorB) {
         if (shadowAncestorA) {
             nodeA = shadowAncestorA;
             offsetA = 0;
+            bias = 1;
         }
         if (shadowAncestorB) {
             nodeB = shadowAncestorB;
             offsetB = 0;
+            bias = -1;
         }
     }
 
-    return Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);
+    int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB);
+    return result ? result : bias;
 }
 
 Node* highestEditableRoot(const Position& position)
index ebc411f2fd3cce5ca376e3f6f43408d0cab03dc2..19f6783873bb7fca527c113770a3536a05e16ef9 100644 (file)
@@ -2621,6 +2621,13 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
     // a document that is entirely editable.
     bool isEditableRoot = n && n->rootEditableElement() == n && !n->hasTagName(bodyTag) && !n->hasTagName(htmlTag);
 
+    if (isReplaced()) {
+        if (y < absy || y < absy + height() && x < absx)
+            return VisiblePosition(n, caretMinOffset(), DOWNSTREAM);
+        if (y >= absy + height() || y >= absy && x >= absx + width())
+            return VisiblePosition(n, caretMaxOffset(), DOWNSTREAM);
+    }
+
     if (y < top || (isEditableRoot && (y < bottom && x < left))) {
         if (!isEditableRoot)
             if (RenderObject* c = firstChild()) {
index dfbbc59f8eb734caeb9c0c306d40b0ae306f1eb2..2fa01bd99027712adfb16a95d4bb974801f48917 100644 (file)
@@ -2873,7 +2873,7 @@ int RenderObject::caretMinOffset() const
 
 int RenderObject::caretMaxOffset() const
 {
-    return 0;
+    return isReplaced() ? 1 : 0;
 }
 
 unsigned RenderObject::caretMaxRenderedOffset() const
index 806f0bb8ef3edfb80f646f795b3f5359f916353a..ced88aa226839b995482a3b3f5ab2b97a4b67609 100644 (file)
@@ -247,13 +247,13 @@ InlineTextBox* RenderText::findNextInlineTextBox(int offset, int &pos) const
     return s;
 }
 
-VisiblePosition RenderText::positionForCoordinates(int _x, int _y)
+VisiblePosition RenderText::positionForCoordinates(int x, int y)
 {
     if (!firstTextBox() || stringLength() == 0)
         return VisiblePosition(element(), 0, DOWNSTREAM);
 
     int absx, absy;
-    RenderBlock *cb = containingBlock();
+    RenderBlockcb = containingBlock();
     cb->absolutePositionForContent(absx, absy);
     if (cb->hasOverflowClip())
         cb->layer()->subtractScrollOffset(absx, absy);
@@ -262,47 +262,51 @@ VisiblePosition RenderText::positionForCoordinates(int _x, int _y)
     int offset;
     
     // FIXME: We should be able to roll these special cases into the general cases in the loop below.
-    if (firstTextBox() && _y < absy + firstTextBox()->root()->bottomOverflow() && _x < absx + firstTextBox()->m_x) {
+    if (firstTextBox() && y < absy + firstTextBox()->root()->bottomOverflow() && x < absx + firstTextBox()->m_x) {
         // at the y coordinate of the first line or above
         // and the x coordinate is to the left of the first text box left edge
-        offset = firstTextBox()->offsetForPosition(_x - absx);
+        offset = firstTextBox()->offsetForPosition(x - absx);
         return VisiblePosition(element(), offset + firstTextBox()->m_start, DOWNSTREAM);
     }
-    if (lastTextBox() && _y >= absy + lastTextBox()->root()->topOverflow() && _x >= absx + lastTextBox()->m_x + lastTextBox()->m_width) {
+    if (lastTextBox() && y >= absy + lastTextBox()->root()->topOverflow() && x >= absx + lastTextBox()->m_x + lastTextBox()->m_width) {
         // at the y coordinate of the last line or below
         // and the x coordinate is to the right of the last text box right edge
-        offset = lastTextBox()->offsetForPosition(_x - absx);
+        offset = lastTextBox()->offsetForPosition(x - absx);
         return VisiblePosition(element(), offset + lastTextBox()->m_start, DOWNSTREAM);
     }
 
-    for (InlineTextBox *box = firstTextBox(); box; box = box->nextTextBox()) {
-        if (_y >= absy + box->root()->topOverflow() && _y < absy + box->root()->bottomOverflow()) {
-            offset = box->offsetForPosition(_x - absx);
-
-            if (_x == absx + box->m_x)
-                // the x coordinate is equal to the left edge of this box
-                // the affinity must be downstream so the position doesn't jump back to the previous line
-                return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
-
-            if (_x < absx + box->m_x + box->m_width)
-                // and the x coordinate is to the left of the right edge of this box
-                // check to see if position goes in this box
-                return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
-
-            if (!box->prevOnLine() && _x < absx + box->m_x)
-                // box is first on line
-                // and the x coordinate is to the left of the first text box left edge
-                return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
-
-            if (!box->nextOnLine())
-                // box is last on line
-                // and the x coordinate is to the right of the last text box right edge
-                // generate VisiblePosition, use UPSTREAM affinity if possible
-                return VisiblePosition(element(), offset + box->m_start, VP_UPSTREAM_IF_POSSIBLE);
+    InlineTextBox* lastBoxAbove = 0;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (y >= absy + box->root()->topOverflow()) {
+            if (y < absy + box->root()->bottomOverflow()) {
+                offset = box->offsetForPosition(x - absx);
+
+                if (x == absx + box->m_x)
+                    // the x coordinate is equal to the left edge of this box
+                    // the affinity must be downstream so the position doesn't jump back to the previous line
+                    return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+
+                if (x < absx + box->m_x + box->m_width)
+                    // and the x coordinate is to the left of the right edge of this box
+                    // check to see if position goes in this box
+                    return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+
+                if (!box->prevOnLine() && x < absx + box->m_x)
+                    // box is first on line
+                    // and the x coordinate is to the left of the first text box left edge
+                    return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+
+                if (!box->nextOnLine())
+                    // box is last on line
+                    // and the x coordinate is to the right of the last text box right edge
+                    // generate VisiblePosition, use UPSTREAM affinity if possible
+                    return VisiblePosition(element(), offset + box->m_start, VP_UPSTREAM_IF_POSSIBLE);
+            }
+            lastBoxAbove = box;
         }
     }
     
-    return VisiblePosition(element(), 0, DOWNSTREAM);
+    return VisiblePosition(element(), lastBoxAbove ? lastBoxAbove->m_start + lastBoxAbove->m_len : 0, DOWNSTREAM);
 }
 
 #if __GNUC__