Source/WebCore: enable ctrl-arrow move by word visually in non-Windows platforms.
authorxji@chromium.org <xji@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 May 2012 03:41:29 +0000 (03:41 +0000)
committerxji@chromium.org <xji@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 May 2012 03:41:29 +0000 (03:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=85017

Reviewed by Ryosuke Niwa.

Enable ctrl-arrow moves caret by word in visual order in non-Windows platforms that use ICU word
break iterator (it is not enabled for WinCE and Qt where ICU is not used). For those platforms, ctrl-arrow
moves caret to word break position before spaces. For example, given a logical text "abc def hij", the word
break positions using ctrl-left-arrow from rightmost position are "|abc |def |hij".
The word break positions using ctrl-right-arrow from leftmost position are "abc| def| hij|".

Test: editing/selection/move-by-word-visually-mac.html

* editing/EditingBehavior.h:
(EditingBehavior):
(WebCore::EditingBehavior::shouldEatSpaceToNextWord): To control different word break positions
(regards to space) for different platforms.
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::modifyMovingRight): Enable visual word movement for all platforms that use ICU.
(WebCore::FrameSelection::modifyMovingLeft):
* editing/visible_units.cpp:
(WebCore::visualWordPosition): Determine the right word break position (regards to space) based on EditingBehavior.
(WebCore::leftWordPosition):
(WebCore::rightWordPosition):
* editing/visible_units.h:

LayoutTests: enable ctrl-arrow move by word visually in other platforms (besides Windows)
https://bugs.webkit.org/show_bug.cgi?id=85017

Reviewed by Ryosuke Niwa.

Since DOMSelection.modify('move', 'left'/'right', 'word') moves caret by word in visual order (instead of
logical order) now, there are several changes to the test file:
1. file name renamed from move-left-right-by-word-mac.html to move-by-word-visually-mac.html.
2. test expectations change from moving caret by word in logical order to moving caret by word in visual order.
3. since test expectations are inside test file itself, test file itself changes accordingly.

* editing/selection/move-by-word-visually-mac-expected.txt: Copied from LayoutTests/editing/selection/move-left-right-by-word-mac-expected.txt.
* editing/selection/move-by-word-visually-mac.html: Copied from LayoutTests/editing/selection/move-left-right-by-word-mac.html.
* editing/selection/move-left-right-by-word-mac-expected.txt: Removed.
* editing/selection/move-left-right-by-word-mac.html: Removed.

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

LayoutTests/ChangeLog
LayoutTests/editing/selection/move-by-word-visually-mac-expected.txt [new file with mode: 0644]
LayoutTests/editing/selection/move-by-word-visually-mac.html [new file with mode: 0644]
LayoutTests/editing/selection/move-left-right-by-word-mac-expected.txt [deleted file]
LayoutTests/editing/selection/move-left-right-by-word-mac.html [deleted file]
Source/WebCore/ChangeLog
Source/WebCore/editing/EditingBehavior.h
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/editing/visible_units.cpp
Source/WebCore/editing/visible_units.h

index b2f6086..c91c66f 100644 (file)
@@ -1,3 +1,21 @@
+2012-05-01  Xiaomei Ji  <xji@chromium.org>
+
+        enable ctrl-arrow move by word visually in other platforms (besides Windows)
+        https://bugs.webkit.org/show_bug.cgi?id=85017
+
+        Reviewed by Ryosuke Niwa.
+  
+        Since DOMSelection.modify('move', 'left'/'right', 'word') moves caret by word in visual order (instead of
+        logical order) now, there are several changes to the test file:
+        1. file name renamed from move-left-right-by-word-mac.html to move-by-word-visually-mac.html.
+        2. test expectations change from moving caret by word in logical order to moving caret by word in visual order.
+        3. since test expectations are inside test file itself, test file itself changes accordingly.
+       
+        * editing/selection/move-by-word-visually-mac-expected.txt: Copied from LayoutTests/editing/selection/move-left-right-by-word-mac-expected.txt.
+        * editing/selection/move-by-word-visually-mac.html: Copied from LayoutTests/editing/selection/move-left-right-by-word-mac.html.
+        * editing/selection/move-left-right-by-word-mac-expected.txt: Removed.
+        * editing/selection/move-left-right-by-word-mac.html: Removed.
+
 2012-05-01  Raymond Liu  <raymond.liu@intel.com>
 
         Modify RealtimeAnalyserNode pull mechanism
