| 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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); | 700 EXPECT_STREQ("aaa\nbbbddd\neee", div->innerText().utf8().data()); |
| 701 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); | 701 EXPECT_EQ(7u, controller().getSelectionOffsets().start()); |
| 702 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); | 702 EXPECT_EQ(7u, controller().getSelectionOffsets().end()); |
| 703 | 703 |
| 704 controller().deleteSurroundingText(5, 5); | 704 controller().deleteSurroundingText(5, 5); |
| 705 EXPECT_STREQ("aaee", div->innerText().utf8().data()); | 705 EXPECT_STREQ("aaee", div->innerText().utf8().data()); |
| 706 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 706 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
| 707 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 707 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
| 708 } | 708 } |
| 709 | 709 |
| 710 TEST_F(InputMethodControllerTest, |
| 711 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheLeft) { |
| 712 HTMLInputElement* input = |
| 713 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 714 |
| 715 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text (U+0E01 |
| 716 // "ka kai" + U+0E49 "mai tho"). |
| 717 // A "black star" is 1 grapheme cluster. It has 1 code point, and its length |
| 718 // is 1 (abbreviated as [1,1,1]). A "trophy": [1,1,2]. The composed text: |
| 719 // [1,2,2]. |
| 720 input->setValue(String::fromUTF8( |
| 721 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 722 document().updateStyleAndLayout(); |
| 723 // The cursor is at the end of the text. |
| 724 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); |
| 725 |
| 726 controller().deleteSurroundingTextInCodePoints(2, 0); |
| 727 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); |
| 728 controller().deleteSurroundingTextInCodePoints(4, 0); |
| 729 EXPECT_STREQ("a", input->value().utf8().data()); |
| 730 |
| 731 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 732 input->setValue(String::fromUTF8( |
| 733 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 734 document().updateStyleAndLayout(); |
| 735 // The cursor is at the end of the text. |
| 736 controller().setEditableSelectionOffsets(PlainTextRange(8, 8)); |
| 737 |
| 738 // TODO(yabinh): We should only delete 1 code point instead of the entire |
| 739 // grapheme cluster (2 code points). The root cause is that we adjust the |
| 740 // selection by grapheme cluster in deleteSurroundingText(). |
| 741 controller().deleteSurroundingTextInCodePoints(1, 0); |
| 742 EXPECT_STREQ("a\xE2\x98\x85 \xF0\x9F\x8F\x86 ", input->value().utf8().data()); |
| 743 } |
| 744 |
| 745 TEST_F(InputMethodControllerTest, |
| 746 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnTheRight) { |
| 747 HTMLInputElement* input = |
| 748 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 749 |
| 750 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 751 input->setValue(String::fromUTF8( |
| 752 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 753 document().updateStyleAndLayout(); |
| 754 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); |
| 755 |
| 756 controller().deleteSurroundingTextInCodePoints(0, 5); |
| 757 EXPECT_STREQ("\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); |
| 758 |
| 759 controller().deleteSurroundingTextInCodePoints(0, 1); |
| 760 // TODO(yabinh): Same here. We should only delete 1 code point. |
| 761 EXPECT_STREQ("", input->value().utf8().data()); |
| 762 } |
| 763 |
| 764 TEST_F(InputMethodControllerTest, |
| 765 DeleteSurroundingTextInCodePointsWithMultiCodeTextOnBothSides) { |
| 766 HTMLInputElement* input = |
| 767 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 768 |
| 769 // 'a' + "black star" + SPACE + "trophy" + SPACE + composed text |
| 770 input->setValue(String::fromUTF8( |
| 771 "a\xE2\x98\x85 \xF0\x9F\x8F\x86 \xE0\xB8\x81\xE0\xB9\x89")); |
| 772 document().updateStyleAndLayout(); |
| 773 controller().setEditableSelectionOffsets(PlainTextRange(3, 3)); |
| 774 controller().deleteSurroundingTextInCodePoints(2, 2); |
| 775 EXPECT_STREQ("a\xE0\xB8\x81\xE0\xB9\x89", input->value().utf8().data()); |
| 776 } |
| 777 |
| 778 TEST_F(InputMethodControllerTest, DeleteSurroundingTextInCodePointsWithImage) { |
| 779 Element* div = insertHTMLElement( |
| 780 "<div id='sample' contenteditable>aaa" |
| 781 "<img src='empty.png'>bbb</div>", |
| 782 "sample"); |
| 783 |
| 784 controller().setEditableSelectionOffsets(PlainTextRange(4, 4)); |
| 785 controller().deleteSurroundingTextInCodePoints(1, 1); |
| 786 EXPECT_STREQ("aaabb", div->innerText().utf8().data()); |
| 787 EXPECT_EQ(3u, controller().getSelectionOffsets().start()); |
| 788 EXPECT_EQ(3u, controller().getSelectionOffsets().end()); |
| 789 } |
| 790 |
| 791 TEST_F(InputMethodControllerTest, |
| 792 DeleteSurroundingTextInCodePointsWithInvalidSurrogatePair) { |
| 793 HTMLInputElement* input = |
| 794 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 795 |
| 796 // 'a' + high surrogate of "trophy" + "black star" + low surrogate of "trophy" |
| 797 // + SPACE |
| 798 const UChar UText[] = {'a', 0xD83C, 0x2605, 0xDFC6, ' ', '\0'}; |
| 799 const String& text = String(UText); |
| 800 |
| 801 input->setValue(text); |
| 802 document().updateStyleAndLayout(); |
| 803 // The invalid high surrogate is encoded as '\xED\xA0\xBC', and invalid low |
| 804 // surrogate is encoded as '\xED\xBF\x86'. |
| 805 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86 ", |
| 806 input->value().utf8().data()); |
| 807 |
| 808 controller().setEditableSelectionOffsets(PlainTextRange(5, 5)); |
| 809 // Delete a SPACE. |
| 810 controller().deleteSurroundingTextInCodePoints(1, 0); |
| 811 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 812 input->value().utf8().data()); |
| 813 // Do nothing since there is an invalid surrogate in the requested range. |
| 814 controller().deleteSurroundingTextInCodePoints(2, 0); |
| 815 EXPECT_STREQ("a\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 816 input->value().utf8().data()); |
| 817 |
| 818 controller().setEditableSelectionOffsets(PlainTextRange(0, 0)); |
| 819 // Delete 'a'. |
| 820 controller().deleteSurroundingTextInCodePoints(0, 1); |
| 821 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 822 input->value().utf8().data()); |
| 823 // Do nothing since there is an invalid surrogate in the requested range. |
| 824 controller().deleteSurroundingTextInCodePoints(0, 2); |
| 825 EXPECT_STREQ("\xED\xA0\xBC\xE2\x98\x85\xED\xBF\x86", |
| 826 input->value().utf8().data()); |
| 827 } |
| 828 |
| 710 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { | 829 TEST_F(InputMethodControllerTest, SetCompositionForInputWithNewCaretPositions) { |
| 711 HTMLInputElement* input = | 830 HTMLInputElement* input = |
| 712 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); | 831 toHTMLInputElement(insertHTMLElement("<input id='sample'>", "sample")); |
| 713 | 832 |
| 714 input->setValue("hello"); | 833 input->setValue("hello"); |
| 715 document().updateStyleAndLayout(); | 834 document().updateStyleAndLayout(); |
| 716 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); | 835 controller().setEditableSelectionOffsets(PlainTextRange(2, 2)); |
| 717 EXPECT_STREQ("hello", input->value().utf8().data()); | 836 EXPECT_STREQ("hello", input->value().utf8().data()); |
| 718 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); | 837 EXPECT_EQ(2u, controller().getSelectionOffsets().start()); |
| 719 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); | 838 EXPECT_EQ(2u, controller().getSelectionOffsets().end()); |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 | 1274 |
| 1156 controller().commitText(String("string"), underlines, 0); | 1275 controller().commitText(String("string"), underlines, 0); |
| 1157 | 1276 |
| 1158 ASSERT_EQ(1u, document().markers().markers().size()); | 1277 ASSERT_EQ(1u, document().markers().markers().size()); |
| 1159 | 1278 |
| 1160 EXPECT_EQ(9u, document().markers().markers()[0]->startOffset()); | 1279 EXPECT_EQ(9u, document().markers().markers()[0]->startOffset()); |
| 1161 EXPECT_EQ(15u, document().markers().markers()[0]->endOffset()); | 1280 EXPECT_EQ(15u, document().markers().markers()[0]->endOffset()); |
| 1162 } | 1281 } |
| 1163 | 1282 |
| 1164 } // namespace blink | 1283 } // namespace blink |
| OLD | NEW |