+2008-04-27 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ - test for https://bugs.webkit.org/show_bug.cgi?id=3729
+ <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text
+
+ * editing/selection/move-left-right-expected.txt: Added.
+ * editing/selection/move-left-right.html: Added.
+ * platform/mac/editing/selection/move-left-right-expected.txt: Added.
+
2008-04-27 Sam Weinig <sam@webkit.org>
Reviewed by Maciej Stachowiak.
--- /dev/null
+Test 1, LTR:
+ Moving right: "\n abc\n "[9, 10, 11, 12]
+ Moving left: "\n abc\n "[12, 11, 10, 9]
+Test 1, RTL:
+ Moving left: "\n abc\n "[9, 11, 10, 12]
+ Moving right: "\n abc\n "[12, 10, 11, 9]
+Test 2, LTR:
+ Moving right: "\n ABC\n "[9, 11, 10, 12]
+ Moving left: "\n ABC\n "[12, 10, 11, 9]
+Test 2, RTL:
+ Moving left: "\n ABC\n "[9, 10, 11, 12]
+ Moving right: "\n ABC\n "[12, 11, 10, 9]
+Test 3, LTR:
+ Moving right: <DIV>[0], "abc\n "[0, 1, 2, 3]
+ Moving left: "abc\n "[3, 2, 1, 0], <DIV>[0]
+Test 3, RTL:
+ Moving left: <DIV>[0], "abc\n "[0, 2, 1, 3]
+ Moving right: "abc\n "[3, 1, 2, 0], <DIV>[0]
+Test 4, LTR:
+ Moving right: <DIV>[0], "ABC\n "[0, 2, 1, 3]
+ Moving left: "ABC\n "[3, 1, 2, 0], <DIV>[0]
+Test 4, RTL:
+ Moving left: <DIV>[0], "ABC\n "[0, 1, 2, 3]
+ Moving right: "ABC\n "[3, 2, 1, 0], <DIV>[0]
+Test 5, LTR:
+ Moving right: "\n abcABCdef\n "[9, 10, 11, 12, 14, 13, 15, 16, 17, 18]
+ Moving left: "\n abcABCdef\n "[18, 17, 16, 15, 13, 14, 12, 11, 10, 9]
+Test 5, RTL:
+ Moving left: "\n abcABCdef\n "[9, 11, 10, 12, 13, 14, 15, 17, 16, 18]
+ Moving right: "\n abcABCdef\n "[18, 16, 17, 15, 14, 13, 12, 10, 11, 9]
+Test 6, LTR:
+ Moving right: "\n ABCabcDEF\n "[9, 11, 10, 12, 13, 14, 15, 17, 16, 18]
+ Moving left: "\n ABCabcDEF\n "[18, 16, 17, 15, 14, 13, 12, 10, 11, 9]
+Test 6, RTL:
+ Moving left: "\n ABCabcDEF\n "[9, 10, 11, 12, 14, 13, 15, 16, 17, 18]
+ Moving right: "\n ABCabcDEF\n "[18, 17, 16, 15, 13, 14, 12, 11, 10, 9]
+Test 7, LTR:
+ Moving right: "\n abcABCDEF\n "[9, 10, 11, 12, 17, 16, 15, 14, 13, 18]
+ Moving left: "\n abcABCDEF\n "[18, 13, 14, 15, 16, 17, 12, 11, 10, 9]
+Test 7, RTL:
+ Moving left: "\n abcABCDEF\n "[9, 11, 10, 12, 13, 14, 15, 16, 17, 18]
+ Moving right: "\n abcABCDEF\n "[18, 17, 16, 15, 14, 13, 12, 10, 11, 9]
+Test 8, LTR:
+ Moving right: "\n ABCabcdef\n "[9, 11, 10, 12, 13, 14, 15, 16, 17, 18]
+ Moving left: "\n ABCabcdef\n "[18, 17, 16, 15, 14, 13, 12, 10, 11, 9]
+Test 8, RTL:
+ Moving left: "\n ABCabcdef\n "[9, 10, 11, 12, 17, 16, 15, 14, 13, 18]
+ Moving right: "\n ABCabcdef\n "[18, 13, 14, 15, 16, 17, 12, 11, 10, 9]
+Test 9, LTR:
+ Moving right: "abc"[0, 1, 2, 3], "ABCdef\n "[2, 1, 3, 4, 5, 6]
+ Moving left: "ABCdef\n "[6, 5, 4, 3, 1, 2], "abc"[3, 2, 1, 0]
+Test 9, RTL:
+ Moving left: "abc"[0, 2, 1, 3], "ABCdef\n "[1, 2, 3, 5, 4, 6]
+ Moving right: "ABCdef\n "[6, 4, 5, 3, 2, 1], "abc"[3, 1, 2, 0]
+Test 10, LTR:
+ Moving right: "ABC"[0, 2, 1, 3], "abcDEF\n "[1, 2, 3, 5, 4, 6]
+ Moving left: "abcDEF\n "[6, 4, 5, 3, 2, 1], "ABC"[3, 1, 2, 0]
+Test 10, RTL:
+ Moving left: "ABC"[0, 1, 2, 3], "abcDEF\n "[2, 1, 3, 4, 5, 6]
+ Moving right: "abcDEF\n "[6, 5, 4, 3, 1, 2], "ABC"[3, 2, 1, 0]
+Test 11, LTR:
+ Moving right: "abcABC123DEFdef\n "[0, 1, 2, 3, 11, 10, 6, 7, 8, 9, 5, 4, 12, 13, 14, 15]
+ Moving left: "abcABC123DEFdef\n "[15, 14, 13, 12, 4, 5, 9, 8, 7, 6, 10, 11, 3, 2, 1, 0]
+Test 11, RTL:
+ Moving left: "abcABC123DEFdef\n "[0, 2, 1, 3, 4, 5, 6, 8, 7, 9, 10, 11, 12, 14, 13, 15]
+ Moving right: "abcABC123DEFdef\n "[15, 13, 14, 12, 11, 10, 9, 7, 8, 6, 5, 4, 3, 1, 2, 0]
+Test 12, LTR:
+ Moving right: "abcABC123\n "[0, 1, 2, 3, 7, 8, 5, 4, 9]
+ Moving left: "abcABC123\n "[9, 4, 5, 8, 7, 3, 2, 1, 0]
+Test 12, RTL:
+ Moving left: "abcABC123\n "[0, 2, 1, 3, 4, 5, 6, 8, 7, 9]
+ Moving right: "abcABC123\n "[9, 7, 8, 6, 5, 4, 3, 1, 2, 0]
+Test 13, LTR:
+ Moving right: "abcABC123def\n "[0, 1, 2, 3, 7, 8, 5, 4, 9, 10, 11, 12]
+ Moving left: "abcABC123def\n "[12, 11, 10, 9, 4, 5, 8, 7, 6, 2, 1, 0]
+WARNING: Moving to the left did not visit the same positions in reverse order as moving to the right.
+Test 13, RTL:
+ Moving left: "abcABC123def\n "[0, 2, 1, 3, 4, 5, 6, 11, 10, 9, 8, 7, 12]
+ Moving right: "abcABC123def\n "[12, 7, 8, 9, 10, 11, 6, 5, 4, 3, 1, 2, 0]
+Test 14, LTR:
+ Moving right: "ABC123DEFabcGHI456JLM\n "[0, 8, 7, 3, 4, 5, 6, 2, 1, 9, 10, 11, 12, 20, 19, 15, 16, 17, 18, 14, 13, 21]
+ Moving left: "ABC123DEFabcGHI456JLM\n "[21, 13, 14, 18, 17, 16, 15, 19, 20, 12, 11, 10, 9, 1, 2, 6, 5, 4, 3, 7, 8, 0]
+Test 14, RTL:
+ Moving left: "ABC123DEFabcGHI456JLM\n "[0, 1, 2, 3, 5, 4, 6, 7, 8, 9, 11, 10, 12, 13, 14, 15, 17, 16, 18, 19, 20, 21]
+ Moving right: "ABC123DEFabcGHI456JLM\n "[21, 20, 19, 18, 16, 17, 15, 14, 13, 12, 10, 11, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0]
+Test 15, LTR:
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[9, 10, 11, 12, 13, 14, 15, 16, 22, 21, 20, 23, 24, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 35]
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[35, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 24, 23, 20, 21, 22, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 15, RTL:
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[9, 14, 13, 12, 11, 10, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 16, LTR:
+ Moving right: "\n MUQJ after encyclopedia\n "[9, 12, 11, 10, 13, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving left: "\n MUQJ after encyclopedia\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 14, 13, 10, 11, 12, 9]
+Test 16, RTL:
+ Moving left: "\n MUQJ after encyclopedia\n "[9, 10, 11, 12, 13, 14, 21, 20, 19, 18, 22, 23, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 35]
+ Moving right: "\n MUQJ after encyclopedia\n "[35, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 23, 22, 18, 19, 20, 21, 14, 13, 12, 11, 10, 9]
+Test 17, LTR:
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[9, 10, 11, 12, 13, 14, 15, 16, 22, 21, 20, 23, 24, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 35]
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[35, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 24, 23, 20, 21, 22, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 17, RTL:
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[9, 14, 13, 12, 11, 10, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 18, LTR:
+ Moving right: "\n MUQJ after encyclopedia\n "[9, 12, 11, 10, 13, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving left: "\n MUQJ after encyclopedia\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 14, 13, 10, 11, 12, 9]
+Test 18, RTL:
+ Moving left: "\n MUQJ after encyclopedia\n "[9, 10, 11, 12, 13, 14, 21, 20, 19, 18, 22, 23, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 35]
+ Moving right: "\n MUQJ after encyclopedia\n "[35, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 23, 22, 18, 19, 20, 21, 14, 13, 12, 11, 10, 9]
+Test 19, LTR:
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 19, 18, 21, 22, 28, 27, 26, 25, 24, 23, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 23, 24, 25, 26, 27, 28, 22, 21, 18, 19, 20, 17, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 19, RTL:
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 15, 14, 13, 12, 11, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 31, 33, 34, 38, 37, 36, 35, 39, 40]
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 35, 36, 37, 38, 34, 33, 31, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 10, 11, 12, 13, 14, 15, 9]
+Test 20, LTR:
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 19, 18, 21, 22, 28, 27, 26, 25, 24, 23, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 23, 24, 25, 26, 27, 28, 22, 21, 18, 19, 20, 17, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 20, RTL:
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 15, 14, 13, 12, 11, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 31, 33, 34, 38, 37, 36, 35, 39, 40]
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 35, 36, 37, 38, 34, 33, 31, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 10, 11, 12, 13, 14, 15, 9]
+Test 21, LTR:
+ Moving right: "\n Lorem\n "[9, 10, 11, 12, 13, 14], <DIV>[0], "\n ipsum\n "[9, 10, 11, 12, 13, 14]
+ Moving left: "\n ipsum\n "[14, 13, 12, 11, 10, 9], <DIV>[0], "\n Lorem\n "[14, 13, 12, 11, 10, 9]
+Test 21, RTL:
+ Moving left: "\n Lorem\n "[9, 13, 12, 11, 10, 14], <DIV>[0], "\n ipsum\n "[9, 13, 12, 11, 10, 14]
+ Moving right: "\n ipsum\n "[14, 10, 11, 12, 13, 9], <DIV>[0], "\n Lorem\n "[14, 10, 11, 12, 13, 9]
+Test 22, LTR:
+ Moving right: "\n WMH[\n "[9, 12, 11, 10, 13], <DIV>[0], "\n OWQU[\n "[9, 13, 12, 11, 10, 14]
+ Moving left: "\n OWQU[\n "[14, 10, 11, 12, 13, 9], <DIV>[0], "\n WMH[\n "[13, 10, 11, 12, 9]
+Test 22, RTL:
+ Moving left: "\n WMH[\n "[9, 10, 11, 12, 13], <DIV>[0], "\n OWQU[\n "[9, 10, 11, 12, 13, 14]
+ Moving right: "\n OWQU[\n "[14, 13, 12, 11, 10, 9], <DIV>[0], "\n WMH[\n "[13, 12, 11, 10, 9]
+Test 23, LTR:
+ Moving right: "\n abcdefABC"[9, 10, 11, 12, 13, 14, 15], "DEF\n "[2, 1], <DIV>[2], "\n abcdefABC"[18, 17, 16], "DEF\n "[3]
+ Moving left: "DEF\n "[3], "\n abcdefABC"[16, 17, 18], <DIV>[2], "DEF\n "[1, 2], "\n abcdefABC"[15, 14, 13, 12, 11, 10, 9]
+Test 23, RTL:
+ Moving left: "\n abcdefABC"[9, 14, 13, 12, 11, 10, 15, 16, 17, 18], <DIV>[2], "DEF\n "[1, 2, 3]
+ Moving right: "DEF\n "[3, 2, 1], <DIV>[2], "\n abcdefABC"[18, 17, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 24, LTR:
+ Moving right: "\n ABCDEFabc"[9, 14, 13, 12, 11, 10, 15, 16, 17, 18], <DIV>[2], "def\n "[1, 2, 3]
+ Moving left: "def\n "[3, 2, 1], <DIV>[2], "\n ABCDEFabc"[18, 17, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 24, RTL:
+ Moving left: "\n ABCDEFabc"[9, 10, 11, 12, 13, 14, 15], "def\n "[2, 1], <DIV>[2], "\n ABCDEFabc"[18, 17, 16], "def\n "[3]
+ Moving right: "def\n "[3], "\n ABCDEFabc"[16, 17, 18], <DIV>[2], "def\n "[1, 2], "\n ABCDEFabc"[15, 14, 13, 12, 11, 10, 9]
+Test 25, LTR:
+ Moving right: "\n abc"[9, 10, 11, 12], <DIV>[2], "DEFghi\n "[2, 1], <DIV>[5, 4], "ABC"[3, 2, 1], "DEFghi\n "[3, 4, 5, 6]
+ Moving left: "DEFghi\n "[6, 5, 4, 3], "ABC"[1, 2, 3], <DIV>[4, 5], "DEFghi\n "[1, 2], <DIV>[2], "\n abc"[12, 11, 10, 9]
+Test 25, RTL:
+ Moving left: "\n abc"[9, 11, 10, 12], <DIV>[2], "ABC"[1, 2, 3], <DIV>[4, 5], "DEFghi\n "[1, 2, 3, 5, 4, 6]
+ Moving right: "DEFghi\n "[6, 4, 5, 3, 2, 1], <DIV>[5, 4], "ABC"[3, 2, 1], <DIV>[2], "\n abc"[12, 10, 11, 9]
+Test 26, LTR:
+ Moving right: "\n ABC"[9, 11, 10, 12], <DIV>[2], "abc"[1, 2, 3], <DIV>[4, 5], "defDEF\n "[1, 2, 3, 5, 4, 6]
+ Moving left: "defDEF\n "[6, 4, 5, 3, 2, 1], <DIV>[5, 4], "abc"[3, 2, 1], <DIV>[2], "\n ABC"[12, 10, 11, 9]
+Test 26, RTL:
+ Moving left: "\n ABC"[9, 10, 11, 12], <DIV>[2], "defDEF\n "[2, 1], <DIV>[5, 4], "abc"[3, 2, 1], "defDEF\n "[3, 4, 5, 6]
+ Moving right: "defDEF\n "[6, 5, 4, 3], "abc"[1, 2, 3], <DIV>[4, 5], "defDEF\n "[1, 2], <DIV>[2], "\n ABC"[12, 11, 10, 9]
+Test 27, LTR:
+ Moving right: "\n abcABC"[9, 10, 11, 12], "DEF"[2, 1], "\n abcABC"[15, 14, 13], "DEF"[3]
+ Moving left: "DEF"[3], "\n abcABC"[13, 14, 15], "DEF"[1, 2], "\n abcABC"[12, 11, 10, 9]
+Test 27, RTL:
+ Moving left: "\n abcABC"[9, 11, 10, 12, 13, 14, 15], "DEF"[1, 2, 3]
+ Moving right: "DEF"[3, 2, 1], "\n abcABC"[15, 14, 13, 12, 10, 11, 9]
+Test 28, LTR:
+ Moving right: "\n ABCabc"[9, 11, 10, 12, 13, 14, 15], "def"[1, 2, 3]
+ Moving left: "def"[3, 2, 1], "\n ABCabc"[15, 14, 13, 12, 10, 11, 9]
+Test 28, RTL:
+ Moving left: "\n ABCabc"[9, 10, 11, 12], "def"[2, 1], "\n ABCabc"[15, 14, 13], "def"[3]
+ Moving right: "def"[3], "\n ABCabc"[13, 14, 15], "def"[1, 2], "\n ABCabc"[12, 11, 10, 9]
+Test 29, LTR:
+ Moving right: "\n ab"[9, 10, 11], "cABCdef"[1, 3, 2, 4, 5, 6, 7]
+ Moving left: "cABCdef"[7, 6, 5, 4, 2, 3, 1], "\n ab"[11, 10, 9]
+Test 29, RTL:
+ Moving left: "\n ab"[9, 11, 10], "cABCdef"[1, 2, 3, 4, 6, 5, 7]
+ Moving right: "cABCdef"[7, 5, 6, 4, 3, 2, 1], "\n ab"[10, 11, 9]
+Test 30, LTR:
+ Moving right: "\n AB"[9, 11, 10], "CabcDEF"[1, 2, 3, 4, 6, 5, 7]
+ Moving left: "CabcDEF"[7, 5, 6, 4, 3, 2, 1], "\n AB"[10, 11, 9]
+Test 30, RTL:
+ Moving left: "\n AB"[9, 10, 11], "CabcDEF"[1, 3, 2, 4, 5, 6, 7]
+ Moving right: "CabcDEF"[7, 6, 5, 4, 2, 3, 1], "\n AB"[11, 10, 9]
+Test 31, LTR:
+ Moving right: "\n abc"[9, 10, 11, 12], "ABCdef"[2, 1, 3, 4, 5, 6]
+ Moving left: "ABCdef"[6, 5, 4, 3, 1, 2], "\n abc"[12, 11, 10, 9]
+Test 31, RTL:
+ Moving left: "\n abc"[9, 11, 10, 12], "ABCdef"[1, 2, 3, 5, 4, 6]
+ Moving right: "ABCdef"[6, 4, 5, 3, 2, 1], "\n abc"[12, 10, 11, 9]
+Test 32, LTR:
+ Moving right: "\n ABC"[9, 11, 10, 12], "abcDEF"[1, 2, 3, 5, 4, 6]
+ Moving left: "abcDEF"[6, 4, 5, 3, 2, 1], "\n ABC"[12, 10, 11, 9]
+Test 32, RTL:
+ Moving left: "\n ABC"[9, 10, 11, 12], "abcDEF"[2, 1, 3, 4, 5, 6]
+ Moving right: "abcDEF"[6, 5, 4, 3, 1, 2], "\n ABC"[12, 11, 10, 9]
+Test 33, LTR:
+ Moving right: "\n abcAdef\n "[9, 10, 11, 12, 13, 14, 15, 16]
+ Moving left: "\n abcAdef\n "[16, 15, 14, 13, 12, 11, 10, 9]
+Test 33, RTL:
+ Moving left: "\n abcAdef\n "[9, 11, 10, 12, 13, 15, 14, 16]
+ Moving right: "\n abcAdef\n "[16, 14, 15, 13, 12, 10, 11, 9]
+Test 34, LTR:
+ Moving right: "\n ABCaDEF\n "[9, 11, 10, 12, 13, 15, 14, 16]
+ Moving left: "\n ABCaDEF\n "[16, 14, 15, 13, 12, 10, 11, 9]
+Test 34, RTL:
+ Moving left: "\n ABCaDEF\n "[9, 10, 11, 12, 13, 14, 15, 16]
+ Moving right: "\n ABCaDEF\n "[16, 15, 14, 13, 12, 11, 10, 9]
+Test 35, LTR:
+ Moving right: "\n abcABC"[9, 10, 11, 12, 14, 13, 15], "def"[1, 2, 3]
+ Moving left: "def"[3, 2, 1], "\n abcABC"[15, 13, 14, 12, 11, 10, 9]
+Test 35, RTL:
+ Moving left: "\n abcABC"[9, 11, 10, 12, 13, 14, 15], "def"[2, 1, 3]
+ Moving right: "def"[3, 1, 2], "\n abcABC"[15, 14, 13, 12, 10, 11, 9]
+Test 36, LTR:
+ Moving right: "\n ABCabc"[9, 11, 10, 12, 13, 14, 15], "DEF"[2, 1, 3]
+ Moving left: "DEF"[3, 1, 2], "\n ABCabc"[15, 14, 13, 12, 10, 11, 9]
+Test 36, RTL:
+ Moving left: "\n ABCabc"[9, 10, 11, 12, 14, 13, 15], "DEF"[1, 2, 3]
+ Moving right: "DEF"[3, 2, 1], "\n ABCabc"[15, 13, 14, 12, 11, 10, 9]
+Test 37, LTR:
+ Moving right: "\n abcA"[9, 10, 11, 12], "BCdef"[1], "\n abcA"[13], "BCdef"[2, 3, 4, 5]
+ Moving left: "BCdef"[5, 4, 3, 2], "\n abcA"[13], "BCdef"[1], "\n abcA"[12, 11, 10, 9]
+Test 37, RTL:
+ Moving left: "\n abcA"[9, 11, 10, 12, 13], "BCdef"[1, 2, 4, 3, 5]
+ Moving right: "BCdef"[5, 3, 4, 2, 1], "\n abcA"[13, 12, 10, 11, 9]
+Test 38, LTR:
+ Moving right: "\n ABCa"[9, 11, 10, 12, 13], "bcDEF"[1, 2, 4, 3, 5]
+ Moving left: "bcDEF"[5, 3, 4, 2, 1], "\n ABCa"[13, 12, 10, 11, 9]
+Test 38, RTL:
+ Moving left: "\n ABCa"[9, 10, 11, 12], "bcDEF"[1], "\n ABCa"[13], "bcDEF"[2, 3, 4, 5]
+ Moving right: "bcDEF"[5, 4, 3, 2], "\n ABCa"[13], "bcDEF"[1], "\n ABCa"[12, 11, 10, 9]
+
--- /dev/null
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style>
+ div.test {
+ -webkit-user-modify: read-write;
+ padding: 4px;
+ border: 1px dashed lightblue;
+ margin: 4px 4px 4px 24px;
+ outline: none;
+ font-family: Lucida Grande;
+ counter-increment: test-number;
+ }
+ div.test:before { content: counter(test-number); position: absolute; left: 8px; font-size: x-small; text-align: right; width: 20px; }
+ div.test span { background-color: #def; }
+ div.test img { width: 1em; height: 1em; background-color: lightgreen; }
+ div.test img + img { background-color: lightblue; }
+ div.test div { border: 1px dashed pink; padding: 3px; height: 2em; }
+ </style>
+ <script>
+ function log(message)
+ {
+ document.getElementById("console").appendChild(document.createTextNode(message));
+ }
+
+ function caretCoordinates()
+ {
+ if (!window.textInputController)
+ return { x: 0, y :0 };
+ var caretRect = textInputController.firstRectForCharacterRange(textInputController.selectedRange()[0], 0);
+ return { x: caretRect[0], y: caretRect[1] };
+ }
+
+ function positionsMovingInDirection(sel, direction)
+ {
+ var positions = [];
+ while (true) {
+ positions.push({ node: sel.anchorNode, offset: sel.anchorOffset, point: caretCoordinates() });
+ sel.modify("move", direction, "character");
+ if (positions[positions.length - 1].node == sel.anchorNode && positions[positions.length - 1].offset == sel.anchorOffset)
+ break;
+ };
+ return positions;
+ }
+
+ function fold(string)
+ {
+ var result = "";
+ for (var i = 0; i < string.length; ++i) {
+ var char = string.charCodeAt(i);
+ if (char >= 0x05d0)
+ char -= 0x058f;
+ else if (char == 10) {
+ result += "\\n";
+ continue;
+ }
+ result += String.fromCharCode(char);
+ }
+ return result;
+ }
+
+ function logPositions(positions)
+ {
+ for (var i = 0; i < positions.length; ++i) {
+ if (i) {
+ if (positions[i].node != positions[i - 1].node)
+ log("]");
+ log(", ");
+ }
+ if (!i || positions[i].node != positions[i - 1].node)
+ log((positions[i].node instanceof Text ? '"' + fold(positions[i].node.data) + '"' : "<" + positions[i].node.tagName + ">") + "[");
+ log(positions[i].offset);
+ }
+ log("]");
+ }
+
+ function checkReverseOrder(positions, reversePositions)
+ {
+ var mismatch = positions.length != reversePositions.length;
+ while (!mismatch) {
+ var pos = positions.pop();
+ if (!pos)
+ break;
+ var reversePos = reversePositions.shift();
+ if (pos.node != reversePos.node || pos.offset != reversePos.offset)
+ mismatch = true;
+ }
+
+ if (mismatch)
+ log("WARNING: Moving to the left did not visit the same positions in reverse order as moving to the right.\n");
+ }
+
+ function checkCoordinatesMovingRightDown(positions)
+ {
+ for (var i = 1; i < positions.length; ++i) {
+ if (positions[i].point.y > positions[i - 1].point.y || positions[i].point.x < positions[i - 1].point.x && positions[i].point.y >= positions[i - 1].point.y)
+ log("WARNING: Moved in the wrong direction in step " + i + ": from (" + positions[i - 1].point.x + ", " + positions[i - 1].point.y + ") to (" + positions[i].point.x + ", " + positions[i].point.y + ").\n");
+ }
+ }
+
+ function checkCoordinatesMovingLeftDown(positions)
+ {
+ for (var i = 1; i < positions.length; ++i) {
+ if (positions[i].point.y > positions[i - 1].point.y || positions[i].point.x > positions[i - 1].point.x && positions[i].point.y >= positions[i - 1].point.y)
+ log("WARNING: Moved in the wrong direction in step " + i + ": from (" + positions[i - 1].point.x + ", " + positions[i - 1].point.y + ") to (" + positions[i].point.x + ", " + positions[i].point.y + ").\n");
+ }
+ }
+
+ function checkCoordinatesMovingRightUp(positions)
+ {
+ for (var i = 1; i < positions.length; ++i) {
+ if (positions[i].point.y < positions[i - 1].point.y || positions[i].point.x < positions[i - 1].point.x && positions[i].point.y <= positions[i - 1].point.y)
+ log("WARNING: Moved in the wrong direction in step " + i + ": from (" + positions[i - 1].point.x + ", " + positions[i - 1].point.y + ") to (" + positions[i].point.x + ", " + positions[i].point.y + ").\n");
+ }
+ }
+
+ function checkCoordinatesMovingLeftUp(positions)
+ {
+ for (var i = 1; i < positions.length; ++i) {
+ if (positions[i].point.y < positions[i - 1].point.y || positions[i].point.x > positions[i - 1].point.x && positions[i].point.y <= positions[i - 1].point.y)
+ log("WARNING: Moved in the wrong direction in step " + i + ": from (" + positions[i - 1].point.x + ", " + positions[i - 1].point.y + ") to (" + positions[i].point.x + ", " + positions[i].point.y + ").\n");
+ }
+ }
+
+ onload = function()
+ {
+ if (!window.layoutTestController)
+ return;
+
+ layoutTestController.dumpAsText();
+
+ var tests = document.getElementsByClassName("test");
+ var sel = getSelection();
+ for (var i = 0; i < tests.length; ++i) {
+ var positionsMovingRight;
+ var positionsMovingLeft;
+
+ log("Test " + (i + 1) + ", LTR:\n Moving right: ");
+ sel.setPosition(tests[i], 0);
+ positionsMovingRight = positionsMovingInDirection(sel, "right");
+ logPositions(positionsMovingRight);
+ log("\n");
+ checkCoordinatesMovingRightDown(positionsMovingRight);
+
+ log(" Moving left: ");
+ positionsMovingLeft = positionsMovingInDirection(sel, "left");
+ logPositions(positionsMovingLeft);
+ log("\n");
+ checkCoordinatesMovingLeftUp(positionsMovingLeft);
+
+ checkReverseOrder(positionsMovingLeft, positionsMovingRight);
+
+ tests[i].style.direction = "rtl";
+
+ log("Test " + (i + 1) + ", RTL:\n Moving left: ");
+ sel.setPosition(tests[i], 0);
+ positionsMovingLeft = positionsMovingInDirection(sel, "left");
+ logPositions(positionsMovingLeft);
+ log("\n");
+ checkCoordinatesMovingLeftDown(positionsMovingLeft);
+
+ log(" Moving right: ");
+ positionsMovingRight = positionsMovingInDirection(sel, "right");
+ logPositions(positionsMovingRight);
+ log("\n");
+ checkCoordinatesMovingRightUp(positionsMovingRight);
+
+ checkReverseOrder(positionsMovingLeft, positionsMovingRight);
+
+ tests[i].style.display = "none";
+ }
+ }
+
+ </script>
+</head>
+<body>
+ <div class="test">
+ abc
+ </div>
+
+ <div class="test">
+ אבג
+ </div>
+
+ <div class="test"><br>abc
+ </div>
+
+ <div class="test"><br>אבג
+ </div>
+
+ <div class="test">
+ abcאבגdef
+ </div>
+
+ <div class="test">
+ אבגabcדהו
+ </div>
+
+ <div class="test">
+ abcאבגדהו
+ </div>
+
+ <div class="test">
+ אבגabcdef
+ </div>
+
+ <div class="test">
+ <span>abc</span>אבגdef
+ </div>
+
+ <div class="test">
+ <span>אבג</span>abcדהו
+ </div>
+
+ <div class="test">abcאבג123דהוdef
+ </div>
+
+ <div class="test">abcאבג123
+ </div>
+
+ <div class="test">abcאבג123def
+ </div>
+
+ <div class="test">אבג123דהוabcזחט456יכל
+ </div>
+
+ <div class="test" style="width: 120px;">
+ before אחרי אנציקלופדיה
+ </div>
+
+ <div class="test" style="width: 120px;">
+ לפני after encyclopedia
+ </div>
+
+ <div class="test" contenteditable style="width: 120px;">
+ before אחרי אנציקלופדיה
+ </div>
+
+ <div class="test" contenteditable style="width: 120px;">
+ לפני after encyclopedia
+ </div>
+
+ <div class="test" style="width: 100px;">
+ This is יותר צר מיתר the boxes.
+ </div>
+
+ <div contenteditable class="test" style="width: 100px;">
+ This is יותר צר מיתר the boxes.
+ </div>
+
+ <div class="test">
+ Lorem
+ <div></div>
+ ipsum
+ </div>
+
+ <div class="test">
+ צלחת
+ <div></div>
+ מצנפת
+ </div>
+
+ <div class="test">
+ abcdefאבג<img>דהו
+ </div>
+
+ <div class="test">
+ אבגדהוabc<img>def
+ </div>
+
+ <div class="test">
+ abc<input>אבג<img><img>דהוghi
+ </div>
+
+ <div class="test">
+ אבג<input>abc<img><img>defדהו
+ </div>
+
+ <div class="test">
+ abcאבג<span>דהו</span>
+ </div>
+
+ <div class="test">
+ אבגabc<span>def</span>
+ </div>
+
+ <div class="test">
+ ab<span>cאבגdef</span>
+ </div>
+
+ <div class="test">
+ אב<span>גabcדהו</span>
+ </div>
+
+ <div class="test">
+ abc<span>אבגdef</span>
+ </div>
+
+ <div class="test">
+ אבג<span>abcדהו</span>
+ </div>
+
+ <div class="test">
+ abcאdef
+ </div>
+
+ <div class="test">
+ אבגaדהו
+ </div>
+
+ <div class="test">
+ abcאבג<span>def</span>
+ </div>
+
+ <div class="test">
+ אבגabc<span>דהו</span>
+ </div>
+
+ <div class="test">
+ abcא<span>בגdef</span>
+ </div>
+
+ <div class="test">
+ אבגa<span>bcדהו</span>
+ </div>
+
+ <pre id="console"></pre>
+</body>
--- /dev/null
+Test 1, LTR:
+ Moving right: "\n abc\n "[9, 10, 11, 12]
+ Moving left: "\n abc\n "[12, 11, 10, 9]
+Test 1, RTL:
+ Moving left: "\n abc\n "[9, 11, 10, 12]
+ Moving right: "\n abc\n "[12, 10, 11, 9]
+Test 2, LTR:
+ Moving right: "\n ABC\n "[9, 11, 10, 12]
+ Moving left: "\n ABC\n "[12, 10, 11, 9]
+Test 2, RTL:
+ Moving left: "\n ABC\n "[9, 10, 11, 12]
+ Moving right: "\n ABC\n "[12, 11, 10, 9]
+Test 3, LTR:
+ Moving right: <DIV>[0], "abc\n "[0, 1, 2, 3]
+ Moving left: "abc\n "[3, 2, 1, 0], <DIV>[0]
+Test 3, RTL:
+ Moving left: <DIV>[0], "abc\n "[0, 2, 1, 3]
+ Moving right: "abc\n "[3, 1, 2, 0], <DIV>[0]
+Test 4, LTR:
+ Moving right: <DIV>[0], "ABC\n "[0, 2, 1, 3]
+ Moving left: "ABC\n "[3, 1, 2, 0], <DIV>[0]
+Test 4, RTL:
+ Moving left: <DIV>[0], "ABC\n "[0, 1, 2, 3]
+ Moving right: "ABC\n "[3, 2, 1, 0], <DIV>[0]
+Test 5, LTR:
+ Moving right: "\n abcABCdef\n "[9, 10, 11, 12, 14, 13, 15, 16, 17, 18]
+ Moving left: "\n abcABCdef\n "[18, 17, 16, 15, 13, 14, 12, 11, 10, 9]
+Test 5, RTL:
+ Moving left: "\n abcABCdef\n "[9, 11, 10, 12, 13, 14, 15, 17, 16, 18]
+ Moving right: "\n abcABCdef\n "[18, 16, 17, 15, 14, 13, 12, 10, 11, 9]
+Test 6, LTR:
+ Moving right: "\n ABCabcDEF\n "[9, 11, 10, 12, 13, 14, 15, 17, 16, 18]
+ Moving left: "\n ABCabcDEF\n "[18, 16, 17, 15, 14, 13, 12, 10, 11, 9]
+Test 6, RTL:
+ Moving left: "\n ABCabcDEF\n "[9, 10, 11, 12, 14, 13, 15, 16, 17, 18]
+ Moving right: "\n ABCabcDEF\n "[18, 17, 16, 15, 13, 14, 12, 11, 10, 9]
+Test 7, LTR:
+ Moving right: "\n abcABCDEF\n "[9, 10, 11, 12, 17, 16, 15, 14, 13, 18]
+ Moving left: "\n abcABCDEF\n "[18, 13, 14, 15, 16, 17, 12, 11, 10, 9]
+Test 7, RTL:
+ Moving left: "\n abcABCDEF\n "[9, 11, 10, 12, 13, 14, 15, 16, 17, 18]
+ Moving right: "\n abcABCDEF\n "[18, 17, 16, 15, 14, 13, 12, 10, 11, 9]
+Test 8, LTR:
+ Moving right: "\n ABCabcdef\n "[9, 11, 10, 12, 13, 14, 15, 16, 17, 18]
+ Moving left: "\n ABCabcdef\n "[18, 17, 16, 15, 14, 13, 12, 10, 11, 9]
+Test 8, RTL:
+ Moving left: "\n ABCabcdef\n "[9, 10, 11, 12, 17, 16, 15, 14, 13, 18]
+ Moving right: "\n ABCabcdef\n "[18, 13, 14, 15, 16, 17, 12, 11, 10, 9]
+Test 9, LTR:
+ Moving right: "abc"[0, 1, 2, 3], "ABCdef\n "[2, 1, 3, 4, 5, 6]
+ Moving left: "ABCdef\n "[6, 5, 4, 3, 1, 2], "abc"[3, 2, 1, 0]
+Test 9, RTL:
+ Moving left: "abc"[0, 2, 1, 3], "ABCdef\n "[1, 2, 3, 5, 4, 6]
+ Moving right: "ABCdef\n "[6, 4, 5, 3, 2, 1], "abc"[3, 1, 2, 0]
+Test 10, LTR:
+ Moving right: "ABC"[0, 2, 1, 3], "abcDEF\n "[1, 2, 3, 5, 4, 6]
+ Moving left: "abcDEF\n "[6, 4, 5, 3, 2, 1], "ABC"[3, 1, 2, 0]
+Test 10, RTL:
+ Moving left: "ABC"[0, 1, 2, 3], "abcDEF\n "[2, 1, 3, 4, 5, 6]
+ Moving right: "abcDEF\n "[6, 5, 4, 3, 1, 2], "ABC"[3, 2, 1, 0]
+Test 11, LTR:
+ Moving right: "abcABC123DEFdef\n "[0, 1, 2, 3, 11, 10, 6, 7, 8, 9, 5, 4, 12, 13, 14, 15]
+ Moving left: "abcABC123DEFdef\n "[15, 14, 13, 12, 4, 5, 9, 8, 7, 6, 10, 11, 3, 2, 1, 0]
+Test 11, RTL:
+ Moving left: "abcABC123DEFdef\n "[0, 2, 1, 3, 4, 5, 6, 8, 7, 9, 10, 11, 12, 14, 13, 15]
+ Moving right: "abcABC123DEFdef\n "[15, 13, 14, 12, 11, 10, 9, 7, 8, 6, 5, 4, 3, 1, 2, 0]
+Test 12, LTR:
+ Moving right: "abcABC123\n "[0, 1, 2, 3, 7, 8, 5, 4, 9]
+ Moving left: "abcABC123\n "[9, 4, 5, 8, 7, 3, 2, 1, 0]
+Test 12, RTL:
+ Moving left: "abcABC123\n "[0, 2, 1, 3, 4, 5, 6, 8, 7, 9]
+ Moving right: "abcABC123\n "[9, 7, 8, 6, 5, 4, 3, 1, 2, 0]
+Test 13, LTR:
+ Moving right: "abcABC123def\n "[0, 1, 2, 3, 7, 8, 5, 4, 9, 10, 11, 12]
+ Moving left: "abcABC123def\n "[12, 11, 10, 9, 4, 5, 8, 7, 6, 2, 1, 0]
+WARNING: Moving to the left did not visit the same positions in reverse order as moving to the right.
+Test 13, RTL:
+ Moving left: "abcABC123def\n "[0, 2, 1, 3, 4, 5, 6, 11, 10, 9, 8, 7, 12]
+ Moving right: "abcABC123def\n "[12, 7, 8, 9, 10, 11, 6, 5, 4, 3, 1, 2, 0]
+Test 14, LTR:
+ Moving right: "ABC123DEFabcGHI456JLM\n "[0, 8, 7, 3, 4, 5, 6, 2, 1, 9, 10, 11, 12, 20, 19, 15, 16, 17, 18, 14, 13, 21]
+ Moving left: "ABC123DEFabcGHI456JLM\n "[21, 13, 14, 18, 17, 16, 15, 19, 20, 12, 11, 10, 9, 1, 2, 6, 5, 4, 3, 7, 8, 0]
+Test 14, RTL:
+ Moving left: "ABC123DEFabcGHI456JLM\n "[0, 1, 2, 3, 5, 4, 6, 7, 8, 9, 11, 10, 12, 13, 14, 15, 17, 16, 18, 19, 20, 21]
+ Moving right: "ABC123DEFabcGHI456JLM\n "[21, 20, 19, 18, 16, 17, 15, 14, 13, 12, 10, 11, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0]
+Test 15, LTR:
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[9, 10, 11, 12, 13, 14, 15, 16, 22, 21, 20, 23, 24, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 35]
+WARNING: Moved in the wrong direction in step 13: from (117, 551) to (49, 551).
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[35, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 24, 23, 20, 21, 22, 16, 15, 14, 13, 12, 11, 10, 9]
+WARNING: Moved in the wrong direction in step 11: from (49, 551) to (117, 551).
+Test 15, RTL:
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[9, 14, 13, 12, 11, 10, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 16, LTR:
+ Moving right: "\n MUQJ after encyclopedia\n "[9, 12, 11, 10, 13, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving left: "\n MUQJ after encyclopedia\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 14, 13, 10, 11, 12, 9]
+Test 16, RTL:
+ Moving left: "\n MUQJ after encyclopedia\n "[9, 10, 11, 12, 13, 14, 21, 20, 19, 18, 22, 23, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 35]
+WARNING: Moved in the wrong direction in step 12: from (65, 551) to (148, 551).
+ Moving right: "\n MUQJ after encyclopedia\n "[35, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 23, 22, 18, 19, 20, 21, 14, 13, 12, 11, 10, 9]
+WARNING: Moved in the wrong direction in step 12: from (148, 551) to (65, 551).
+Test 17, LTR:
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[9, 10, 11, 12, 13, 14, 15, 16, 22, 21, 20, 23, 24, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 35]
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[35, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 24, 23, 20, 21, 22, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 17, RTL:
+ Moving left: "\n before AHYJ AQWJXMFUDJE\n "[9, 14, 13, 12, 11, 10, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving right: "\n before AHYJ AQWJXMFUDJE\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 18, LTR:
+ Moving right: "\n MUQJ after encyclopedia\n "[9, 12, 11, 10, 13, 14, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
+ Moving left: "\n MUQJ after encyclopedia\n "[35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 14, 13, 10, 11, 12, 9]
+Test 18, RTL:
+ Moving left: "\n MUQJ after encyclopedia\n "[9, 10, 11, 12, 13, 14, 21, 20, 19, 18, 22, 23, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 35]
+ Moving right: "\n MUQJ after encyclopedia\n "[35, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 23, 22, 18, 19, 20, 21, 14, 13, 12, 11, 10, 9]
+Test 19, LTR:
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 19, 18, 21, 22, 28, 27, 26, 25, 24, 23, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
+WARNING: Moved in the wrong direction in step 14: from (87, 551) to (46, 551).
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 23, 24, 25, 26, 27, 28, 22, 21, 18, 19, 20, 17, 16, 15, 14, 13, 12, 11, 10, 9]
+WARNING: Moved in the wrong direction in step 18: from (46, 551) to (87, 551).
+Test 19, RTL:
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 15, 14, 13, 12, 11, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 31, 33, 34, 38, 37, 36, 35, 39, 40]
+WARNING: Moved in the wrong direction in step 26: from (100, 533) to (129, 533).
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 35, 36, 37, 38, 34, 33, 31, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 10, 11, 12, 13, 14, 15, 9]
+WARNING: Moved in the wrong direction in step 6: from (129, 533) to (100, 533).
+Test 20, LTR:
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 19, 18, 21, 22, 28, 27, 26, 25, 24, 23, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40]
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 23, 24, 25, 26, 27, 28, 22, 21, 18, 19, 20, 17, 16, 15, 14, 13, 12, 11, 10, 9]
+Test 20, RTL:
+ Moving left: "\n This is JF[Y WY OJ[Y the boxes. \n "[9, 15, 14, 13, 12, 11, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 31, 33, 34, 38, 37, 36, 35, 39, 40]
+ Moving right: "\n This is JF[Y WY OJ[Y the boxes. \n "[40, 39, 35, 36, 37, 38, 34, 33, 31, 32, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 10, 11, 12, 13, 14, 15, 9]
+Test 21, LTR:
+ Moving right: "\n Lorem\n "[9, 10, 11, 12, 13, 14], <DIV>[0], "\n ipsum\n "[9, 10, 11, 12, 13, 14]
+ Moving left: "\n ipsum\n "[14, 13, 12, 11, 10, 9], <DIV>[0], "\n Lorem\n "[14, 13, 12, 11, 10, 9]
+Test 21, RTL:
+ Moving left: "\n Lorem\n "[9, 13, 12, 11, 10, 14], <DIV>[0], "\n ipsum\n "[9, 13, 12, 11, 10, 14]
+ Moving right: "\n ipsum\n "[14, 10, 11, 12, 13, 9], <DIV>[0], "\n Lorem\n "[14, 10, 11, 12, 13, 9]
+Test 22, LTR:
+ Moving right: "\n WMH[\n "[9, 12, 11, 10, 13], <DIV>[0], "\n OWQU[\n "[9, 13, 12, 11, 10, 14]
+ Moving left: "\n OWQU[\n "[14, 10, 11, 12, 13, 9], <DIV>[0], "\n WMH[\n "[13, 10, 11, 12, 9]
+Test 22, RTL:
+ Moving left: "\n WMH[\n "[9, 10, 11, 12, 13], <DIV>[0], "\n OWQU[\n "[9, 10, 11, 12, 13, 14]
+ Moving right: "\n OWQU[\n "[14, 13, 12, 11, 10, 9], <DIV>[0], "\n WMH[\n "[13, 12, 11, 10, 9]
+Test 23, LTR:
+ Moving right: "\n abcdefABC"[9, 10, 11, 12, 13, 14, 15], "DEF\n "[2, 1], <DIV>[2], "\n abcdefABC"[18, 17, 16], "DEF\n "[3]
+ Moving left: "DEF\n "[3], "\n abcdefABC"[16, 17, 18], <DIV>[2], "DEF\n "[1, 2], "\n abcdefABC"[15, 14, 13, 12, 11, 10, 9]
+Test 23, RTL:
+ Moving left: "\n abcdefABC"[9, 14, 13, 12, 11, 10, 15, 16, 17, 18], <DIV>[2], "DEF\n "[1, 2, 3]
+ Moving right: "DEF\n "[3, 2, 1], <DIV>[2], "\n abcdefABC"[18, 17, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 24, LTR:
+ Moving right: "\n ABCDEFabc"[9, 14, 13, 12, 11, 10, 15, 16, 17, 18], <DIV>[2], "def\n "[1, 2, 3]
+ Moving left: "def\n "[3, 2, 1], <DIV>[2], "\n ABCDEFabc"[18, 17, 16, 15, 10, 11, 12, 13, 14, 9]
+Test 24, RTL:
+ Moving left: "\n ABCDEFabc"[9, 10, 11, 12, 13, 14, 15], "def\n "[2, 1], <DIV>[2], "\n ABCDEFabc"[18, 17, 16], "def\n "[3]
+ Moving right: "def\n "[3], "\n ABCDEFabc"[16, 17, 18], <DIV>[2], "def\n "[1, 2], "\n ABCDEFabc"[15, 14, 13, 12, 11, 10, 9]
+Test 25, LTR:
+ Moving right: "\n abc"[9, 10, 11, 12], <DIV>[2], "DEFghi\n "[2, 1], <DIV>[5, 4], "ABC"[3, 2, 1], "DEFghi\n "[3, 4, 5, 6]
+ Moving left: "DEFghi\n "[6, 5, 4, 3], "ABC"[1, 2, 3], <DIV>[4, 5], "DEFghi\n "[1, 2], <DIV>[2], "\n abc"[12, 11, 10, 9]
+Test 25, RTL:
+ Moving left: "\n abc"[9, 11, 10, 12], <DIV>[2], "ABC"[1, 2, 3], <DIV>[4, 5], "DEFghi\n "[1, 2, 3, 5, 4, 6]
+ Moving right: "DEFghi\n "[6, 4, 5, 3, 2, 1], <DIV>[5, 4], "ABC"[3, 2, 1], <DIV>[2], "\n abc"[12, 10, 11, 9]
+Test 26, LTR:
+ Moving right: "\n ABC"[9, 11, 10, 12], <DIV>[2], "abc"[1, 2, 3], <DIV>[4, 5], "defDEF\n "[1, 2, 3, 5, 4, 6]
+ Moving left: "defDEF\n "[6, 4, 5, 3, 2, 1], <DIV>[5, 4], "abc"[3, 2, 1], <DIV>[2], "\n ABC"[12, 10, 11, 9]
+Test 26, RTL:
+ Moving left: "\n ABC"[9, 10, 11, 12], <DIV>[2], "defDEF\n "[2, 1], <DIV>[5, 4], "abc"[3, 2, 1], "defDEF\n "[3, 4, 5, 6]
+ Moving right: "defDEF\n "[6, 5, 4, 3], "abc"[1, 2, 3], <DIV>[4, 5], "defDEF\n "[1, 2], <DIV>[2], "\n ABC"[12, 11, 10, 9]
+Test 27, LTR:
+ Moving right: "\n abcABC"[9, 10, 11, 12], "DEF"[2, 1], "\n abcABC"[15, 14, 13], "DEF"[3]
+ Moving left: "DEF"[3], "\n abcABC"[13, 14, 15], "DEF"[1, 2], "\n abcABC"[12, 11, 10, 9]
+Test 27, RTL:
+ Moving left: "\n abcABC"[9, 11, 10, 12, 13, 14, 15], "DEF"[1, 2, 3]
+ Moving right: "DEF"[3, 2, 1], "\n abcABC"[15, 14, 13, 12, 10, 11, 9]
+Test 28, LTR:
+ Moving right: "\n ABCabc"[9, 11, 10, 12, 13, 14, 15], "def"[1, 2, 3]
+ Moving left: "def"[3, 2, 1], "\n ABCabc"[15, 14, 13, 12, 10, 11, 9]
+Test 28, RTL:
+ Moving left: "\n ABCabc"[9, 10, 11, 12], "def"[2, 1], "\n ABCabc"[15, 14, 13], "def"[3]
+ Moving right: "def"[3], "\n ABCabc"[13, 14, 15], "def"[1, 2], "\n ABCabc"[12, 11, 10, 9]
+Test 29, LTR:
+ Moving right: "\n ab"[9, 10, 11], "cABCdef"[1, 3, 2, 4, 5, 6, 7]
+ Moving left: "cABCdef"[7, 6, 5, 4, 2, 3, 1], "\n ab"[11, 10, 9]
+Test 29, RTL:
+ Moving left: "\n ab"[9, 11, 10], "cABCdef"[1, 2, 3, 4, 6, 5, 7]
+ Moving right: "cABCdef"[7, 5, 6, 4, 3, 2, 1], "\n ab"[10, 11, 9]
+Test 30, LTR:
+ Moving right: "\n AB"[9, 11, 10], "CabcDEF"[1, 2, 3, 4, 6, 5, 7]
+ Moving left: "CabcDEF"[7, 5, 6, 4, 3, 2, 1], "\n AB"[10, 11, 9]
+Test 30, RTL:
+ Moving left: "\n AB"[9, 10, 11], "CabcDEF"[1, 3, 2, 4, 5, 6, 7]
+ Moving right: "CabcDEF"[7, 6, 5, 4, 2, 3, 1], "\n AB"[11, 10, 9]
+Test 31, LTR:
+ Moving right: "\n abc"[9, 10, 11, 12], "ABCdef"[2, 1, 3, 4, 5, 6]
+ Moving left: "ABCdef"[6, 5, 4, 3, 1, 2], "\n abc"[12, 11, 10, 9]
+Test 31, RTL:
+ Moving left: "\n abc"[9, 11, 10, 12], "ABCdef"[1, 2, 3, 5, 4, 6]
+ Moving right: "ABCdef"[6, 4, 5, 3, 2, 1], "\n abc"[12, 10, 11, 9]
+Test 32, LTR:
+ Moving right: "\n ABC"[9, 11, 10, 12], "abcDEF"[1, 2, 3, 5, 4, 6]
+ Moving left: "abcDEF"[6, 4, 5, 3, 2, 1], "\n ABC"[12, 10, 11, 9]
+Test 32, RTL:
+ Moving left: "\n ABC"[9, 10, 11, 12], "abcDEF"[2, 1, 3, 4, 5, 6]
+ Moving right: "abcDEF"[6, 5, 4, 3, 1, 2], "\n ABC"[12, 11, 10, 9]
+Test 33, LTR:
+ Moving right: "\n abcAdef\n "[9, 10, 11, 12, 13, 14, 15, 16]
+ Moving left: "\n abcAdef\n "[16, 15, 14, 13, 12, 11, 10, 9]
+Test 33, RTL:
+ Moving left: "\n abcAdef\n "[9, 11, 10, 12, 13, 15, 14, 16]
+ Moving right: "\n abcAdef\n "[16, 14, 15, 13, 12, 10, 11, 9]
+Test 34, LTR:
+ Moving right: "\n ABCaDEF\n "[9, 11, 10, 12, 13, 15, 14, 16]
+ Moving left: "\n ABCaDEF\n "[16, 14, 15, 13, 12, 10, 11, 9]
+Test 34, RTL:
+ Moving left: "\n ABCaDEF\n "[9, 10, 11, 12, 13, 14, 15, 16]
+ Moving right: "\n ABCaDEF\n "[16, 15, 14, 13, 12, 11, 10, 9]
+Test 35, LTR:
+ Moving right: "\n abcABC"[9, 10, 11, 12, 14, 13, 15], "def"[1, 2, 3]
+ Moving left: "def"[3, 2, 1], "\n abcABC"[15, 13, 14, 12, 11, 10, 9]
+Test 35, RTL:
+ Moving left: "\n abcABC"[9, 11, 10, 12, 13, 14, 15], "def"[2, 1, 3]
+ Moving right: "def"[3, 1, 2], "\n abcABC"[15, 14, 13, 12, 10, 11, 9]
+Test 36, LTR:
+ Moving right: "\n ABCabc"[9, 11, 10, 12, 13, 14, 15], "DEF"[2, 1, 3]
+ Moving left: "DEF"[3, 1, 2], "\n ABCabc"[15, 14, 13, 12, 10, 11, 9]
+Test 36, RTL:
+ Moving left: "\n ABCabc"[9, 10, 11, 12, 14, 13, 15], "DEF"[1, 2, 3]
+ Moving right: "DEF"[3, 2, 1], "\n ABCabc"[15, 13, 14, 12, 11, 10, 9]
+Test 37, LTR:
+ Moving right: "\n abcA"[9, 10, 11, 12], "BCdef"[1], "\n abcA"[13], "BCdef"[2, 3, 4, 5]
+ Moving left: "BCdef"[5, 4, 3, 2], "\n abcA"[13], "BCdef"[1], "\n abcA"[12, 11, 10, 9]
+Test 37, RTL:
+ Moving left: "\n abcA"[9, 11, 10, 12, 13], "BCdef"[1, 2, 4, 3, 5]
+ Moving right: "BCdef"[5, 3, 4, 2, 1], "\n abcA"[13, 12, 10, 11, 9]
+Test 38, LTR:
+ Moving right: "\n ABCa"[9, 11, 10, 12, 13], "bcDEF"[1, 2, 4, 3, 5]
+ Moving left: "bcDEF"[5, 3, 4, 2, 1], "\n ABCa"[13, 12, 10, 11, 9]
+Test 38, RTL:
+ Moving left: "\n ABCa"[9, 10, 11, 12], "bcDEF"[1], "\n ABCa"[13], "bcDEF"[2, 3, 4, 5]
+ Moving right: "bcDEF"[5, 4, 3, 2], "\n ABCa"[13], "bcDEF"[1], "\n ABCa"[12, 11, 10, 9]
+
+2008-04-27 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ - fix https://bugs.webkit.org/show_bug.cgi?id=3729
+ <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text
+
+ Test: editing/selection/move-left-right.html
+
+ * editing/SelectionController.cpp:
+ (WebCore::SelectionController::modifyMovingRight): Added. Currently
+ implemented for character granularity, all other being treated as
+ "forward".
+ (WebCore::SelectionController::modifyMovingForward): Renamed
+ modifyMovingRightForward() to this.
+ (WebCore::SelectionController::modifyMovingLeft): Added. Currently
+ implemented for character granularity, all other being treated as
+ "backward".
+ (WebCore::SelectionController::modifyMovingBackward): Renamed
+ modifyMovingLeftBackward() to this.
+ (WebCore::SelectionController::modify): Changed to call either the
+ visual (left/right) or logical (backward/forward) methods depending on
+ the 'dir' argument for moves.
+ * editing/SelectionController.h:
+ * editing/VisiblePosition.cpp:
+ (WebCore::VisiblePosition::leftVisuallyDistinctCandidate): Added.
+ (WebCore::VisiblePosition::left): Added.
+ (WebCore::VisiblePosition::rightVisuallyDistinctCandidate): Added.
+ (WebCore::VisiblePosition::right): Added.
+ * editing/VisiblePosition.h:
+
2008-04-27 Sam Weinig <sam@webkit.org>
Reviewed by Maciej Stachowiak.
return pos;
}
-VisiblePosition SelectionController::modifyMovingRightForward(TextGranularity granularity)
+VisiblePosition SelectionController::modifyMovingRight(TextGranularity granularity)
+{
+ VisiblePosition pos;
+ switch (granularity) {
+ case CharacterGranularity:
+ if (isRange())
+ pos = VisiblePosition(m_sel.end(), m_sel.affinity());
+ else
+ pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).right(true);
+ break;
+ case WordGranularity:
+ case SentenceGranularity:
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case LineBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ // FIXME: Implement all of the above.
+ pos = modifyMovingForward(granularity);
+ break;
+ }
+ return pos;
+}
+
+VisiblePosition SelectionController::modifyMovingForward(TextGranularity granularity)
{
VisiblePosition pos;
// FIXME: Stay in editable content for the less common granularities.
return pos;
}
-VisiblePosition SelectionController::modifyMovingLeftBackward(TextGranularity granularity)
+VisiblePosition SelectionController::modifyMovingLeft(TextGranularity granularity)
+{
+ VisiblePosition pos;
+ switch (granularity) {
+ case CharacterGranularity:
+ if (isRange())
+ pos = VisiblePosition(m_sel.start(), m_sel.affinity());
+ else
+ pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).left(true);
+ break;
+ case WordGranularity:
+ case SentenceGranularity:
+ case LineGranularity:
+ case ParagraphGranularity:
+ case SentenceBoundary:
+ case LineBoundary:
+ case ParagraphBoundary:
+ case DocumentBoundary:
+ // FIXME: Implement all of the above.
+ pos = modifyMovingBackward(granularity);
+ break;
+ }
+ return pos;
+}
+
+VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granularity)
{
VisiblePosition pos;
switch (granularity) {
VisiblePosition pos;
switch (dir) {
- // EDIT FIXME: These need to handle bidi
case RIGHT:
+ if (alter == MOVE)
+ pos = modifyMovingRight(granularity);
+ else
+ pos = modifyExtendingRightForward(granularity);
+ break;
case FORWARD:
if (alter == EXTEND)
pos = modifyExtendingRightForward(granularity);
else
- pos = modifyMovingRightForward(granularity);
+ pos = modifyMovingForward(granularity);
break;
case LEFT:
+ if (alter == MOVE)
+ pos = modifyMovingLeft(granularity);
+ else
+ pos = modifyExtendingLeftBackward(granularity);
+ break;
case BACKWARD:
if (alter == EXTEND)
pos = modifyExtendingLeftBackward(granularity);
else
- pos = modifyMovingLeftBackward(granularity);
+ pos = modifyMovingBackward(granularity);
break;
}
enum EPositionType { START, END, BASE, EXTENT };
VisiblePosition modifyExtendingRightForward(TextGranularity);
- VisiblePosition modifyMovingRightForward(TextGranularity);
+ VisiblePosition modifyMovingRight(TextGranularity);
+ VisiblePosition modifyMovingForward(TextGranularity);
VisiblePosition modifyExtendingLeftBackward(TextGranularity);
- VisiblePosition modifyMovingLeftBackward(TextGranularity);
+ VisiblePosition modifyMovingLeft(TextGranularity);
+ VisiblePosition modifyMovingBackward(TextGranularity);
void layout();
IntRect caretRepaintRect() const;
return honorEditableBoundaryAtOrBefore(prev);
}
+Position VisiblePosition::leftVisuallyDistinctCandidate() const
+{
+ Position p = m_deepPosition;
+ Position downstreamStart = p.downstream();
+
+ TextDirection primaryDirection = LTR;
+ for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
+ if (r->isBlockFlow()) {
+ primaryDirection = r->style()->direction();
+ break;
+ }
+ }
+
+ while (true) {
+ InlineBox* box;
+ int offset;
+ p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
+ if (!box)
+ return primaryDirection == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p);
+
+ RenderObject* renderer = box->object();
+
+ while (true) {
+ if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())
+ return box->direction() == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p);
+
+ offset = box->direction() == LTR ? renderer->previousOffset(offset) : renderer->nextOffset(offset);
+
+ int caretMinOffset = box->caretMinOffset();
+ int caretMaxOffset = box->caretMaxOffset();
+
+ if (offset > caretMinOffset && offset < caretMaxOffset)
+ break;
+
+ if (box->direction() == LTR ? offset < caretMinOffset : offset > caretMaxOffset) {
+ // Overshot to the left.
+ InlineBox* prevBox = box->prevLeafChild();
+ if (!prevBox)
+ return primaryDirection == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p);;
+
+ // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
+ box = prevBox;
+ renderer = box->object();
+ offset = prevBox->caretRightmostOffset();
+ continue;
+ }
+
+ ASSERT(offset == box->caretLeftmostOffset());
+
+ unsigned char level = box->bidiLevel();
+ InlineBox* prevBox = box->prevLeafChild();
+
+ if (box->direction() == primaryDirection) {
+ if (!prevBox || prevBox->bidiLevel() >= level)
+ break;
+
+ level = prevBox->bidiLevel();
+
+ InlineBox* nextBox = box;
+ do {
+ nextBox = nextBox->nextLeafChild();
+ } while (nextBox && nextBox->bidiLevel() > level);
+
+ if (nextBox && nextBox->bidiLevel() == level)
+ break;
+
+ while (InlineBox* prevBox = box->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ box = prevBox;
+ }
+ renderer = box->object();
+ offset = box->caretRightmostOffset();
+ if (box->direction() == primaryDirection)
+ break;
+ continue;
+ }
+
+ if (prevBox) {
+ box = prevBox;
+ renderer = box->object();
+ offset = box->caretRightmostOffset();
+ if (box->bidiLevel() > level) {
+ do {
+ prevBox = box->prevLeafChild();
+ } while (prevBox && prevBox->bidiLevel() > level);
+
+ if (!prevBox || prevBox->bidiLevel() < level)
+ continue;
+ }
+ } else {
+ // Trailing edge of a secondary run. Set to the leading edge of the entire run.
+ while (true) {
+ while (InlineBox* nextBox = box->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ box = nextBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ while (InlineBox* prevBox = box->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ box = prevBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ }
+ renderer = box->object();
+ offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
+ }
+ break;
+ }
+
+ p = Position(renderer->element(), offset);
+
+ if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
+ return p;
+ }
+}
+
+VisiblePosition VisiblePosition::left(bool stayInEditableContent) const
+{
+ Position pos = leftVisuallyDistinctCandidate();
+ if (pos.atStart() || pos.atEnd())
+ return VisiblePosition();
+
+ VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);
+ ASSERT(left != *this);
+
+ if (!stayInEditableContent)
+ return left;
+
+ // FIXME: This may need to do something different from "before".
+ return honorEditableBoundaryAtOrBefore(left);
+}
+
+Position VisiblePosition::rightVisuallyDistinctCandidate() const
+{
+ Position p = m_deepPosition;
+ Position downstreamStart = p.downstream();
+
+ TextDirection primaryDirection = LTR;
+ for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) {
+ if (r->isBlockFlow()) {
+ primaryDirection = r->style()->direction();
+ break;
+ }
+ }
+
+ while (true) {
+ InlineBox* box;
+ int offset;
+ p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset);
+ if (!box)
+ return primaryDirection == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p);
+
+ RenderObject* renderer = box->object();
+
+ while (true) {
+ if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())
+ return box->direction() == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p);
+
+ offset = box->direction() == LTR ? renderer->nextOffset(offset) : renderer->previousOffset(offset);
+
+ int caretMinOffset = box->caretMinOffset();
+ int caretMaxOffset = box->caretMaxOffset();
+
+ if (offset > caretMinOffset && offset < caretMaxOffset)
+ break;
+
+ if (box->direction() == LTR ? offset > caretMaxOffset : offset < caretMinOffset) {
+ // Overshot to the right.
+ InlineBox* nextBox = box->nextLeafChild();
+ if (!nextBox)
+ return primaryDirection == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p);;
+
+ // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
+ box = nextBox;
+ renderer = box->object();
+ offset = nextBox->caretLeftmostOffset();
+ continue;
+ }
+
+ ASSERT(offset == box->caretRightmostOffset());
+
+ unsigned char level = box->bidiLevel();
+ InlineBox* nextBox = box->nextLeafChild();
+
+ if (box->direction() == primaryDirection) {
+ if (!nextBox || nextBox->bidiLevel() >= level)
+ break;
+
+ level = nextBox->bidiLevel();
+
+ InlineBox* prevBox = box;
+ do {
+ prevBox = prevBox->prevLeafChild();
+ } while (prevBox && prevBox->bidiLevel() > level);
+
+ if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA
+ break;
+
+ // For example, abc 123 ^ CBA
+ while (InlineBox* nextBox = box->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ box = nextBox;
+ }
+ renderer = box->object();
+ offset = box->caretLeftmostOffset();
+ if (box->direction() == primaryDirection)
+ break;
+ continue;
+ }
+
+ if (nextBox) {
+ box = nextBox;
+ renderer = box->object();
+ offset = box->caretLeftmostOffset();
+ if (box->bidiLevel() > level) {
+ do {
+ nextBox = box->nextLeafChild();
+ } while (nextBox && nextBox->bidiLevel() > level);
+
+ if (!nextBox || nextBox->bidiLevel() < level)
+ continue;
+ }
+ } else {
+ // Trailing edge of a secondary run. Set to the leading edge of the entire run.
+ while (true) {
+ while (InlineBox* prevBox = box->prevLeafChild()) {
+ if (prevBox->bidiLevel() < level)
+ break;
+ box = prevBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ while (InlineBox* nextBox = box->nextLeafChild()) {
+ if (nextBox->bidiLevel() < level)
+ break;
+ box = nextBox;
+ }
+ if (box->bidiLevel() == level)
+ break;
+ level = box->bidiLevel();
+ }
+ renderer = box->object();
+ offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
+ }
+ break;
+ }
+
+ p = Position(renderer->element(), offset);
+
+ if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
+ return p;
+ }
+}
+
+VisiblePosition VisiblePosition::right(bool stayInEditableContent) const
+{
+ Position pos = rightVisuallyDistinctCandidate();
+ if (pos.atStart() || pos.atEnd())
+ return VisiblePosition();
+
+ VisiblePosition right = VisiblePosition(pos, DOWNSTREAM);
+ ASSERT(right != *this);
+
+ if (!stayInEditableContent)
+ return right;
+
+ // FIXME: This may need to do something different from "after".
+ return honorEditableBoundaryAtOrAfter(right);
+}
+
VisiblePosition VisiblePosition::honorEditableBoundaryAtOrBefore(const VisiblePosition &pos) const
{
if (pos.isNull())
VisiblePosition honorEditableBoundaryAtOrBefore(const VisiblePosition&) const;
VisiblePosition honorEditableBoundaryAtOrAfter(const VisiblePosition&) const;
+ VisiblePosition left(bool stayInEditableContent = false) const;
+ VisiblePosition right(bool stayInEditableContent = false) const;
+
UChar characterAfter() const;
UChar characterBefore() const { return previous().characterAfter(); }
void init(const Position&, EAffinity);
Position canonicalPosition(const Position&);
+ Position leftVisuallyDistinctCandidate() const;
+ Position rightVisuallyDistinctCandidate() const;
+
Position m_deepPosition;
EAffinity m_affinity;
};