diff --git a/LayoutTests/editing/selection/move-by-word-visually-mac-expected.txt b/LayoutTests/editing/selection/move-by-word-visually-mac-expected.txt
new file mode 100644 (file)
index 0000000..efc8990
--- /dev/null
@@ -0,0 +1,128 @@
+
+======== Move By Word ====
+Test 1, LTR:
+Move right by one word
+"abc def hij opq rst"[0, 3, 7, 11, 15, 19]
+Move left by one word
+"abc def hij opq rst"[19, 16, 12, 8, 4, 0]
+Test 2, RTL:
+Move left by one word
+"abc def hij opq rst"[0, 16, 12, 8, 4, 19]
+Move right by one word
+"abc def hij opq rst"[19, 3, 7, 11, 15, 0]
+Test 3, LTR:
+Move right by one word
+"ZZZ QQQ BBB CCC XXX"[0, 16, 12, 8, 4, 19]
+Move left by one word
+"ZZZ QQQ BBB CCC XXX"[19, 3, 7, 11, 15, 0]
+Test 4, RTL:
+Move left by one word
+"ZZZ QQQ BBB CCC XXX"[0, 3, 7, 11, 15, 19]
+Move right by one word
+"ZZZ QQQ BBB CCC XXX"[19, 16, 12, 8, 4, 0]
+Test 5, LTR:
+Move right by one word
+"abc def hij AAA BBB WWW opr uvw xyz"[0, 3, 7, 11, 20, 16, 23, 27, 31, 35]
+Move left by one word
+"abc def hij AAA BBB WWW opr uvw xyz"[35, 32, 28, 24, 15, 19, 12, 8, 4, 0]
+Test 6, RTL:
+Move left by one word
+"abc def hij AAA BBB WWW opr uvw xyz"[0, 8, 4, 11, 15, 19, 23, 32, 28, 35]
+Move right by one word
+"abc def hij AAA BBB WWW opr uvw xyz"[35, 27, 31, 24, 20, 16, 12, 3, 7, 0]
+Test 7, LTR:
+Move right by one word
+"abc def ZQB RIG uvw xyz"[0, 3, 7, 12, 15, 19, 23]
+Move left by one word
+"abc def ZQB RIG uvw xyz"[23, 20, 16, 11, 8, 4, 0]
+Test 8, RTL:
+Move left by one word
+"abc def ZQB RIG uvw xyz"[0, 4, 7, 11, 15, 20, 23]
+Move right by one word
+"abc def ZQB RIG uvw xyz"[23, 19, 16, 12, 8, 3, 0]
+Test 9, LTR:
+Move right by one word
+"aaa AAA bbb"[0, 3, 7, 11]
+Move left by one word
+"aaa AAA bbb"[11, 8, 4, 0]
+Test 10, RTL:
+Move left by one word
+"aaa AAA bbb"[0, 3, 7, 11]
+Move right by one word
+"aaa AAA bbb"[11, 8, 4, 0]
+Test 11, LTR:
+Move right by one word
+"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[0, 8, 4, 11, 15, 19, 23, 32, 28, 35]
+Move left by one word
+"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[35, 27, 31, 24, 20, 16, 12, 3, 7, 0]
+Test 12, RTL:
+Move left by one word
+"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[0, 3, 7, 11, 20, 16, 23, 27, 31, 35]
+Move right by one word
+"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[35, 32, 28, 24, 15, 19, 12, 8, 4, 0]
+Test 13, LTR:
+Move right by one word
+"AAA BBB aaa bbb WWW DDD"[0, 4, 7, 11, 15, 20, 23]
+Move left by one word
+"AAA BBB aaa bbb WWW DDD"[23, 19, 16, 12, 8, 3, 0]
+Test 14, RTL:
+Move left by one word
+"AAA BBB aaa bbb WWW DDD"[0, 3, 7, 12, 15, 19, 23]
+Move right by one word
+"AAA BBB aaa bbb WWW DDD"[23, 20, 16, 11, 8, 4, 0]
+Test 15, LTR:
+Move right by one word
+"ZQB abc RIG"[0, 3, 7, 11]
+Move left by one word
+"ZQB abc RIG"[11, 8, 4, 0]
+Test 16, RTL:
+Move left by one word
+"ZQB abc RIG"[0, 3, 7, 11]
+Move right by one word
+"ZQB abc RIG"[11, 8, 4, 0]
+Test 17, LTR:
+Move right by one word
+"abc def ghi jkl mn "[0, 3, 7, 11, 15, 18], "opq rst uvw xyz"[3, 7, 11, 15]
+Move left by one word
+"opq rst uvw xyz"[15, 12, 8, 4, 0], "abc def ghi jkl mn "[16, 12, 8, 4, 0]
+Test 18, RTL:
+Move left by one word
+" abc def AAA AAA hij AAA AAA uvw xyz "[1, 5, 8, 12, 16, 20, 24, 28, 32, 36], <DIV>[0], "AAA kj AAA mn opq AAA AAA"[3, 6, 10, 13, 17, 21, 25]    FAIL expected: [" abc def AAA AAA hij AAA AAA uvw xyz "[ 1,  5,  8,  12,  16,  20,  24,  28,  32,  36, ]"AAA kj AAA mn opq AAA AAA"[ 3,  6,  10,  13,  17,  21,  25]
+" abc def AAA AAA hij AAA AAA uvw xyz "[36], <DIV>[0]   FAIL expected "AAA kj AAA mn opq AAA AAA"[ 3]
+Move right by one word
+"AAA kj AAA mn opq AAA AAA"[25, 22, 18, 14, 11, 7, 4, 0], " abc def AAA AAA hij AAA AAA uvw xyz "[33, 29, 25, 21, 17, 13, 9, 4, 1]
+Test 19, LTR:
+Move right by one word
+"abc def    hij opq"[0, 3, 7, 14, 18]
+Move left by one word
+"abc def    hij opq"[18, 15, 8, 4, 0]
+Test 20, LTR:
+Move right by one word
+"    abc    def    hij    opq    "[4, 7, 14, 21, 28]
+Move left by one word
+"    abc    def    hij    opq    "[28, 22, 15, 8, 4]
+Test 21, RTL:
+Move left by one word
+"    abc    def    hij    ABW    DSU    EJH    opq    rst    uvw    "[0, 18, 11, 21, 28, 35, 42, 60, 53, 63, 67]
+Move right by one word
+"    abc    def    hij    ABW    DSU    EJH    opq    rst    uvw    "[67, 49, 56, 46, 39, 32, 25, 7, 14, 4, 0]
+Test 22, RTL:
+Move left by one word
+"    ABW    DSU    HJH    FUX    "[0, 7, 14, 21, 28, 32]
+Move right by one word
+"    ABW    DSU    HJH    FUX    "[32, 25, 18, 11, 4, 0]
+Test 23, RTL:
+Move left by one word
+"abc def "[0], " rst uvw"[5, 1], "hij opq"[4], "abc def "[8, 4], " rst uvw"[8]
+Move right by one word
+" rst uvw"[8], "abc def "[3, 7], "hij opq"[3, 7], " rst uvw"[4], "abc def "[0]
+Test 24, RTL:
+Move left by one word
+"ABD opq rst DSU "[0, 3, 8, 11, 15], "abc uvw AAA def lmn"[16, 12, 11, 4, 19], "ABW hij xyz FXX"[3, 8, 11, 15]    FAIL expected: ["ABD opq rst DSU "[ 0,  3,  8,  11,  15, ]"abc uvw AAA def lmn"[ 16,  12,  11,  4, ]"ABW hij xyz FXX"[ 3,  8,  11,  15]
+"abc uvw AAA def lmn"[4, 19]   FAIL expected "ABW hij xyz FXX"[ 3]
+"abc uvw AAA def lmn"[3, 19]   FAIL expected "ABW hij xyz FXX"[ 3]
+"abc uvw AAA def lmn"[2, 19]   FAIL expected "ABW hij xyz FXX"[ 3]
+"abc uvw AAA def lmn"[1, 19]   FAIL expected "ABW hij xyz FXX"[ 3]
+Move right by one word
+"ABW hij xyz FXX"[15, 12, 7, 4], "abc uvw AAA def lmn"[3, 7, 8, 15], "ABD opq rst DSU "[16, 12, 7, 4, 0]
+
diff --git a/LayoutTests/editing/selection/move-by-word-visually-mac.html b/LayoutTests/editing/selection/move-by-word-visually-mac.html
new file mode 100644 (file)
index 0000000..c229efa
--- /dev/null
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel="stylesheet" type="text/css" href="resources/extend-selection.css" />
+<style>
+test_move_by_word {display: none;}
+</style>
+<script src="resources/move-by-word-visually.js"></script>
+<script>
+
+onload = function() {
+    try {
+        runTest();
+    } finally {
+        flushLog();
+    }
+};
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.setEditingBehavior('mac');
+}
+</script>
+</head>
+<body>
+<div id="testMoveByWord">
+<!-- 
+Title saves the word breaks.
+The format of title is "xxx|xxxx".
+
+The sequence on the left of "|" is word boundaries when moving caret from left to right.
+The sequence on the right of "|" is word boundaries when moving caret from right to left.
+
+If there is a single node in the line the sequence are offsets.
+If there are multiple nodes in the line the sequence is array of [anchor_node_id offset child_node_index] 
+where child_node_index is optional default is the first child of the anchor node.
+-->
+<!-- pure English -->
+<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19|19 16 12 8 4 0" contenteditable>abc def hij opq rst</div>
+<div dir=rtl class="test_move_by_word" title="19 3 7 11 15 0|0 16 12 8 4 19" contenteditable>abc def hij opq rst</div>
+
+<!-- pure Hebrew -->
+<div dir=ltr class="test_move_by_word" title="0 16 12 8 4 19|19 3 7 11 15 0" contenteditable>ששש נננ בבב גגג קקק</div>
+<div dir=rtl class="test_move_by_word" title="19 16 12 8 4 0|0 3 7 11 15 19" contenteditable>ששש נננ בבב גגג קקק</div>
+
+<!-- bidi text -->
+<!-- English Hebrew English -->
+<div dir=ltr class="test_move_by_word" title="0 3 7 11 20 16 23 27 31 35|35 32 28 24 15 19 12 8 4 0" contenteditable>abc def hij אאא בבב צצצ opr uvw xyz</div>
+<div dir=rtl class="test_move_by_word" title="35 27 31 24 20 16 12 3 7 0|0 8 4 11 15 19 23 32 28 35" contenteditable>abc def hij אאא בבב צצצ opr uvw xyz</div>
+
+<div dir=ltr class="test_move_by_word" title="0 3 7 12 15 19 23|23 20 16 11 8 4 0" contenteditable>abc def שנב סטז uvw xyz</div>
+<div dir=rtl class="test_move_by_word" title="23 19 16 12 8 3 0|0 4 7 11 15 20 23" contenteditable>abc def שנב סטז uvw xyz</div>
+
+<div dir=ltr class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>aaa אאא bbb</div>
+<div dir=rtl class="test_move_by_word" title="11 8 4 0|0 3 7 11" contenteditable>aaa אאא bbb</div>
+
+<!-- Hebrew English Hebrew -->
+<div dir=ltr class="test_move_by_word" title="0 8 4 11 15 19 23 32 28 35|35 27 31 24 20 16 12 3 7 0" contenteditable>אאא בבב צצצ aaa bbb ccc דדד עעע פפפ</div>
+<div dir=rtl class="test_move_by_word" title="35 32 28 24 15 19 12 8 4 0|0 3 7 11 20 16 23 27 31 35" contenteditable>אאא בבב צצצ aaa bbb ccc דדד עעע פפפ</div>
+
+<div dir=ltr class="test_move_by_word" title="0 4 7 11 15 20 23|23 19 16 12 8 3 0" contenteditable>אאא בבב aaa bbb צצצ דדד</div>
+<div dir=rtl class="test_move_by_word" title="23 20 16 11 8 4 0|0 3 7 12 15 19 23" contenteditable>אאא בבב aaa bbb צצצ דדד</div>
+
+<div dir=ltr class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>שנב abc סטז</div>
+<div dir=rtl class="test_move_by_word" title="11 8 4 0|0 3 7 11" contenteditable>שנב abc סטז</div>
+
+<!-- test multi-line -->
+<div><span style="font-family:arial;font-size:10px" class="fix_width" id="span_size">אאא אאא</span></div>
+<div style="font-family:arial;font-size:10px" contenteditable dir=ltr id="ml_1" class="test_move_by_word fix_width" title="[ml_1, 0][ml_1, 3][ml_1, 7][ml_1, 11][ml_1, 15][ml_1, 18][ml_1, 3, 5][ml_1, 7, 5][ml_1, 11, 5][ml_1, 15, 5]|[ml_1, 15, 5][ml_1, 12, 5][ml_1, 8, 5][ml_1, 4, 5][ml_1, 0, 5][ml_1, 16][ml_1, 12][ml_1, 8][ml_1, 4][ml_1, 0]">abc def ghi jkl mn <br/><br/><br/>opq rst uvw xyz</div>
+
+<div style="font-family:arial;font-size:10px" contenteditable dir=rtl id="ml_12" class="test_move_by_word fix_width" title="
+[ml_12, 25, 5][ml_12, 22, 5][ml_12, 18, 5][ml_12, 14, 5][ml_12, 11, 5][ml_12, 7, 5][ml_12, 4, 5][ml_12, 0, 5][ml_12, 33][ml_12, 29][ml_12, 25][ml_12, 21][ml_12, 17][ml_12, 13][ml_12, 9][ml_12, 4][ml_12, 1]|[ml_12, 1][ml_12, 5][ml_12, 8][ml_12, 12][ml_12, 16][ml_12, 20][ml_12, 24][ml_12, 28][ml_12, 32][ml_12, 36][ml_12, 3, 5][ml_12, 6, 5][ml_12, 10, 5][ml_12, 13, 5][ml_12, 17, 5][ml_12, 21, 5][ml_12, 25, 5]
+"> abc def אאא אאא hij אאא אאא uvw xyz <div><br/></div><div><br/></div><div><br/></div>אאא kj אאא mn opq אאא אאא</div>
+
+<!-- test multispaces -->
+<div dir=ltr class="test_move_by_word" title="0 3 7 14 18|18 15 8 4 0" contenteditable>abc def    hij opq</div>
+
+<!-- There are multiple spaces in the test, and the spaces will be collapsed. Thus, given an offset 25, which is
+     immediately before "opq", it's canonicalPosition is at offset 22, and the VisiblePosition created is based on
+     Position(22). That is why '22'(instead of 25) is the expected result when moving caret left by word from "opq|".
+     Same for the result of 15 and 8.
+ -->
+<div dir=ltr class="test_move_by_word" title="4 7 14 21 28|28 22 15 8 4" contenteditable>    abc    def    hij    opq    </div>
+
+<div style="white-space:pre" dir=rtl class="test_move_by_word" title="67 49 56 46 39 32 25 7 14 4 0|0 18 11 21 28 35 42 60 53 63 67" contenteditable>    abc    def    hij    אבצ    דעפ    היח    opq    rst    uvw    </div>
+<div style="white-space:pre" dir=rtl class="test_move_by_word" title="32 25 18 11 4 0|0 7 14 21 28 32" contenteditable>    אבצ    דעפ    חיח    ופק    </div>
+
+<!-- test inline element -->
+<div dir=rtl id="d_4" class="test_move_by_word" title="[d_4, 8, 3][d_4, 3, 1][d_4, 7, 1][s_4, 3, 1][s_4, 7, 1][d_4, 4, 3][d_4, 0, 1]|[d_4, 0, 1][d_4, 5, 3][d_4, 1, 3][s_4, 4, 1][d_4, 8, 1][d_4, 4, 1][d_4, 8, 3]" contenteditable>abc def <span id="s_4">hij opq</span> rst uvw</div>
+
+<div id="d_20" dir=rtl class="test_move_by_word" title="[d_20, 15, 3][d_20, 12, 3][d_20, 7, 3][d_20, 4, 3][s_20, 3, 1][s_20, 7, 1][s_20, 8, 1][s_20, 15, 1][d_20, 16, 1][d_20, 12, 1][d_20, 7, 1][d_20, 4, 1][d_20, 0, 1]|[d_20, 0, 1][d_20, 3, 1][d_20, 8, 1][d_20, 11, 1][d_20, 15, 1][s_20, 16, 1][s_20, 12, 1][s_20, 11, 1][s_20, 4, 1][d_20, 3, 3][d_20, 8, 3][d_20, 11, 3][d_20, 15, 3]" contenteditable>אבד opq rst דעפ <span dir=ltr id="s_20">abc uvw אאא def lmn</span>אבצ hij xyz וקק</div>
+
+</div>
+
+<pre id="console"></pre>
+</body>
+</html>
diff --git a/LayoutTests/editing/selection/move-left-right-by-word-mac-expected.txt b/LayoutTests/editing/selection/move-left-right-by-word-mac-expected.txt
deleted file mode 100644 (file)
index 9f7cfa0..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-Test 1, LTR:
-Move right by one word
-"abc def hij opq rst"[0, 3, 7, 11, 15, 19]
-Move left by one word
-"abc def hij opq rst"[19, 16, 12, 8, 4, 0]
-Test 2, RTL:
-Move right by one word
-"abc def hij opq rst"[0, 3, 7, 11, 15, 19]
-Move left by one word
-"abc def hij opq rst"[19, 16, 12, 8, 4, 0]
-Test 3, LTR:
-Move right by one word
-"ZZZ QQQ BBB CCC XXX"[0, 3, 7, 11, 15, 19]
-Move left by one word
-"ZZZ QQQ BBB CCC XXX"[19, 16, 12, 8, 4, 0]
-Test 4, RTL:
-Move right by one word
-"ZZZ QQQ BBB CCC XXX"[0, 3, 7, 11, 15, 19]
-Move left by one word
-"ZZZ QQQ BBB CCC XXX"[19, 16, 12, 8, 4, 0]
-Test 5, LTR:
-Move right by one word
-"abc def hij AAA BBB WWW opr uvw xyz"[0, 3, 7, 11, 15, 19, 23, 27, 31, 35]
-Move left by one word
-"abc def hij AAA BBB WWW opr uvw xyz"[35, 32, 28, 24, 20, 16, 12, 8, 4, 0]
-Test 6, RTL:
-Move right by one word
-"abc def hij AAA BBB WWW opr uvw xyz"[0, 3, 7, 11, 15, 19, 23, 27, 31, 35]
-Move left by one word
-"abc def hij AAA BBB WWW opr uvw xyz"[35, 32, 28, 24, 20, 16, 12, 8, 4, 0]
-Test 7, LTR:
-Move right by one word
-"abc def ZQB RIG uvw xyz"[0, 3, 7, 11, 15, 19, 23]
-Move left by one word
-"abc def ZQB RIG uvw xyz"[23, 20, 16, 12, 8, 4, 0]
-Test 8, RTL:
-Move right by one word
-"abc def ZQB RIG uvw xyz"[0, 3, 7, 11, 15, 19, 23]
-Move left by one word
-"abc def ZQB RIG uvw xyz"[23, 20, 16, 12, 8, 4, 0]
-Test 9, LTR:
-Move right by one word
-"aaa AAA bbb"[0, 3, 7, 11]
-Move left by one word
-"aaa AAA bbb"[11, 8, 4, 0]
-Test 10, RTL:
-Move right by one word
-"aaa AAA bbb"[0, 3, 7, 11]
-Move left by one word
-"aaa AAA bbb"[11, 8, 4, 0]
-Test 11, LTR:
-Move right by one word
-"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[0, 3, 7, 11, 15, 19, 23, 27, 31, 35]
-Move left by one word
-"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[35, 32, 28, 24, 20, 16, 12, 8, 4, 0]
-Test 12, RTL:
-Move right by one word
-"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[0, 3, 7, 11, 15, 19, 23, 27, 31, 35]
-Move left by one word
-"AAA BBB WWW aaa bbb ccc DDD SSS UUU"[35, 32, 28, 24, 20, 16, 12, 8, 4, 0]
-Test 13, LTR:
-Move right by one word
-"AAA BBB aaa bbb WWW DDD"[0, 3, 7, 11, 15, 19, 23]
-Move left by one word
-"AAA BBB aaa bbb WWW DDD"[23, 20, 16, 12, 8, 4, 0]
-Test 14, RTL:
-Move right by one word
-"AAA BBB aaa bbb WWW DDD"[0, 3, 7, 11, 15, 19, 23]
-Move left by one word
-"AAA BBB aaa bbb WWW DDD"[23, 20, 16, 12, 8, 4, 0]
-Test 15, LTR:
-Move right by one word
-"ZQB abc RIG"[0, 3, 7, 11]
-Move left by one word
-"ZQB abc RIG"[11, 8, 4, 0]
-Test 16, RTL:
-Move right by one word
-"ZQB abc RIG"[0, 3, 7, 11]
-Move left by one word
-"ZQB abc RIG"[11, 8, 4, 0]
-Test 17, LTR:
-Move right by one word
-"abc def    hij opq"[0, 3, 7, 14, 18]
-Move left by one word
-"abc def    hij opq"[18, 15, 8, 4, 0]
-
diff --git a/LayoutTests/editing/selection/move-left-right-by-word-mac.html b/LayoutTests/editing/selection/move-left-right-by-word-mac.html
deleted file mode 100644 (file)
index 16bfd60..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link rel="stylesheet" type="text/css" href="resources/extend-selection.css" />
-<style>
-test_move_by_word {display: none;}
-</style>
-<script src="resources/move-by-word-visually.js"></script>
-<script>
-
-onload = function() {
-    try {
-        var tests = document.getElementsByClassName("test_move_by_word");
-        var sel = getSelection();
-        for (var i = 0; i < tests.length; ++i) {
-            if (tests[i].getAttribute("dir") == 'ltr')
-                log("Test " + (i + 1) + ", LTR:\n");
-            else
-                log("Test " + (i + 1) + ", RTL:\n");
-            sel.setPosition(tests[i], 0);
-            moveByWord(sel, tests[i], "right");
-            moveByWord(sel, tests[i], "left");
-        }
-        if (document.getElementById("testMoveByWord"))
-            document.getElementById("testMoveByWord").style.display = "none";
-    } finally {
-        flushLog();
-    }
-};
-
-if (window.layoutTestController) {
-    layoutTestController.dumpAsText();
-    layoutTestController.setEditingBehavior('mac');
-}
-</script>
-</head>
-<body>
-<div id="testMoveByWord">
-<!-- 
-Title saves the word breaks.
-The format of title is "xxx|xxxx".
-
-The sequence on the left of "|" is word boundaries when moving caret from left to right.
-The sequence on the right of "|" is word boundaries when moving caret from right to left.
-
-If there is a single node in the line, the sequence are offsets.
-If there are multiple nodes in the line, the sequence is array of [anchor_node_id, offset, child_node_index], 
-where child_node_index is optional, default is the first child of the anchor node.
--->
-<!-- pure English -->
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19|19 16 12 8 4 0" contenteditable>abc def hij opq rst</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19|19 16 12 8 4 0" contenteditable>abc def hij opq rst</div>
-
-<!-- pure Hebrew -->
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19|19 16 12 8 4 0" contenteditable>ששש נננ בבב גגג קקק</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19|19 16 12 8 4 0" contenteditable>ששש נננ בבב גגג קקק</div>
-
-<!-- bidi text -->
-<!-- English Hebrew English -->
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19 23 27 31 35|35 32 28 24 20 16 12 8 4 0" contenteditable>abc def hij אאא בבב צצצ opr uvw xyz</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19 23 27 31 35|35 32 28 24 20 16 12 8 4 0" contenteditable>abc def hij אאא בבב צצצ opr uvw xyz</div>
-
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19 23|23 20 16 12 8 4 0" contenteditable>abc def שנב סטז uvw xyz</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19 23|23 20 16 12 8 4 0" contenteditable>abc def שנב סטז uvw xyz</div>
-
-<div dir=ltr class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>aaa אאא bbb</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>aaa אאא bbb</div>
-
-<!-- Hebrew English Hebrew -->
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19 23 27 31 35|35 32 28 24 20 16 12 8 4 0" contenteditable>אאא בבב צצצ aaa bbb ccc דדד עעע פפפ</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19 23 27 31 35|35 32 28 24 20 16 12 8 4 0" contenteditable>אאא בבב צצצ aaa bbb ccc דדד עעע פפפ</div>
-
-<div dir=ltr class="test_move_by_word" title="0 3 7 11 15 19 23|23 20 16 12 8 4 0" contenteditable>אאא בבב aaa bbb צצצ דדד</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11 15 19 23|23 20 16 12 8 4 0" contenteditable>אאא בבב aaa bbb צצצ דדד</div>
-
-<div dir=ltr class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>שנב abc סטז</div>
-<div dir=rtl class="test_move_by_word" title="0 3 7 11|11 8 4 0" contenteditable>שנב abc סטז</div>
-
-<div id="multispace" dir=ltr class="test_move_by_word" title="0 3 7 14 18|18 15 8 4 0" contenteditable>abc def    hij opq</div>
-
-</div>
-
-<pre id="console"></pre>
-</body>
-</html>
index 3d0b281..8821832 100644 (file)
@@ -1,3 +1,31 @@
+2012-05-01  Xiaomei Ji  <xji@chromium.org>
+
+        enable ctrl-arrow move by word visually in non-Windows platforms.
+        https://bugs.webkit.org/show_bug.cgi?id=85017
+
+        Reviewed by Ryosuke Niwa.
+
+        Enable ctrl-arrow moves caret by word in visual order in non-Windows platforms that use ICU word
+        break iterator (it is not enabled for WinCE and Qt where ICU is not used). For those platforms, ctrl-arrow
+        moves caret to word break position before spaces. For example, given a logical text "abc def hij", the word
+        break positions using ctrl-left-arrow from rightmost position are "|abc |def |hij".
+        The word break positions using ctrl-right-arrow from leftmost position are "abc| def| hij|".
+
+        Test: editing/selection/move-by-word-visually-mac.html
+
+        * editing/EditingBehavior.h:
+        (EditingBehavior):
+        (WebCore::EditingBehavior::shouldEatSpaceToNextWord): To control different word break positions
+        (regards to space) for different platforms.
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::modifyMovingRight): Enable visual word movement for all platforms that use ICU.
+        (WebCore::FrameSelection::modifyMovingLeft):
+        * editing/visible_units.cpp:
+        (WebCore::visualWordPosition): Determine the right word break position (regards to space) based on EditingBehavior.
+        (WebCore::leftWordPosition):
+        (WebCore::rightWordPosition):
+        * editing/visible_units.h:
+
 2012-05-01  Raymond Liu  <raymond.liu@intel.com>
 
         Modify RealtimeAnalyserNode pull mechanism
