[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.21-584-g1e41756

ojan at chromium.org ojan at chromium.org
Fri Feb 26 22:25:00 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit e74aea90bed51a239d84eba1384706a6beaef451
Author: ojan at chromium.org <ojan at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Feb 18 19:38:14 2010 +0000

    2010-02-17  Ojan Vafai  <ojan at chromium.org>
    
            Reviewed by Adam Barth.
    
            keyboard selection sometimes moves the wrong end of the selection for Win/Linux
            https://bugs.webkit.org/show_bug.cgi?id=35066
    
            The changes to js-test-selection-shared.js are just to make the selection editing tests
            easier to debug in the future.
    
            The mac results for extend-after-mouse-selection.html contain a "FAIL" line. This is
            a case where WebKit doesn't match TextEdit.
    
            * editing/editing.js:
            (execMoveSelectionForwardByLineBoundaryCommand):
            (moveSelectionForwardByLineBoundaryCommand):
            (execExtendSelectionForwardByLineBoundaryCommand):
            (extendSelectionForwardByLineBoundaryCommand):
            (execExtendSelectionBackwardByLineBoundaryCommand):
            (extendSelectionBackwardByLineBoundaryCommand):
            (execMoveSelectionBackwardByLineBoundaryCommand):
            (moveSelectionBackwardByLineBoundaryCommand):
            * editing/selection/extend-after-mouse-selection.html: Added.
            * editing/selection/move-begin-end-expected.txt:
            * editing/selection/move-begin-end.html:
            * editing/selection/resources/js-test-selection-shared.js:
            (objectAsString):
            (assertSelectionAt):
            * platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt:
            * platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt:
            * platform/mac/editing/selection/extend-after-mouse-selection-expected.txt: Added.
            * platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt:
            * platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt:
            * platform/win/editing/selection/extend-after-mouse-selection-expected.txt: Added.
            * platform/win/editing/selection/extend-selection-expected.txt: Added.
    2010-02-17  Ojan Vafai  <ojan at chromium.org>
    
            Reviewed by Adam Barth.
    
            keyboard selection sometimes moves the wrong end of the selection for Win/Linux
            https://bugs.webkit.org/show_bug.cgi?id=35066
    
            On Windows/Linux keyboard based selections should always move the same
            end of the seleciton. On Mac, lineboundary and documentboundary changes
            move different ends of the selection depending on which direction your
            extending.
    
            Test: editing/selection/extend-after-mouse-selection.html
    
            * editing/SelectionController.cpp:
            (WebCore::SelectionController::positionForPlatform):
            (WebCore::SelectionController::startForPlatform):
            (WebCore::SelectionController::endForPlatform):
            (WebCore::SelectionController::modifyExtendingRight):
            (WebCore::SelectionController::modifyExtendingForward):
            (WebCore::SelectionController::modifyMovingForward):
            (WebCore::SelectionController::modifyExtendingBackward):
            (WebCore::SelectionController::modifyMovingBackward):
            * editing/SelectionController.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54980 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index e134170..fa67e40 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,39 @@
+2010-02-17  Ojan Vafai  <ojan at chromium.org>
+
+        Reviewed by Adam Barth.
+
+        keyboard selection sometimes moves the wrong end of the selection for Win/Linux
+        https://bugs.webkit.org/show_bug.cgi?id=35066
+
+        The changes to js-test-selection-shared.js are just to make the selection editing tests
+        easier to debug in the future.
+
+        The mac results for extend-after-mouse-selection.html contain a "FAIL" line. This is
+        a case where WebKit doesn't match TextEdit.
+
+        * editing/editing.js:
+        (execMoveSelectionForwardByLineBoundaryCommand):
+        (moveSelectionForwardByLineBoundaryCommand):
+        (execExtendSelectionForwardByLineBoundaryCommand):
+        (extendSelectionForwardByLineBoundaryCommand):
+        (execExtendSelectionBackwardByLineBoundaryCommand):
+        (extendSelectionBackwardByLineBoundaryCommand):
+        (execMoveSelectionBackwardByLineBoundaryCommand):
+        (moveSelectionBackwardByLineBoundaryCommand):
+        * editing/selection/extend-after-mouse-selection.html: Added.
+        * editing/selection/move-begin-end-expected.txt:
+        * editing/selection/move-begin-end.html:
+        * editing/selection/resources/js-test-selection-shared.js:
+        (objectAsString):
+        (assertSelectionAt):
+        * platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt:
+        * platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt:
+        * platform/mac/editing/selection/extend-after-mouse-selection-expected.txt: Added.
+        * platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt:
+        * platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt:
+        * platform/win/editing/selection/extend-after-mouse-selection-expected.txt: Added.
+        * platform/win/editing/selection/extend-selection-expected.txt: Added.
+
 2010-02-18  Nate Chapin  <japhet at chromium.org>
 
         Unreviewed, build fix.
diff --git a/LayoutTests/editing/editing.js b/LayoutTests/editing/editing.js
index 94833aa..f1b80dd 100644
--- a/LayoutTests/editing/editing.js
+++ b/LayoutTests/editing/editing.js
@@ -159,6 +159,36 @@ function extendSelectionForwardByLineCommand() {
 
 //-------------------------------------------------------------------------------------------------------
 
+function execMoveSelectionForwardByLineBoundaryCommand() {
+    selection.modify("move", "forward", "lineBoundary");
+}
+function moveSelectionForwardByLineBoundaryCommand() {
+    if (commandDelay > 0) {
+        window.setTimeout(execMoveSelectionForwardByLineBoundaryCommand, commandCount * commandDelay);
+        commandCount++;
+    }
+    else {
+        execMoveSelectionForwardByLineBoundaryCommand();
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
+function execExtendSelectionForwardByLineBoundaryCommand() {
+    selection.modify("extend", "forward", "lineBoundary");
+}
+function extendSelectionForwardByLineBoundaryCommand() {
+    if (commandDelay > 0) {
+        window.setTimeout(execExtendSelectionForwardByLineBoundaryCommand, commandCount * commandDelay);
+        commandCount++;
+    }
+    else {
+        execExtendSelectionForwardByLineBoundaryCommand();
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
 function execMoveSelectionBackwardByCharacterCommand() {
     selection.modify("move", "backward", "character");
 }
@@ -279,6 +309,36 @@ function extendSelectionBackwardByLineCommand() {
 
 //-------------------------------------------------------------------------------------------------------
 
+function execExtendSelectionBackwardByLineBoundaryCommand() {
+    selection.modify("extend", "backward", "lineBoundary");
+}
+function extendSelectionBackwardByLineBoundaryCommand() {
+    if (commandDelay > 0) {
+        window.setTimeout(execExtendSelectionBackwardByLineBoundaryCommand, commandCount * commandDelay);
+        commandCount++;
+    }
+    else {
+        execExtendSelectionBackwardByLineBoundaryCommand();
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
+function execMoveSelectionBackwardByLineBoundaryCommand() {
+    selection.modify("move", "backward", "lineBoundary");
+}
+function moveSelectionBackwardByLineBoundaryCommand() {
+    if (commandDelay > 0) {
+        window.setTimeout(execMoveSelectionBackwardByLineBoundaryCommand, commandCount * commandDelay);
+        commandCount++;
+    }
+    else {
+        execMoveSelectionBackwardByLineBoundaryCommand();
+    }
+}
+
+//-------------------------------------------------------------------------------------------------------
+
 function execBoldCommand() {
     document.execCommand("Bold");
     debugForDumpAsText("execBoldCommand");
diff --git a/LayoutTests/editing/selection/extend-after-mouse-selection.html b/LayoutTests/editing/selection/extend-after-mouse-selection.html
new file mode 100644
index 0000000..aedfe2f
--- /dev/null
+++ b/LayoutTests/editing/selection/extend-after-mouse-selection.html
@@ -0,0 +1,82 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    border: 2px solid red; 
+    font-size: 24px; 
+}
+</style>
+<script src="../editing.js"></script>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/js-test-selection-shared.js"></script>
+
+<script>
+// FIXME: Expose settings->editingBehavior() and use that here instead.
+var onMacPlatform = navigator.userAgent.search(/\bMac OS X\b/) != -1;
+
+function editingTest() {
+    var startTarget = document.getElementById('start');
+    var endTarget = document.getElementById('end');
+
+    eventSender.mouseMoveTo(startTarget.offsetLeft, startTarget.offsetTop + 10);
+    // Double-click to select at word-granularity to workaround eventSender bug with selecting text at
+    // character granularity (i.e. that it just doesn't work).
+    eventSender.mouseDown();
+    eventSender.mouseUp();    
+    eventSender.mouseDown();
+    eventSender.mouseMoveTo(endTarget.offsetLeft, endTarget.offsetTop + 10);
+    eventSender.mouseUp();    
+
+    assertSelectionAt(startTarget.firstChild, 0, endTarget.firstChild, 2);
+
+    extendSelectionBackwardByCharacterCommand();
+
+    // The first character-granularity selection after a mouse-selection resets the anchor/focus.
+    // FIXME: On Win/Linux the anchor/focus should be fixed after the mouse-selection.
+    assertSelectionAt(endTarget.firstChild, 2, startTarget.previousSibling, 1);
+
+    extendSelectionForwardByCharacterCommand();
+    assertSelectionAt(endTarget.firstChild, 2, startTarget.firstChild, 0);
+    
+    extendSelectionForwardByLineBoundaryCommand();
+    
+    if (onMacPlatform) {
+        // FIXME: This encodes what TextEdit does. Currently WebKit does the wrong thing.
+        // The selection should go from the beginning of startTarget to the end of the line that endTarget is on.
+        assertSelectionAt(endTarget.nextSibling, 1, startTarget.firstChild, 0);
+    } else {
+        // Seleciton goes from the end of "ef" to the first BR element in the contentEditable region.
+        assertSelectionAt(endTarget.firstChild, 2, document.getElementById('test'), 3);
+    }
+    
+    extendSelectionBackwardByLineBoundaryCommand();
+
+    if (onMacPlatform) {
+        // FIXME: This encodes what TextEdit does. Currently WebKit does the wrong thing.
+        // The selection should contain the both entire lines that endTarget and startTarget are on.
+        assertSelectionAt(endTarget.nextSibling, 1, startTarget.previousSibling, 0);
+    } else
+        assertSelectionAt(endTarget.firstChild, 2, startTarget.previousSibling, 0);
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div contenteditable id="root" class="editing">
+    <span id="test">a <span id="start">bc</span> <br>d <span id="end">ef</span> <br>ghi</span>
+</div>
+
+<div id="console"></div>
+
+<script>
+editingTest();
+var successfullyParsed = true;
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/selection/move-begin-end-expected.txt b/LayoutTests/editing/selection/move-begin-end-expected.txt
index 6083af7..3840b6f 100644
--- a/LayoutTests/editing/selection/move-begin-end-expected.txt
+++ b/LayoutTests/editing/selection/move-begin-end-expected.txt
@@ -1,8 +1,8 @@
-EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 8 of DIV > BODY > HTML > #document
+EDITING DELEGATE: shouldBeginEditingInDOMRange:range from 0 of DIV > BODY > HTML > #document to 1 of DIV > BODY > HTML > #document
 EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
+EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 9 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > 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 #text > DIV > BODY > HTML > #document to 9 of #text > 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: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document toDOMRange:range from 9 of #text > DIV > BODY > HTML > #document to 9 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
 EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
diff --git a/LayoutTests/editing/selection/move-begin-end.html b/LayoutTests/editing/selection/move-begin-end.html
index f9b2218..d6b4f9b 100644
--- a/LayoutTests/editing/selection/move-begin-end.html
+++ b/LayoutTests/editing/selection/move-begin-end.html
@@ -72,7 +72,7 @@ if (window.layoutTestController)
         </script>
     </head>
     <body onload="runTest();">
-        <div contenteditable id="area">Some text</textarea>
+        <div contenteditable id="area">Some text</div>
         <div>This tests that moving the caret and selecting using Command+Left/Right arrows work correctly. If this text is successful, the text "SUCCESS" will be shown below.</div>
         <div id="result">FAILURE</div>
     </body>
diff --git a/LayoutTests/editing/selection/resources/js-test-selection-shared.js b/LayoutTests/editing/selection/resources/js-test-selection-shared.js
index 0a064ed..dd23e55 100644
--- a/LayoutTests/editing/selection/resources/js-test-selection-shared.js
+++ b/LayoutTests/editing/selection/resources/js-test-selection-shared.js
@@ -7,7 +7,7 @@ function objectAsString(object, properties) {
 
         var value = object[property];
         if (value && value.nodeType) // textNode
-            value = value + "( " + value.nodeValue + " )";
+            value = value + "(" + value.nodeValue + ")";
 
         result += property + ": " + value;
     }
@@ -21,16 +21,20 @@ function selectionAsString(sel)
     return objectAsString(sel, properties);
 }
 
-function assertSelectionAt(node, offset) {
+function assertSelectionAt(anchorNode, anchorOffset, optFocusNode, optFocusOffset) {
+    var focusNode = optFocusNode || anchorNode;
+    var focusOffset = (optFocusOffset === undefined) ? anchorOffset : optFocusOffset;
+
     var sel = window.getSelection();
-    if (sel.anchorNode == node
-        && sel.focusNode == node
-        && sel.anchorOffset == offset
-        && sel.focusOffset == offset
-        && sel.isCollapsed) {
-        testPassed("Selection is at node: " + node + " offset: " + offset);
+    if (sel.anchorNode == anchorNode
+        && sel.focusNode == focusNode
+        && sel.anchorOffset == anchorOffset
+        && sel.focusOffset == focusOffset) {
+        testPassed("Selection is " + selectionAsString(sel));
     } else {
-        testFailed("Selection is " + selectionAsString(sel) + " should be at node: " + node + " offset: " + offset);
+        testFailed("Selection is " + selectionAsString(sel) + 
+            " should be at anchorNode: " + anchorNode + " anchorOffset: " + anchorOffset +
+            " focusNode: " + focusNode + " focusOffset: " + focusOffset);
     }
 }
 
diff --git a/LayoutTests/platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt b/LayoutTests/platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt
index ca7bbe4..2f8d5a5 100644
--- a/LayoutTests/platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt
+++ b/LayoutTests/platform/mac/editing/selection/click-in-margins-inside-editable-div-expected.txt
@@ -3,20 +3,20 @@ Ensure cursor placement matches IE6/IE7/FF3 when clicking above/below lines in p
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 2
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 0 focusNode: [object Text](YY) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 0 focusNode: [object Text](YY) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 0 focusNode: [object Text](YY) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 2 focusNode: [object Text](YY) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 2 focusNode: [object Text](YY) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 2 focusNode: [object Text](YY) focusOffset: 2 isCollapsed: true]
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt b/LayoutTests/platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
index e8a4563..182c0eb 100644
--- a/LayoutTests/platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
+++ b/LayoutTests/platform/mac/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
@@ -3,8 +3,8 @@ Click above/beneath the word FOO. Notice how the cursor goes in the right place
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 3
+PASS Selection is [anchorNode: [object Text](12345) anchorOffset: 0 focusNode: [object Text](12345) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](BAR) anchorOffset: 3 focusNode: [object Text](BAR) focusOffset: 3 isCollapsed: true]
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/mac/editing/selection/extend-after-mouse-selection-expected.txt b/LayoutTests/platform/mac/editing/selection/extend-after-mouse-selection-expected.txt
new file mode 100644
index 0000000..2b64a2b
--- /dev/null
+++ b/LayoutTests/platform/mac/editing/selection/extend-after-mouse-selection-expected.txt
@@ -0,0 +1,12 @@
+a bc 
+d ef 
+ghi
+PASS Selection is [anchorNode: [object Text](bc) anchorOffset: 0 focusNode: [object Text](ef) focusOffset: 2 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](a ) focusOffset: 1 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](bc) focusOffset: 0 isCollapsed: false]
+FAIL Selection is [anchorNode: [object Text]( ) anchorOffset: 0 focusNode: [object Text]( ) focusOffset: 1 isCollapsed: false] should be at anchorNode: [object Text] anchorOffset: 1 focusNode: [object Text] focusOffset: 0
+FAIL Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](d ) focusOffset: 0 isCollapsed: false] should be at anchorNode: [object Text] anchorOffset: 1 focusNode: [object Text] focusOffset: 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt b/LayoutTests/platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt
index a9f3d11..80eebbb 100644
--- a/LayoutTests/platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt
+++ b/LayoutTests/platform/win/editing/selection/click-in-margins-inside-editable-div-expected.txt
@@ -3,20 +3,20 @@ Ensure cursor placement matches IE6/IE7/FF3 when clicking above/below lines in p
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 1
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 1
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 1
-PASS Selection is at node: [object Text] offset: 2
-PASS Selection is at node: [object Text] offset: 0
-PASS Selection is at node: [object Text] offset: 1
-PASS Selection is at node: [object Text] offset: 2
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 1 focusNode: [object Text](XX) focusOffset: 1 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 0 focusNode: [object Text](XX) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 1 focusNode: [object Text](XX) focusOffset: 1 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](XX) anchorOffset: 2 focusNode: [object Text](XX) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 0 focusNode: [object Text](YY) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 1 focusNode: [object Text](YY) focusOffset: 1 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 2 focusNode: [object Text](YY) focusOffset: 2 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 0 focusNode: [object Text](YY) focusOffset: 0 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 1 focusNode: [object Text](YY) focusOffset: 1 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](YY) anchorOffset: 2 focusNode: [object Text](YY) focusOffset: 2 isCollapsed: true]
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt b/LayoutTests/platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
index 8dc7c07..ce31cfd 100644
--- a/LayoutTests/platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
+++ b/LayoutTests/platform/win/editing/selection/click-in-padding-with-multiple-line-boxes-expected.txt
@@ -3,8 +3,8 @@ Click above/beneath the word FOO. Notice how the cursor goes in the right place
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS Selection is at node: [object Text] offset: 1
-PASS Selection is at node: [object Text] offset: 1
+PASS Selection is [anchorNode: [object Text](FOO) anchorOffset: 1 focusNode: [object Text](FOO) focusOffset: 1 isCollapsed: true]
+PASS Selection is [anchorNode: [object Text](FOO) anchorOffset: 1 focusNode: [object Text](FOO) focusOffset: 1 isCollapsed: true]
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/win/editing/selection/extend-after-mouse-selection-expected.txt b/LayoutTests/platform/win/editing/selection/extend-after-mouse-selection-expected.txt
new file mode 100644
index 0000000..0c5de09
--- /dev/null
+++ b/LayoutTests/platform/win/editing/selection/extend-after-mouse-selection-expected.txt
@@ -0,0 +1,12 @@
+a bc 
+d ef 
+ghi
+PASS Selection is [anchorNode: [object Text](bc) anchorOffset: 0 focusNode: [object Text](ef) focusOffset: 2 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](a ) focusOffset: 1 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](bc) focusOffset: 0 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object HTMLElement](null) focusOffset: 3 isCollapsed: false]
+PASS Selection is [anchorNode: [object Text](ef) anchorOffset: 2 focusNode: [object Text](a ) focusOffset: 0 isCollapsed: false]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/win/editing/selection/extend-selection-expected.txt b/LayoutTests/platform/win/editing/selection/extend-selection-expected.txt
new file mode 100644
index 0000000..5e57843
--- /dev/null
+++ b/LayoutTests/platform/win/editing/selection/extend-selection-expected.txt
@@ -0,0 +1,528 @@
+abc אבג xyz דהו def
+אבג xyz דהו def זחט
+אבג דהו אבג
+abc efd dabeb
+Lorem ipsum dolor sit amet
+Lorem ipsum dolor sit amet
+Lorem ipsum dolor sit amet
+Lorem ipsum dolor sit amet
+Lorem
+ipsum dolor sit
+amett
+Lorem ipsum dolor sit amet
+Lorem ipsum dolor
+just a test
+sit amet
+Lorem ipsum dolor sit amet
+Lorem
+ipsum dolor sit
+amet
+Just testing רק בודק
+Just testing what ever
+car means אבג.
+car דהו אבג.
+he said " car דהו אבג ."
+זחט יךכ לםמ ' he said " car דהו אבג " '?
+אבג abc דהו
+edf זחט abrebg
+abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg
+abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg
+
+
+
+Extending by character
+Test 1, LTR:
+  Extending right: "\nabc ABC xyz DEF def\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending left:  "\nabc ABC xyz DEF def\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+Test 1, RTL:
+  Extending left: "\nabc ABC xyz DEF def\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending right:  "\nabc ABC xyz DEF def\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending backward: "\nabc ABC xyz DEF def\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 2, LTR:
+  Extending right: "\nABC xyz DEF def GHI\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending left:  "\nABC xyz DEF def GHI\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+Test 2, RTL:
+  Extending left: "\nABC xyz DEF def GHI\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending right:  "\nABC xyz DEF def GHI\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14), (1,15), (1,16), (1,17), (1,18), (1,19), (1,20)]
+  Extending backward: "\nABC xyz DEF def GHI\n"[(1,20), (1,19), (1,18), (1,17), (1,16), (1,15), (1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 3, LTR:
+  Extending right: "\nABC DEF ABC\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12)]
+  Extending left:  "\nABC DEF ABC\n"[(1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12)]
+  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+Test 3, RTL:
+  Extending left: "\nABC DEF ABC\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12)]
+  Extending right:  "\nABC DEF ABC\n"[(1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12)]
+  Extending backward: "\nABC DEF ABC\n"[(1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 4, LTR:
+  Extending right: "\nabc efd dabeb\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14)]
+  Extending left:  "\nabc efd dabeb\n"[(1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14)]
+  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+Test 4, RTL:
+  Extending left: "\nabc efd dabeb\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14)]
+  Extending right:  "\nabc efd dabeb\n"[(1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7), (1,8), (1,9), (1,10), (1,11), (1,12), (1,13), (1,14)]
+  Extending backward: "\nabc efd dabeb\n"[(1,14), (1,13), (1,12), (1,11), (1,10), (1,9), (1,8), (1,7), (1,6), (1,5), (1,4), (1,3), (1,2), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 5, LTR:
+  Extending right: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending left:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+Test 5, RTL:
+  Extending left: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending right:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward: " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 6, LTR:
+  Extending right: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending left:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+Test 6, RTL:
+  Extending left: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending right:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward: " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 7, LTR:
+  Extending right: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending left:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+Test 7, RTL:
+  Extending left: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending right:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward: " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 8, LTR:
+  Extending right: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending left:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+Test 8, RTL:
+  Extending left: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending right:  " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6)], "ipsum dolor sit"[(0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amet"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending backward: " amet"[(0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "Lorem "[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+
+
+
+
+
+Extending by word
+Test 1, LTR:
+  Extending right: "\nabc ABC xyz DEF def\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending left:  "\nabc ABC xyz DEF def\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+Test 1, RTL:
+  Extending left: "\nabc ABC xyz DEF def\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending right:  "\nabc ABC xyz DEF def\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending backward: "\nabc ABC xyz DEF def\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 2, LTR:
+  Extending right: "\nABC xyz DEF def GHI\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending left:  "\nABC xyz DEF def GHI\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+Test 2, RTL:
+  Extending left: "\nABC xyz DEF def GHI\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending right:  "\nABC xyz DEF def GHI\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,4), (1,8), (1,12), (1,16), (1,20)]
+  Extending backward: "\nABC xyz DEF def GHI\n"[(1,20), (1,17), (1,13), (1,9), (1,5), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 3, LTR:
+  Extending right: "\nABC DEF ABC\n"[(1,1), (1,4), (1,8), (1,12)]
+  Extending left:  "\nABC DEF ABC\n"[(1,12), (1,9), (1,5), (1,1)]
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,4), (1,8), (1,12)]
+  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,9), (1,5), (1,1)]
+Test 3, RTL:
+  Extending left: "\nABC DEF ABC\n"[(1,1), (1,4), (1,8), (1,12)]
+  Extending right:  "\nABC DEF ABC\n"[(1,12), (1,9), (1,5), (1,1)]
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,4), (1,8), (1,12)]
+  Extending backward: "\nABC DEF ABC\n"[(1,12), (1,9), (1,5), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 4, LTR:
+  Extending right: "\nabc efd dabeb\n"[(1,1), (1,4), (1,8), (1,14)]
+  Extending left:  "\nabc efd dabeb\n"[(1,14), (1,9), (1,5), (1,1)]
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,4), (1,8), (1,14)]
+  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,9), (1,5), (1,1)]
+Test 4, RTL:
+  Extending left: "\nabc efd dabeb\n"[(1,1), (1,4), (1,8), (1,14)]
+  Extending right:  "\nabc efd dabeb\n"[(1,14), (1,9), (1,5), (1,1)]
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,4), (1,8), (1,14)]
+  Extending backward: "\nabc efd dabeb\n"[(1,14), (1,9), (1,5), (1,1)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 5, LTR:
+  Extending right: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending left:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+Test 5, RTL:
+  Extending left: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending right:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward: " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 6, LTR:
+  Extending right: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending left:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+Test 6, RTL:
+  Extending left: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending right:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward: " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 7, LTR:
+  Extending right: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending left:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+Test 7, RTL:
+  Extending left: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending right:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward: " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+Test 8, LTR:
+  Extending right: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending left:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+Test 8, RTL:
+  Extending left: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending right:  " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+  Extending forward: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amet"[(0,5)]
+  Extending backward: " amet"[(0,5), (0,1)], "ipsum dolor sit"[(0,12), (0,6)], "Lorem "[(0,6), (0,0)]
+
+
+  validating ltrRight and ltrLeft
+  validating ltrRight and ltrForward
+  validating ltrForward and rtlForward
+  validating ltrLeft and ltrBackward
+  validating ltrBackward and rtlBackward
+  validating ltrRight and rtlLeft
+  validating ltrLeft and rtlRight
+
+
+
+
+
+Extending by character
+Test 1, LTR:
+  Extending right: "Lorem "[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5)], "ipsum dolor sit"[(0,0), (0,1), (0,2), (0,3), (0,4), (0,5), (0,6), (0,7), (0,8), (0,9), (0,10), (0,11), (0,12), (0,13), (0,14), (0,15)], " amett"[(0,1), (0,2), (0,3), (0,4), (0,5)]
+  Extending left:  " amett"[(0,6), (0,5), (0,4), (0,3), (0,2), (0,1)], "ipsum dolor sit"[(0,15), (0,14), (0,13), (0,12), (0,11), (0,10), (0,9), (0,8), (0,7), (0,6), (0,5), (0,4), (0,3), (0,2), (0,1), (0,0)], "Lorem "[(0,5), (0,4), (0,3), (0,2), (0,1)]
+
+
+
+
+
+Extending by word
+Test 1, LTR:
+  Extending right: "Lorem "[(0,0), (0,5)], "ipsum dolor sit"[(0,5), (0,11), (0,15)], " amett"[(0,6), (0,1)]
+  Extending left:  " amett"[(0,6), (0,1)], "ipsum dolor sit"[(0,12), (0,6), (0,0)], "Lorem "[(0,0), (0,5)]
+
+
+
+Extending by lineBoundary
+Test 1, LTR:
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,20)]
+  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,1)]
+Test 1, RTL:
+  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,20)]
+  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,1)]
+Test 2, LTR:
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,20)]
+  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,1)]
+Test 2, RTL:
+  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,20)]
+  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,1)]
+Test 3, LTR:
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,12)]
+  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,1)]
+Test 3, RTL:
+  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,12)]
+  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,1)]
+Test 4, LTR:
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,14)]
+  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,1)]
+Test 4, RTL:
+  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,14)]
+  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,1)]
+Test 5, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 5, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 6, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 6, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 7, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 7, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 8, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 8, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 9, LTR:
+  Extending forward: "Lorem "[(0,0), (0,5)]
+  Extending backward:  "Lorem "[(0,5), (0,0)]
+Test 9, RTL:
+  Extending forward: "Lorem "[(0,0), (0,5)]
+  Extending backward:  "Lorem "[(0,5), (0,0)]
+Test 10, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 10, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 11, LTR:
+  Extending forward: "Lorem "[(0,0)], "ipsum dolor"[(0,11)]
+  Extending backward:  "ipsum dolor"[(0,11)], "Lorem "[(0,0)]
+Test 11, RTL:
+  Extending forward: "Lorem "[(0,0)], "ipsum dolor"[(0,11)]
+  Extending backward:  "ipsum dolor"[(0,11)], "Lorem "[(0,0)]
+Test 12, LTR:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 12, RTL:
+  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
+  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
+Test 13, LTR:
+  Extending forward: "Lorem "[(0,0), (0,5)]
+  Extending backward:  "Lorem "[(0,5), (0,0)]
+Test 13, RTL:
+  Extending forward: "Lorem "[(0,0), (0,5)]
+  Extending backward:  "Lorem "[(0,5), (0,0)]
+Test 14, LTR:
+  Extending forward: "\n Just\n "[(2,2)], "\n BFDX\n"[(2,6)]
+  Extending backward:  "\n BFDX\n"[(2,6)], "\n Just\n "[(2,2)]
+Test 14, RTL:
+  Extending forward: "\n Just\n "[(2,2)], "\n BFDX\n"[(2,6)]
+  Extending backward:  "\n BFDX\n"[(2,6)], "\n Just\n "[(2,2)]
+Test 15, LTR:
+  Extending forward: "\n Just\n "[(2,2)], "\n ever\n"[(2,6)]
+  Extending backward:  "\n ever\n"[(2,6)], "\n Just\n "[(2,2)]
+Test 15, RTL:
+  Extending forward: "\n Just\n "[(2,2)], "\n ever\n"[(2,6)]
+  Extending backward:  "\n ever\n"[(2,6)], "\n Just\n "[(2,2)]
+Test 16, LTR:
+  Extending forward: "car means ABC."[(0,0), (0,14)]
+  Extending backward:  "car means ABC."[(0,14), (0,0)]
+Test 16, RTL:
+  Extending forward: "car means ABC."[(0,0), (0,14)]
+  Extending backward:  "car means ABC."[(0,14), (0,0)]
+Test 17, LTR:
+  Extending forward: "᪜car DEF ABC.᪝"[(1,1), (1,13)]
+  Extending backward:  "᪜car DEF ABC.᪝"[(1,13), (1,1)]
+Test 17, RTL:
+  Extending forward: "᪜car DEF ABC.᪝"[(1,1), (1,13)]
+  Extending backward:  "᪜car DEF ABC.᪝"[(1,13), (1,1)]
+Test 18, LTR:
+  Extending forward: "he said "᪜car DEF ABC᪝.""[(0,0), (0,24)]
+  Extending backward:  "he said "᪜car DEF ABC᪝.""[(0,24), (0,0)]
+Test 18, RTL:
+  Extending forward: "he said "᪜car DEF ABC᪝.""[(0,0), (0,24)]
+  Extending backward:  "he said "᪜car DEF ABC᪝.""[(0,24), (0,0)]
+Test 19, LTR:
+  Extending forward: "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,0), (0,40)]
+  Extending backward:  "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,40), (0,0)]
+Test 19, RTL:
+  Extending forward: "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,0), (0,40)]
+  Extending backward:  "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,40), (0,0)]
+Test 20, LTR:
+  Extending forward: "ABC abc DEF"[(0,0), (0,11)]
+  Extending backward:  "ABC abc DEF"[(0,11), (0,0)]
+Test 20, RTL:
+  Extending forward: "ABC abc DEF"[(0,0), (0,11)]
+  Extending backward:  "ABC abc DEF"[(0,11), (0,0)]
+Test 21, LTR:
+  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,8), (0,16), (0,26), (0,34), (0,42), (0,50), (0,58), (0,66), (0,74), (0,82), (0,90), (0,98), (0,105)]
+  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,105), (0,98)]
+Test 21, RTL:
+  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,7)]
+  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,7), (0,0)]
+Test 22, LTR:
+  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,8), (0,16), (0,26), (0,34), (0,42), (0,50), (0,58), (0,66), (0,74), (0,82), (0,90), (0,98), (0,105)]
+  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,105), (0,98)]
+Test 22, RTL:
+  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,7)]
+  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,7), (0,0)]
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index cc32f48..93f07ae 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,28 @@
+2010-02-17  Ojan Vafai  <ojan at chromium.org>
+
+        Reviewed by Adam Barth.
+
+        keyboard selection sometimes moves the wrong end of the selection for Win/Linux
+        https://bugs.webkit.org/show_bug.cgi?id=35066
+
+        On Windows/Linux keyboard based selections should always move the same
+        end of the seleciton. On Mac, lineboundary and documentboundary changes
+        move different ends of the selection depending on which direction your
+        extending.
+
+        Test: editing/selection/extend-after-mouse-selection.html
+
+        * editing/SelectionController.cpp:
+        (WebCore::SelectionController::positionForPlatform):
+        (WebCore::SelectionController::startForPlatform):
+        (WebCore::SelectionController::endForPlatform):
+        (WebCore::SelectionController::modifyExtendingRight):
+        (WebCore::SelectionController::modifyExtendingForward):
+        (WebCore::SelectionController::modifyMovingForward):
+        (WebCore::SelectionController::modifyExtendingBackward):
+        (WebCore::SelectionController::modifyMovingBackward):
+        * editing/SelectionController.h:
+
 2010-02-18  Timothy Hatcher  <timothy at apple.com>
 
         Add "with" to the list of keywords to syntax highlight.
