OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/editing/InputMethodController.h" | 5 #include "core/editing/InputMethodController.h" |
6 | 6 |
7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
8 #include "core/dom/Element.h" | 8 #include "core/dom/Element.h" |
9 #include "core/dom/Range.h" | 9 #include "core/dom/Range.h" |
10 #include "core/editing/Editor.h" | 10 #include "core/editing/Editor.h" |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); | 739 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); |
740 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); | 740 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); |
741 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); | 741 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); |
742 | 742 |
743 controller().deleteSurroundingText(5, 5); | 743 controller().deleteSurroundingText(5, 5); |
744 EXPECT_STREQ("aaee", div->innerText().utf8().data()); | 744 EXPECT_STREQ("aaee", div->innerText().utf8().data()); |
745 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 745 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
746 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 746 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
747 } | 747 } |
748 | 748 |
| 749 TEST_F(InputMethodControllerTest, |
| 750 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheLeft) { |
| 751 HTMLInputElement* input = |
| 752 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 753 |
| 754 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text (U+0E01 |
| 755 // "ka kai" + U+0E49 "mai tho"). |
| 756 // A "black star" is 1 grapheme cluster. It has 1 code point, and its length |
| 757 // is 1 (abbreviated as [1,1,1]). A "trophy": [1,1,2]. The composed text: |
| 758 // [1,2,2]. |
| 759 input->setValue(String::fromUTF8( |
| 760 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 761 document().updateStyleAndLayout(); |
| 762 // The cursor is at the end of the text. |
| 763 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); |
| 764 |
| 765 controller().deleteSurroundingTextInCodePoints(2, 0); |
| 766 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); |
| 767 controller().deleteSurroundingTextInCodePoints(4, 0); |
| 768 EXPECT_STREQ("a", input->value().utf8().data()); |
| 769 |
| 770 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 771 input->setValue(String::fromUTF8( |
| 772 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 773 document().updateStyleAndLayout(); |
| 774 // The cursor is at the end of the text. |
| 775 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); |
| 776 |
| 777 // TODO(yabinh): We should only delete 1 code point instead of the entire |
| 778 // grapheme cluster (2 code points). The root cause is that we adjust the |
| 779 // selection by grapheme cluster in deleteSurroundingText(). |
| 780 controller().deleteSurroundingTextInCodePoints(1, 0); |
| 781 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); |
| 782 } |
| 783 |
| 784 TEST_F(InputMethodControllerTest, |
| 785 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheRight) { |
| 786 HTMLInputElement* input = |
| 787 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 788 |
| 789 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 790 input->setValue(String::fromUTF8( |
| 791 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 792 document().updateStyleAndLayout(); |
| 793 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); |
| 794 |
| 795 controller().deleteSurroundingTextInCodePoints(0, 5); |
| 796 EXPECT_STREQ("\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); |
| 797 |
| 798 controller().deleteSurroundingTextInCodePoints(0, 1); |
| 799 // TODO(yabinh): Same here. We should only delete 1 code point. |
| 800 EXPECT_STREQ("", input->value().utf8().data()); |
| 801 } |
| 802 |
| 803 TEST_F(InputMethodControllerTest, |
| 804 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnBothSides) { |
| 805 HTMLInputElement* input = |
| 806 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 807 |
| 808 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 809 input->setValue(String::fromUTF8( |
| 810 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 811 document().updateStyleAndLayout(); |
| 812 controller().setEditableSelectionOffsets(PlainTextRange(3, 3)); |
| 813 controller().deleteSurroundingTextInCodePoints(2, 2); |
| 814 EXPECT_STREQ("a\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); |
| 815 } |
| 816 |
| 817 TEST_F(InputMethodControllerTest, DeleteSurroundingTextInCodePointsWithImage) { |
| 818 Element* div = insertHTMLElement( |
| 819 "<div id='sample' contenteditable>aaa" |
| 820 "<img src='empty.png'>bbb</div>", |
| 821 "sample"); |
| 822 |
| 823 controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); |
| 824 controller().deleteSurroundingTextInCodePoints(1, 1); |
| 825 EXPECT_STREQ("aaabb", div->innerText().utf8().data()); |
| 826 EXPECT_EQ(3u, controller().getSelectionOffsets().start()); |
| 827 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); |
| 828 } |
| 829 |
| 830 TEST_F(InputMethodControllerTest, |
| 831 DeleteSurroundingTextInCodePointsWithInvalidSurrogatePair) { |
| 832 HTMLInputElement* input = |
| 833 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 834 |
| 835 // 'a' + high surrogate of "trophy" + "black star" + low surrogate of "trophy" |
| 836 // + SPACE |
| 837 const UChar uText[] = {'a', 0xD83C, 0x2605, 0xDFC6, ' ', '\0'}; |
| 838 const String& text = String(uText); |
| 839 |
| 840 input->setValue(text); |
| 841 document().updateStyleAndLayout(); |
| 842 // The invalid high surrogate is encoded as '\xED\xA0\xBC', and invalid low |
| 843 // surrogate is encoded as '\xED\xBF\x86'. |
| 844 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86 ", |
| 845 input->value().utf8().data()); |
| 846 |
| 847 controller().setEditableSelectionOffsets(PlainTextRange(5, 5)); |
| 848 // Delete a SPACE. |
| 849 controller().deleteSurroundingTextInCodePoints(1, 0); |
| 850 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 851 input->value().utf8().data()); |
| 852 // Do nothing since there is an invalid surrogate in the requested range. |
| 853 controller().deleteSurroundingTextInCodePoints(2, 0); |
| 854 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 855 input->value().utf8().data()); |
| 856 |
| 857 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); |
| 858 // Delete 'a'. |
| 859 controller().deleteSurroundingTextInCodePoints(0, 1); |
| 860 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 861 input->value().utf8().data()); |
| 862 // Do nothing since there is an invalid surrogate in the requested range. |
| 863 controller().deleteSurroundingTextInCodePoints(0, 2); |
| 864 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 865 input->value().utf8().data()); |
| 866 } |
| 867 |
749 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { | 868 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { |
750 HTMLInputElement* input = | 869 HTMLInputElement* input = |
751 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | 870 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
752 | 871 |
753 input->setValue("hello"); | 872 input->setValue("hello"); |
754 document().updateStyleAndLayout(); | 873 document().updateStyleAndLayout(); |
755 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); | 874 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); |
756 EXPECT_STREQ("hello", input->value().utf8().data()); | 875 EXPECT_STREQ("hello", input->value().utf8().data()); |
757 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 876 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
758 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 877 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 // Make sure that caret is still at the end of the inserted text. | 1403 // Make sure that caret is still at the end of the inserted text. |
1285 EXPECT_FALSE(controller().hasComposition()); | 1404 EXPECT_FALSE(controller().hasComposition()); |
1286 EXPECT_EQ(7, frame() | 1405 EXPECT_EQ(7, frame() |
1287 .selection() | 1406 .selection() |
1288 .computeVisibleSelectionInDOMTreeDeprecated() | 1407 .computeVisibleSelectionInDOMTreeDeprecated() |
1289 .start() | 1408 .start() |
1290 .computeOffsetInContainerNode()); | 1409 .computeOffsetInContainerNode()); |
1291 } | 1410 } |
1292 | 1411 |
1293 } // namespace blink | 1412 } // namespace blink |
OLD | NEW |