| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/base/ime/win/tsf_text_store.h" | 5 #include "ui/base/ime/win/tsf_text_store.h" |
| 6 | 6 |
| 7 #include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE | 7 #include <initguid.h> // for GUID_NULL and GUID_PROP_INPUTSCOPE |
| 8 #include <InputScope.h> | 8 #include <InputScope.h> |
| 9 #include <OleCtl.h> | 9 #include <OleCtl.h> |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 | 22 |
| 23 namespace ui { | 23 namespace ui { |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 class MockTextInputClient : public TextInputClient { | 26 class MockTextInputClient : public TextInputClient { |
| 27 public: | 27 public: |
| 28 ~MockTextInputClient() {} | 28 ~MockTextInputClient() {} |
| 29 MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&)); | 29 MOCK_METHOD1(SetCompositionText, void(const ui::CompositionText&)); |
| 30 MOCK_METHOD0(ConfirmCompositionText, void()); | 30 MOCK_METHOD0(ConfirmCompositionText, void()); |
| 31 MOCK_METHOD0(ClearCompositionText, void()); | 31 MOCK_METHOD0(ClearCompositionText, void()); |
| 32 MOCK_METHOD1(InsertText, void(const string16&)); | 32 MOCK_METHOD1(InsertText, void(const base::string16&)); |
| 33 MOCK_METHOD2(InsertChar, void(char16, int)); | 33 MOCK_METHOD2(InsertChar, void(char16, int)); |
| 34 MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow()); | 34 MOCK_CONST_METHOD0(GetAttachedWindow, gfx::NativeWindow()); |
| 35 MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType()); | 35 MOCK_CONST_METHOD0(GetTextInputType, ui::TextInputType()); |
| 36 MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode()); | 36 MOCK_CONST_METHOD0(GetTextInputMode, ui::TextInputMode()); |
| 37 MOCK_CONST_METHOD0(CanComposeInline, bool()); | 37 MOCK_CONST_METHOD0(CanComposeInline, bool()); |
| 38 MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect()); | 38 MOCK_CONST_METHOD0(GetCaretBounds, gfx::Rect()); |
| 39 MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*)); | 39 MOCK_CONST_METHOD2(GetCompositionCharacterBounds, bool(uint32, gfx::Rect*)); |
| 40 MOCK_CONST_METHOD0(HasCompositionText, bool()); | 40 MOCK_CONST_METHOD0(HasCompositionText, bool()); |
| 41 MOCK_CONST_METHOD1(GetTextRange, bool(gfx::Range*)); | 41 MOCK_CONST_METHOD1(GetTextRange, bool(gfx::Range*)); |
| 42 MOCK_CONST_METHOD1(GetCompositionTextRange, bool(gfx::Range*)); | 42 MOCK_CONST_METHOD1(GetCompositionTextRange, bool(gfx::Range*)); |
| 43 MOCK_CONST_METHOD1(GetSelectionRange, bool(gfx::Range*)); | 43 MOCK_CONST_METHOD1(GetSelectionRange, bool(gfx::Range*)); |
| 44 MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&)); | 44 MOCK_METHOD1(SetSelectionRange, bool(const gfx::Range&)); |
| 45 MOCK_METHOD1(DeleteRange, bool(const gfx::Range&)); | 45 MOCK_METHOD1(DeleteRange, bool(const gfx::Range&)); |
| 46 MOCK_CONST_METHOD2(GetTextFromRange, bool(const gfx::Range&, string16*)); | 46 MOCK_CONST_METHOD2(GetTextFromRange, bool(const gfx::Range&, |
| 47 base::string16*)); |
| 47 MOCK_METHOD0(OnInputMethodChanged, void()); | 48 MOCK_METHOD0(OnInputMethodChanged, void()); |
| 48 MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment, | 49 MOCK_METHOD1(ChangeTextDirectionAndLayoutAlignment, |
| 49 bool(base::i18n::TextDirection)); | 50 bool(base::i18n::TextDirection)); |
| 50 MOCK_METHOD2(ExtendSelectionAndDelete, void(size_t, size_t)); | 51 MOCK_METHOD2(ExtendSelectionAndDelete, void(size_t, size_t)); |
| 51 MOCK_METHOD1(EnsureCaretInRect, void(const gfx::Rect&)); | 52 MOCK_METHOD1(EnsureCaretInRect, void(const gfx::Rect&)); |
| 52 MOCK_METHOD0(OnCandidateWindowShown, void()); | 53 MOCK_METHOD0(OnCandidateWindowShown, void()); |
| 53 MOCK_METHOD0(OnCandidateWindowUpdated, void()); | 54 MOCK_METHOD0(OnCandidateWindowUpdated, void()); |
| 54 MOCK_METHOD0(OnCandidateWindowHidden, void()); | 55 MOCK_METHOD0(OnCandidateWindowHidden, void()); |
| 55 }; | 56 }; |
| 56 | 57 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 &text_input_client_); | 122 &text_input_client_); |
| 122 } | 123 } |
| 123 | 124 |
| 124 virtual void TearDown() OVERRIDE { | 125 virtual void TearDown() OVERRIDE { |
| 125 EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_)); | 126 EXPECT_EQ(S_OK, text_store_->UnadviseSink(sink_)); |
| 126 sink_ = NULL; | 127 sink_ = NULL; |
| 127 text_store_ = NULL; | 128 text_store_ = NULL; |
| 128 } | 129 } |
| 129 | 130 |
| 130 // Accessors to the internal state of TSFTextStore. | 131 // Accessors to the internal state of TSFTextStore. |
| 131 string16* string_buffer() { return &text_store_->string_buffer_; } | 132 base::string16* string_buffer() { return &text_store_->string_buffer_; } |
| 132 size_t* committed_size() { return &text_store_->committed_size_; } | 133 size_t* committed_size() { return &text_store_->committed_size_; } |
| 133 | 134 |
| 134 base::win::ScopedCOMInitializer com_initializer_; | 135 base::win::ScopedCOMInitializer com_initializer_; |
| 135 MockTextInputClient text_input_client_; | 136 MockTextInputClient text_input_client_; |
| 136 scoped_refptr<TSFTextStore> text_store_; | 137 scoped_refptr<TSFTextStore> text_store_; |
| 137 scoped_refptr<MockStoreACPSink> sink_; | 138 scoped_refptr<MockStoreACPSink> sink_; |
| 138 }; | 139 }; |
| 139 | 140 |
| 140 class TSFTextStoreTestCallback { | 141 class TSFTextStoreTestCallback { |
| 141 public: | 142 public: |
| 142 explicit TSFTextStoreTestCallback(TSFTextStore* text_store) | 143 explicit TSFTextStoreTestCallback(TSFTextStore* text_store) |
| 143 : text_store_(text_store) { | 144 : text_store_(text_store) { |
| 144 CHECK(text_store_); | 145 CHECK(text_store_); |
| 145 } | 146 } |
| 146 virtual ~TSFTextStoreTestCallback() {} | 147 virtual ~TSFTextStoreTestCallback() {} |
| 147 | 148 |
| 148 protected: | 149 protected: |
| 149 // Accessors to the internal state of TSFTextStore. | 150 // Accessors to the internal state of TSFTextStore. |
| 150 bool* edit_flag() { return &text_store_->edit_flag_; } | 151 bool* edit_flag() { return &text_store_->edit_flag_; } |
| 151 string16* string_buffer() { return &text_store_->string_buffer_; } | 152 base::string16* string_buffer() { return &text_store_->string_buffer_; } |
| 152 size_t* committed_size() { return &text_store_->committed_size_; } | 153 size_t* committed_size() { return &text_store_->committed_size_; } |
| 153 gfx::Range* selection() { return &text_store_->selection_; } | 154 gfx::Range* selection() { return &text_store_->selection_; } |
| 154 CompositionUnderlines* composition_undelines() { | 155 CompositionUnderlines* composition_undelines() { |
| 155 return &text_store_->composition_undelines_; | 156 return &text_store_->composition_undelines_; |
| 156 } | 157 } |
| 157 | 158 |
| 158 void SetInternalState(const string16& new_string_buffer, | 159 void SetInternalState(const base::string16& new_string_buffer, |
| 159 LONG new_committed_size, LONG new_selection_start, | 160 LONG new_committed_size, LONG new_selection_start, |
| 160 LONG new_selection_end) { | 161 LONG new_selection_end) { |
| 161 ASSERT_LE(0, new_committed_size); | 162 ASSERT_LE(0, new_committed_size); |
| 162 ASSERT_LE(new_committed_size, new_selection_start); | 163 ASSERT_LE(new_committed_size, new_selection_start); |
| 163 ASSERT_LE(new_selection_start, new_selection_end); | 164 ASSERT_LE(new_selection_start, new_selection_end); |
| 164 ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size())); | 165 ASSERT_LE(new_selection_end, static_cast<LONG>(new_string_buffer.size())); |
| 165 *string_buffer() = new_string_buffer; | 166 *string_buffer() = new_string_buffer; |
| 166 *committed_size() = new_committed_size; | 167 *committed_size() = new_committed_size; |
| 167 selection()->set_start(new_selection_start); | 168 selection()->set_start(new_selection_start); |
| 168 selection()->set_end(new_selection_end); | 169 selection()->set_end(new_selection_end); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 186 selection.acpEnd = acp_end; | 187 selection.acpEnd = acp_end; |
| 187 selection.style.ase = TS_AE_NONE; | 188 selection.style.ase = TS_AE_NONE; |
| 188 selection.style.fInterimChar = 0; | 189 selection.style.fInterimChar = 0; |
| 189 EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection)); | 190 EXPECT_EQ(expected_result, text_store_->SetSelection(1, &selection)); |
| 190 if (expected_result == S_OK) { | 191 if (expected_result == S_OK) { |
| 191 GetSelectionTest(acp_start, acp_end); | 192 GetSelectionTest(acp_start, acp_end); |
| 192 } | 193 } |
| 193 } | 194 } |
| 194 | 195 |
| 195 void SetTextTest(LONG acp_start, LONG acp_end, | 196 void SetTextTest(LONG acp_start, LONG acp_end, |
| 196 const string16& text, HRESULT error_code) { | 197 const base::string16& text, HRESULT error_code) { |
| 197 TS_TEXTCHANGE change = {}; | 198 TS_TEXTCHANGE change = {}; |
| 198 ASSERT_EQ(error_code, | 199 ASSERT_EQ(error_code, |
| 199 text_store_->SetText(0, acp_start, acp_end, | 200 text_store_->SetText(0, acp_start, acp_end, |
| 200 text.c_str(), text.size(), &change)); | 201 text.c_str(), text.size(), &change)); |
| 201 if (error_code == S_OK) { | 202 if (error_code == S_OK) { |
| 202 EXPECT_EQ(acp_start, change.acpStart); | 203 EXPECT_EQ(acp_start, change.acpStart); |
| 203 EXPECT_EQ(acp_end, change.acpOldEnd); | 204 EXPECT_EQ(acp_end, change.acpOldEnd); |
| 204 EXPECT_EQ(acp_start + text.size(), change.acpNewEnd); | 205 EXPECT_EQ(acp_start + text.size(), change.acpNewEnd); |
| 205 } | 206 } |
| 206 } | 207 } |
| 207 | 208 |
| 208 void GetTextTest(LONG acp_start, LONG acp_end, | 209 void GetTextTest(LONG acp_start, LONG acp_end, |
| 209 const string16& expected_string, | 210 const base::string16& expected_string, |
| 210 LONG expected_next_acp) { | 211 LONG expected_next_acp) { |
| 211 wchar_t buffer[1024] = {}; | 212 wchar_t buffer[1024] = {}; |
| 212 ULONG text_buffer_copied = 0; | 213 ULONG text_buffer_copied = 0; |
| 213 TS_RUNINFO run_info = {}; | 214 TS_RUNINFO run_info = {}; |
| 214 ULONG run_info_buffer_copied = 0; | 215 ULONG run_info_buffer_copied = 0; |
| 215 LONG next_acp = 0; | 216 LONG next_acp = 0; |
| 216 ASSERT_EQ(S_OK, | 217 ASSERT_EQ(S_OK, |
| 217 text_store_->GetText(acp_start, acp_end, buffer, 1024, | 218 text_store_->GetText(acp_start, acp_end, buffer, 1024, |
| 218 &text_buffer_copied, | 219 &text_buffer_copied, |
| 219 &run_info, 1, &run_info_buffer_copied, | 220 &run_info, 1, &run_info_buffer_copied, |
| 220 &next_acp)); | 221 &next_acp)); |
| 221 ASSERT_EQ(expected_string.size(), text_buffer_copied); | 222 ASSERT_EQ(expected_string.size(), text_buffer_copied); |
| 222 EXPECT_EQ(expected_string, string16(buffer, buffer + text_buffer_copied)); | 223 EXPECT_EQ(expected_string, |
| 224 base::string16(buffer, buffer + text_buffer_copied)); |
| 223 EXPECT_EQ(1, run_info_buffer_copied); | 225 EXPECT_EQ(1, run_info_buffer_copied); |
| 224 EXPECT_EQ(expected_string.size(), run_info.uCount); | 226 EXPECT_EQ(expected_string.size(), run_info.uCount); |
| 225 EXPECT_EQ(TS_RT_PLAIN, run_info.type); | 227 EXPECT_EQ(TS_RT_PLAIN, run_info.type); |
| 226 EXPECT_EQ(expected_next_acp, next_acp); | 228 EXPECT_EQ(expected_next_acp, next_acp); |
| 227 } | 229 } |
| 228 | 230 |
| 229 void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) { | 231 void GetTextErrorTest(LONG acp_start, LONG acp_end, HRESULT error_code) { |
| 230 wchar_t buffer[1024] = {}; | 232 wchar_t buffer[1024] = {}; |
| 231 ULONG text_buffer_copied = 0; | 233 ULONG text_buffer_copied = 0; |
| 232 TS_RUNINFO run_info = {}; | 234 TS_RUNINFO run_info = {}; |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 EXPECT_TRUE(HasReadWriteLock()); | 543 EXPECT_TRUE(HasReadWriteLock()); |
| 542 | 544 |
| 543 *edit_flag() = true; | 545 *edit_flag() = true; |
| 544 SetInternalState(L"012345", 6, 6, 6); | 546 SetInternalState(L"012345", 6, 6, 6); |
| 545 composition_undelines()->clear(); | 547 composition_undelines()->clear(); |
| 546 | 548 |
| 547 state_ = 2; | 549 state_ = 2; |
| 548 return S_OK; | 550 return S_OK; |
| 549 } | 551 } |
| 550 | 552 |
| 551 void InsertText(const string16& text) { | 553 void InsertText(const base::string16& text) { |
| 552 EXPECT_EQ(2, state_); | 554 EXPECT_EQ(2, state_); |
| 553 EXPECT_EQ(L"012345", text); | 555 EXPECT_EQ(L"012345", text); |
| 554 state_ = 3; | 556 state_ = 3; |
| 555 } | 557 } |
| 556 | 558 |
| 557 void SetCompositionText(const ui::CompositionText& composition) { | 559 void SetCompositionText(const ui::CompositionText& composition) { |
| 558 EXPECT_EQ(3, state_); | 560 EXPECT_EQ(3, state_); |
| 559 EXPECT_EQ(L"", composition.text); | 561 EXPECT_EQ(L"", composition.text); |
| 560 EXPECT_EQ(0, composition.selection.start()); | 562 EXPECT_EQ(0, composition.selection.start()); |
| 561 EXPECT_EQ(0, composition.selection.end()); | 563 EXPECT_EQ(0, composition.selection.end()); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 underline.color = SK_ColorBLACK; | 1052 underline.color = SK_ColorBLACK; |
| 1051 underline.thick = false; | 1053 underline.thick = false; |
| 1052 composition_undelines()->push_back(underline); | 1054 composition_undelines()->push_back(underline); |
| 1053 | 1055 |
| 1054 *edit_flag() = true; | 1056 *edit_flag() = true; |
| 1055 *committed_size() = 3; | 1057 *committed_size() = 3; |
| 1056 | 1058 |
| 1057 return S_OK; | 1059 return S_OK; |
| 1058 } | 1060 } |
| 1059 | 1061 |
| 1060 void InsertText2(const string16& text) { | 1062 void InsertText2(const base::string16& text) { |
| 1061 EXPECT_EQ(L"axy", text); | 1063 EXPECT_EQ(L"axy", text); |
| 1062 } | 1064 } |
| 1063 | 1065 |
| 1064 void SetCompositionText2(const ui::CompositionText& composition) { | 1066 void SetCompositionText2(const ui::CompositionText& composition) { |
| 1065 EXPECT_EQ(L"ZCPc", composition.text); | 1067 EXPECT_EQ(L"ZCPc", composition.text); |
| 1066 EXPECT_EQ(0, composition.selection.start()); | 1068 EXPECT_EQ(0, composition.selection.start()); |
| 1067 EXPECT_EQ(3, composition.selection.end()); | 1069 EXPECT_EQ(3, composition.selection.end()); |
| 1068 ASSERT_EQ(2, composition.underlines.size()); | 1070 ASSERT_EQ(2, composition.underlines.size()); |
| 1069 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color); | 1071 EXPECT_EQ(SK_ColorBLACK, composition.underlines[0].color); |
| 1070 EXPECT_EQ(0, composition.underlines[0].start_offset); | 1072 EXPECT_EQ(0, composition.underlines[0].start_offset); |
| 1071 EXPECT_EQ(2, composition.underlines[0].end_offset); | 1073 EXPECT_EQ(2, composition.underlines[0].end_offset); |
| 1072 EXPECT_TRUE(composition.underlines[0].thick); | 1074 EXPECT_TRUE(composition.underlines[0].thick); |
| 1073 EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color); | 1075 EXPECT_EQ(SK_ColorBLACK, composition.underlines[1].color); |
| 1074 EXPECT_EQ(2, composition.underlines[1].start_offset); | 1076 EXPECT_EQ(2, composition.underlines[1].start_offset); |
| 1075 EXPECT_EQ(4, composition.underlines[1].end_offset); | 1077 EXPECT_EQ(4, composition.underlines[1].end_offset); |
| 1076 EXPECT_FALSE(composition.underlines[1].thick); | 1078 EXPECT_FALSE(composition.underlines[1].thick); |
| 1077 } | 1079 } |
| 1078 | 1080 |
| 1079 HRESULT LockGranted3(DWORD flags) { | 1081 HRESULT LockGranted3(DWORD flags) { |
| 1080 GetTextTest(0, -1, L"axyZCPc", 7); | 1082 GetTextTest(0, -1, L"axyZCPc", 7); |
| 1081 | 1083 |
| 1082 composition_undelines()->clear(); | 1084 composition_undelines()->clear(); |
| 1083 *edit_flag() = true; | 1085 *edit_flag() = true; |
| 1084 *committed_size() = 7; | 1086 *committed_size() = 7; |
| 1085 | 1087 |
| 1086 return S_OK; | 1088 return S_OK; |
| 1087 } | 1089 } |
| 1088 | 1090 |
| 1089 void InsertText3(const string16& text) { | 1091 void InsertText3(const base::string16& text) { |
| 1090 EXPECT_EQ(L"ZCPc", text); | 1092 EXPECT_EQ(L"ZCPc", text); |
| 1091 } | 1093 } |
| 1092 | 1094 |
| 1093 void SetCompositionText3(const ui::CompositionText& composition) { | 1095 void SetCompositionText3(const ui::CompositionText& composition) { |
| 1094 EXPECT_EQ(L"", composition.text); | 1096 EXPECT_EQ(L"", composition.text); |
| 1095 EXPECT_EQ(0, composition.selection.start()); | 1097 EXPECT_EQ(0, composition.selection.start()); |
| 1096 EXPECT_EQ(0, composition.selection.end()); | 1098 EXPECT_EQ(0, composition.selection.end()); |
| 1097 EXPECT_EQ(0, composition.underlines.size()); | 1099 EXPECT_EQ(0, composition.underlines.size()); |
| 1098 } | 1100 } |
| 1099 | 1101 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 text_store_->SetFocusedTextInputClient(NULL, NULL); | 1295 text_store_->SetFocusedTextInputClient(NULL, NULL); |
| 1294 num_copied = 0xfffffff; | 1296 num_copied = 0xfffffff; |
| 1295 TS_ATTRVAL buffer[2] = {}; | 1297 TS_ATTRVAL buffer[2] = {}; |
| 1296 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs( | 1298 EXPECT_HRESULT_FAILED(text_store_->RetrieveRequestedAttrs( |
| 1297 arraysize(buffer), buffer, &num_copied)); | 1299 arraysize(buffer), buffer, &num_copied)); |
| 1298 } | 1300 } |
| 1299 } | 1301 } |
| 1300 | 1302 |
| 1301 } // namespace | 1303 } // namespace |
| 1302 } // namespace ui | 1304 } // namespace ui |
| OLD | NEW |