index 9ed1d77..bbf68f5 100644 (file)
@@ -60,10 +60,6 @@ public:
     // On Mac, when processing a contextual click, the object being clicked upon should be selected.
     bool shouldSelectOnContextualMenuClick() const { return m_type == EditingMacBehavior; }
     
-    // On Windows, moving caret left or right by word moves the caret by word in visual order. 
-    // It moves the caret by word in logical order in other platforms.
-    bool shouldMoveLeftRightByWordInVisualOrder() const { return m_type == EditingWindowsBehavior; }
-
     // On Mac and Windows, pressing backspace (when it isn't handled otherwise) should navigate back.
     bool shouldNavigateBackOnBackspace() const { return m_type != EditingUnixBehavior; }
 
@@ -72,6 +68,11 @@ public:
     // to the other end of the line/word (Unix/Windows behavior).
     bool shouldExtendSelectionByWordOrLineAcrossCaret() const { return m_type != EditingMacBehavior; }
 
+    // Based on native behavior, when using ctrl(alt)+arrow to move caret by word, ctrl(alt)+left arrow moves caret to
+    // immediately before the word in all platforms, for example, the word break positions are: "|abc |def |hij |opq".
+    // But ctrl+right arrow moves caret to "abc |def |hij |opq" on Windows and "abc| def| hij| opq|" on Mac and Linux.
+    bool shouldSkipSpaceWhenMovingRight() const { return m_type == EditingWindowsBehavior; }
+
 private:
     EditingBehaviorType m_type;
 };
