Chromium Code Reviews| 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 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); | 723 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); |
| 724 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); | 724 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); |
| 725 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); | 725 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); |
| 726 | 726 |
| 727 controller().deleteSurroundingText(5, 5); | 727 controller().deleteSurroundingText(5, 5); |
| 728 EXPECT_STREQ("aaee", div->innerText().utf8().data()); | 728 EXPECT_STREQ("aaee", div->innerText().utf8().data()); |
| 729 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 729 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
| 730 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 730 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
| 731 } | 731 } |
| 732 | 732 |
| 733 TEST_F(InputMethodControllerTest, | |
| 734 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheLeft) { | |
| 735 HTMLInputElement* input = | |
| 736 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | |
| 737 | |
| 738 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text (U+0E01 | |
| 739 // "ka kai" + U+0E49 "mai tho"). | |
| 740 // A "black star" is 1 grapheme cluster. It has 1 code point, and its length | |
| 741 // is 1 (abbreviated as [1,1,1]). A "trophy": [1,1,2]. The composed text: | |
| 742 // [1,2,2]. | |
| 743 input->setValue(String::fromUTF8( | |
| 744 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); | |
| 745 document().updateStyleAndLayout(); | |
| 746 // The cursor is at the end of the text. | |
| 747 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); | |
| 748 | |
| 749 controller().deleteSurroundingTextInCodePoints(2, 0); | |
| 750 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); | |
| 751 controller().deleteSurroundingTextInCodePoints(4, 0); | |
| 752 EXPECT_STREQ("a", input->value().utf8().data()); | |
| 753 | |
| 754 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text | |
| 755 input->setValue(String::fromUTF8( | |
| 756 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); | |
| 757 document().updateStyleAndLayout(); | |
| 758 // The cursor is at the end of the text. | |
| 759 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); | |
| 760 | |
| 761 // TODO(yabinh): We should only delete 1 code point instead of the entire | |
| 762 // grapheme cluster (2 code points). The root cause is that we adjust the | |
| 763 // selection by grapheme cluster in deleteSurroundingText(). | |
| 764 controller().deleteSurroundingTextInCodePoints(1, 0); | |
| 765 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); | |
| 766 } | |
| 767 | |
| 768 TEST_F(InputMethodControllerTest, | |
| 769 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheRight) { | |
| 770 HTMLInputElement* input = | |
| 771 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | |
| 772 | |
| 773 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text | |
| 774 input->setValue(String::fromUTF8( | |
| 775 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); | |
| 776 document().updateStyleAndLayout(); | |
| 777 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); | |
| 778 | |
| 779 controller().deleteSurroundingTextInCodePoints(0, 5); | |
| 780 EXPECT_STREQ("\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); | |
| 781 | |
| 782 controller().deleteSurroundingTextInCodePoints(0, 1); | |
| 783 // TODO(yabinh): Same here. We should only delete 1 code point. | |
| 784 EXPECT_STREQ("", input->value().utf8().data()); | |
| 785 } | |
| 786 | |
| 787 TEST_F(InputMethodControllerTest, | |
| 788 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnBothSides) { | |
| 789 HTMLInputElement* input = | |
| 790 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | |
| 791 | |
| 792 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text | |
| 793 input->setValue(String::fromUTF8( | |
| 794 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); | |
| 795 document().updateStyleAndLayout(); | |
| 796 controller().setEditableSelectionOffsets(PlainTextRange(3, 3)); | |
| 797 controller().deleteSurroundingTextInCodePoints(2, 2); | |
| 798 EXPECT_STREQ("a\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); | |
| 799 } | |
| 800 | |
| 801 TEST_F(InputMethodControllerTest, DeleteSurroundingTextInCodePointsWithImage) { | |
| 802 Element* div = insertHTMLElement( | |
| 803 "<div id='sample' contenteditable>aaa" | |
| 804 "<img src='empty.png'>bbb</div>", | |
| 805 "sample"); | |
| 806 | |
| 807 controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); | |
| 808 controller().deleteSurroundingTextInCodePoints(1, 1); | |
| 809 EXPECT_STREQ("aaabb", div->innerText().utf8().data()); | |
| 810 EXPECT_EQ(3u, controller().getSelectionOffsets().start()); | |
| 811 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); | |
| 812 } | |
| 813 | |
| 814 TEST_F(InputMethodControllerTest, | |
| 815 DeleteSurroundingTextInCodePointsWithInvalidSurrogatePair) { | |
| 816 HTMLInputElement* input = | |
| 817 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | |
| 818 | |
| 819 // 'a' + high surrogate of "trophy" + "black star" + low surrogate of "trophy" | |
| 820 // + SPACE | |
| 821 const UChar UText[] = {'a', 0xD83C, 0x2605, 0xDFC6, ' ', '\0'}; | |
|
yosin_UTC9
2017/02/09 07:19:27
s/UText/utext/ or another. Don't start variable na
yabinh
2017/02/09 10:37:03
Done.
| |
| 822 const String& text = String(UText); | |
| 823 | |
| 824 input->setValue(text); | |
| 825 document().updateStyleAndLayout(); | |
| 826 // The invalid high surrogate is encoded as '\xED\xA0\xBC', and invalid low | |
| 827 // surrogate is encoded as '\xED\xBF\x86'. | |
| 828 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86 ", | |
| 829 input->value().utf8().data()); | |
| 830 | |
| 831 controller().setEditableSelectionOffsets(PlainTextRange(5, 5)); | |
| 832 // Delete a SPACE. | |
| 833 controller().deleteSurroundingTextInCodePoints(1, 0); | |
| 834 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", | |
| 835 input->value().utf8().data()); | |
| 836 // Do nothing since there is an invalid surrogate in the requested range. | |
| 837 controller().deleteSurroundingTextInCodePoints(2, 0); | |
| 838 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", | |
| 839 input->value().utf8().data()); | |
| 840 | |
| 841 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); | |
| 842 // Delete 'a'. | |
| 843 controller().deleteSurroundingTextInCodePoints(0, 1); | |
| 844 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", | |
| 845 input->value().utf8().data()); | |
| 846 // Do nothing since there is an invalid surrogate in the requested range. | |
| 847 controller().deleteSurroundingTextInCodePoints(0, 2); | |
| 848 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", | |
| 849 input->value().utf8().data()); | |
| 850 } | |
| 851 | |
| 733 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { | 852 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { |
| 734 HTMLInputElement* input = | 853 HTMLInputElement* input = |
| 735 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | 854 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 736 | 855 |
| 737 input->setValue("hello"); | 856 input->setValue("hello"); |
| 738 document().updateStyleAndLayout(); | 857 document().updateStyleAndLayout(); |
| 739 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); | 858 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); |
| 740 EXPECT_STREQ("hello", input->value().utf8().data()); | 859 EXPECT_STREQ("hello", input->value().utf8().data()); |
| 741 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 860 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
| 742 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 861 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1190 | 1309 |
| 1191 controller().commitText(String("string"), underlines, 0); | 1310 controller().commitText(String("string"), underlines, 0); |
| 1192 | 1311 |
| 1193 ASSERT_EQ(1u, document().markers().markers().size()); | 1312 ASSERT_EQ(1u, document().markers().markers().size()); |
| 1194 | 1313 |
| 1195 EXPECT_EQ(9u, document().markers().markers()[0]->startOffset()); | 1314 EXPECT_EQ(9u, document().markers().markers()[0]->startOffset()); |
| 1196 EXPECT_EQ(15u, document().markers().markers()[0]->endOffset()); | 1315 EXPECT_EQ(15u, document().markers().markers()[0]->endOffset()); |
| 1197 } | 1316 } |
| 1198 | 1317 |
| 1199 } // namespace blink | 1318 } // namespace blink |
| OLD | NEW |