diff --git a/WebCore/editing/SelectionController.cpp b/WebCore/editing/SelectionController.cpp
index 786dcc1..25982d4 100644
--- a/WebCore/editing/SelectionController.cpp
+++ b/WebCore/editing/SelectionController.cpp
@@ -265,6 +265,33 @@ TextDirection SelectionController::directionOfEnclosingBlock()
     return LTR;
 }
 
+VisiblePosition SelectionController::positionForPlatform(bool isGetStart) const
+{
+    Position pos;
+    Settings* settings = m_frame ? m_frame->settings() : 0;
+    if (settings && settings->editingBehavior() == EditingMacBehavior)
+        pos = isGetStart ? m_selection.start() : m_selection.end();
+    else {
+        // Linux and Windows always extend selections from the extent endpoint.
+        // FIXME: VisibleSelection should be fixed to ensure as an invariant that
+        // base/extent always point to the same nodes as start/end, but which points
+        // to which depends on the value of isBaseFirst. Then this can be changed
+        // to just return m_sel.extent().
+        pos = m_selection.isBaseFirst() ? m_selection.end() : m_selection.start();
+    }
+    return VisiblePosition(pos, m_selection.affinity());
+}
+
+VisiblePosition SelectionController::startForPlatform() const
+{
+    return positionForPlatform(true);
+}
+
+VisiblePosition SelectionController::endForPlatform() const
+{
+    return positionForPlatform(false);
+}
+
 VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granularity)
 {
     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
@@ -298,7 +325,7 @@ VisiblePosition SelectionController::modifyExtendingRight(TextGranularity granul
             pos = modifyExtendingForward(granularity);
     }
     return pos;
-}    
+}
         
 VisiblePosition SelectionController::modifyExtendingForward(TextGranularity granularity)
 {
@@ -320,16 +347,16 @@ VisiblePosition SelectionController::modifyExtendingForward(TextGranularity gran
             pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case SentenceBoundary:
-            pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = endOfSentence(endForPlatform());
             break;
         case LineBoundary:
-            pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = logicalEndOfLine(endForPlatform());
             break;
         case ParagraphBoundary:
-            pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = endOfParagraph(endForPlatform());
             break;
         case DocumentBoundary:
-            pos = VisiblePosition(m_selection.end(), m_selection.affinity());
+            pos = endForPlatform();
             if (isEditablePosition(pos.deepEquivalent()))
                 pos = endOfEditableContent(pos);
             else
@@ -385,25 +412,25 @@ VisiblePosition SelectionController::modifyMovingForward(TextGranularity granula
         case LineGranularity: {
             // down-arrowing from a range selection that ends at the start of a line needs
             // to leave the selection at that line start (no need to call nextLinePosition!)
-            pos = VisiblePosition(m_selection.end(), m_selection.affinity());
+            pos = endForPlatform();
             if (!isRange() || !isStartOfLine(pos))
                 pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(START));
             break;
         }
         case ParagraphGranularity:
-            pos = nextParagraphPosition(VisiblePosition(m_selection.end(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
+            pos = nextParagraphPosition(endForPlatform(), xPosForVerticalArrowNavigation(START));
             break;
         case SentenceBoundary:
-            pos = endOfSentence(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = endOfSentence(endForPlatform());
             break;
         case LineBoundary:
-            pos = logicalEndOfLine(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = logicalEndOfLine(endForPlatform());
             break;
         case ParagraphBoundary:
-            pos = endOfParagraph(VisiblePosition(m_selection.end(), m_selection.affinity()));
+            pos = endOfParagraph(endForPlatform());
             break;
         case DocumentBoundary:
-            pos = VisiblePosition(m_selection.end(), m_selection.affinity());
+            pos = endForPlatform();
             if (isEditablePosition(pos.deepEquivalent()))
                 pos = endOfEditableContent(pos);
             else
@@ -473,16 +500,16 @@ VisiblePosition SelectionController::modifyExtendingBackward(TextGranularity gra
             pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case SentenceBoundary:
-            pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = startOfSentence(startForPlatform());
             break;
         case LineBoundary:
-            pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = logicalStartOfLine(startForPlatform());
             break;
         case ParagraphBoundary:
-            pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = startOfParagraph(startForPlatform());
             break;
         case DocumentBoundary:
-            pos = VisiblePosition(m_selection.start(), m_selection.affinity());
+            pos = startForPlatform();
             if (isEditablePosition(pos.deepEquivalent()))
                 pos = startOfEditableContent(pos);
             else 
@@ -534,22 +561,22 @@ VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granul
             pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
             break;
         case LineGranularity:
-            pos = previousLinePosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
+            pos = previousLinePosition(startForPlatform(), xPosForVerticalArrowNavigation(START));
             break;
         case ParagraphGranularity:
-            pos = previousParagraphPosition(VisiblePosition(m_selection.start(), m_selection.affinity()), xPosForVerticalArrowNavigation(START));
+            pos = previousParagraphPosition(startForPlatform(), xPosForVerticalArrowNavigation(START));
             break;
         case SentenceBoundary:
-            pos = startOfSentence(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = startOfSentence(startForPlatform());
             break;
         case LineBoundary:
-            pos = logicalStartOfLine(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = logicalStartOfLine(startForPlatform());
             break;
         case ParagraphBoundary:
-            pos = startOfParagraph(VisiblePosition(m_selection.start(), m_selection.affinity()));
+            pos = startOfParagraph(startForPlatform());
             break;
         case DocumentBoundary:
-            pos = VisiblePosition(m_selection.start(), m_selection.affinity());
+            pos = startForPlatform();
             if (isEditablePosition(pos.deepEquivalent()))
                 pos = startOfEditableContent(pos);
             else 
diff --git a/WebCore/editing/SelectionController.h b/WebCore/editing/SelectionController.h
index 7cad435..6849cb6 100644
--- a/WebCore/editing/SelectionController.h
+++ b/WebCore/editing/SelectionController.h
@@ -140,6 +140,10 @@ private:
 
     TextDirection directionOfEnclosingBlock();
 
+    VisiblePosition positionForPlatform(bool isGetStart) const;
+    VisiblePosition startForPlatform() const;
+    VisiblePosition endForPlatform() const;
+
     VisiblePosition modifyExtendingRight(TextGranularity);
     VisiblePosition modifyExtendingForward(TextGranularity);
     VisiblePosition modifyMovingRight(TextGranularity);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list