index 1fa202f..1a7468e 100644 (file)
@@ -640,15 +640,15 @@ VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
         } else
             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
         break;
-    case WordGranularity:
-#if !OS(WINCE)
-        // Visual word movement relies on isWordTextBreak which is not implemented in WinCE.
-        if (visualWordMovementEnabled()
-            || (m_frame && m_frame->editor()->behavior().shouldMoveLeftRightByWordInVisualOrder())) {
-            pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
-            break;
-        }
+    case WordGranularity: {
+#if USE(ICU_UNICODE)
+        // Visual word movement relies on isWordTextBreak which is not implemented in WinCE and QT.
+        // https://bugs.webkit.org/show_bug.cgi?id=81136.
+        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor()->behavior().shouldSkipSpaceWhenMovingRight();
+        pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
+        break;
 #endif
+    }
     case SentenceGranularity:
     case LineGranularity:
     case ParagraphGranularity:
@@ -810,14 +810,13 @@ VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
         else
             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
         break;
-    case WordGranularity:
-#if !OS(WINCE)
-        if (visualWordMovementEnabled()
-            || (m_frame && m_frame->editor()->behavior().shouldMoveLeftRightByWordInVisualOrder())) {
-            pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
-            break;
-        }
+    case WordGranularity: {
+#if USE(ICU_UNICODE)
+        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor()->behavior().shouldSkipSpaceWhenMovingRight();
+        pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
+        break;
 #endif
+    }
     case SentenceGranularity:
     case LineGranularity:
     case ParagraphGranularity:
index 5eccb9b..f225d0b 100644 (file)
@@ -367,7 +367,8 @@ static bool islogicalEndOfWord(TextBreakIterator* iter, int position, bool hardL
 
 enum CursorMovementDirection { MoveLeft, MoveRight };
 
-static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition, CursorMovementDirection direction)
+static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition, CursorMovementDirection direction, 
+    bool skipsSpaceWhenMovingRight)
 {
     if (visiblePosition.isNull())
         return VisiblePosition();
@@ -418,7 +419,10 @@ static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition
         int offsetInIterator = offsetInBox - textBox->start() + previousBoxLength;
 
         bool isWordBreak;
-        if (box->direction() == blockDirection) {
+        bool boxHasSameDirectionalityAsBlock = box->direction() == blockDirection;
+        bool movingBackward = (direction == MoveLeft && box->direction() == LTR) || (direction == MoveRight && box->direction() == RTL);
+        if ((skipsSpaceWhenMovingRight && boxHasSameDirectionalityAsBlock)
+            || (!skipsSpaceWhenMovingRight && movingBackward)) {
             bool logicalStartInRenderer = offsetInBox == static_cast<int>(textBox->start()) && previousBoxInDifferentBlock;
             isWordBreak = isLogicalStartOfWord(iter, offsetInIterator, logicalStartInRenderer);
         } else {
@@ -434,9 +438,9 @@ static VisiblePosition visualWordPosition(const VisiblePosition& visiblePosition
     return VisiblePosition();
 }
 
-VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition)
+VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
 {
-    VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft);
+    VisiblePosition leftWordBreak = visualWordPosition(visiblePosition, MoveLeft, skipsSpaceWhenMovingRight);
     leftWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(leftWordBreak);
     
     // FIXME: How should we handle a non-editable position?
@@ -447,9 +451,9 @@ VisiblePosition leftWordPosition(const VisiblePosition& visiblePosition)
     return leftWordBreak;
 }
 
-VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition)
+VisiblePosition rightWordPosition(const VisiblePosition& visiblePosition, bool skipsSpaceWhenMovingRight)
 {
-    VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRight);
+    VisiblePosition rightWordBreak = visualWordPosition(visiblePosition, MoveRight, skipsSpaceWhenMovingRight);
     rightWordBreak = visiblePosition.honorEditingBoundaryAtOrBefore(rightWordBreak);
 
     // FIXME: How should we handle a non-editable position?
index 3ca4cda..c5c1eb6 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef visible_units_h
 #define visible_units_h
 
+#include "EditingBehaviorTypes.h"
 #include "EditingBoundary.h"
 #include "TextDirection.h"
 
@@ -41,8 +42,8 @@ VisiblePosition startOfWord(const VisiblePosition &, EWordSide = RightWordIfOnBo
 VisiblePosition endOfWord(const VisiblePosition &, EWordSide = RightWordIfOnBoundary);
 VisiblePosition previousWordPosition(const VisiblePosition &);
 VisiblePosition nextWordPosition(const VisiblePosition &);
-VisiblePosition rightWordPosition(const VisiblePosition&);
-VisiblePosition leftWordPosition(const VisiblePosition&);
+VisiblePosition rightWordPosition(const VisiblePosition&, bool skipsSpaceWhenMovingRight);
+VisiblePosition leftWordPosition(const VisiblePosition&, bool skipsSpaceWhenMovingRight);
 bool isStartOfWord(const VisiblePosition&);
 
 // sentences