1 // Copyright 2017 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "fpdfsdk/cba_annotiterator.h"
6 #include "fpdfsdk/cpdfsdk_annot.h"
7 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
8 #include "fpdfsdk/formfiller/cffl_formfiller.h"
9 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
10 #include "fpdfsdk/pwl/cpwl_combo_box.h"
11 #include "fpdfsdk/pwl/cpwl_wnd.h"
12 #include "testing/embedder_test.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 class CPWLComboBoxEditEmbeddertest : public EmbedderTest {
16 protected:
SetUp()17 void SetUp() override {
18 EmbedderTest::SetUp();
19 CreateAndInitializeFormComboboxPDF();
20 }
21
TearDown()22 void TearDown() override {
23 UnloadPage(GetPage());
24 EmbedderTest::TearDown();
25 }
26
CreateAndInitializeFormComboboxPDF()27 void CreateAndInitializeFormComboboxPDF() {
28 EXPECT_TRUE(OpenDocument("combobox_form.pdf"));
29 m_page = LoadPage(0);
30 ASSERT_TRUE(m_page);
31
32 m_pFormFillEnv = static_cast<CPDFSDK_FormFillEnvironment*>(form_handle());
33 CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0),
34 CPDF_Annot::Subtype::WIDGET);
35
36 // User editable combobox.
37 m_pAnnotEditable = iter.GetFirstAnnot();
38 ASSERT_TRUE(m_pAnnotEditable);
39 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotEditable->GetAnnotSubtype());
40
41 // Normal combobox with pre-selected value.
42 m_pAnnotNormal = iter.GetNextAnnot(m_pAnnotEditable);
43 ASSERT_TRUE(m_pAnnotNormal);
44 ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnotNormal->GetAnnotSubtype());
45
46 // Read-only combobox.
47 CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnotNormal);
48 CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot();
49 ASSERT_EQ(pAnnotReadOnly, pLastAnnot);
50 }
51
FormFillerAndWindowSetup(CPDFSDK_Annot * pAnnotCombobox)52 void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotCombobox) {
53 CFFL_InteractiveFormFiller* pInteractiveFormFiller =
54 m_pFormFillEnv->GetInteractiveFormFiller();
55 {
56 CPDFSDK_Annot::ObservedPtr pObserved(pAnnotCombobox);
57 EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0));
58 }
59
60 m_pFormFiller =
61 pInteractiveFormFiller->GetFormFiller(pAnnotCombobox, false);
62 ASSERT_TRUE(m_pFormFiller);
63
64 CPWL_Wnd* pWindow =
65 m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false);
66 ASSERT_TRUE(pWindow);
67 ASSERT_EQ("CPWL_ComboBox", pWindow->GetClassName());
68 m_pComboBox = static_cast<CPWL_ComboBox*>(pWindow);
69 }
70
TypeTextIntoTextField(int num_chars)71 void TypeTextIntoTextField(int num_chars) {
72 // Type text starting with 'A' to as many chars as specified by |num_chars|.
73 for (int i = 0; i < num_chars; ++i) {
74 EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(),
75 i + 'A', 0));
76 }
77 }
78
GetPage() const79 FPDF_PAGE GetPage() const { return m_page; }
GetCPWLComboBox() const80 CPWL_ComboBox* GetCPWLComboBox() const { return m_pComboBox; }
GetCFFLFormFiller() const81 CFFL_FormFiller* GetCFFLFormFiller() const { return m_pFormFiller; }
GetCPDFSDKAnnotNormal() const82 CPDFSDK_Annot* GetCPDFSDKAnnotNormal() const { return m_pAnnotNormal; }
GetCPDFSDKAnnotUserEditable() const83 CPDFSDK_Annot* GetCPDFSDKAnnotUserEditable() const {
84 return m_pAnnotEditable;
85 }
GetCPDFSDKFormFillEnv() const86 CPDFSDK_FormFillEnvironment* GetCPDFSDKFormFillEnv() const {
87 return m_pFormFillEnv;
88 }
89
90 private:
91 FPDF_PAGE m_page;
92 CPWL_ComboBox* m_pComboBox;
93 CFFL_FormFiller* m_pFormFiller;
94 CPDFSDK_Annot* m_pAnnotNormal;
95 CPDFSDK_Annot* m_pAnnotEditable;
96 CPDFSDK_FormFillEnvironment* m_pFormFillEnv;
97 };
98
TEST_F(CPWLComboBoxEditEmbeddertest,GetSelectedTextEmptyAndBasicNormal)99 TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicNormal) {
100 FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
101
102 // Automatically pre-filled with "Banana".
103 EXPECT_FALSE(GetCPWLComboBox()->GetText().IsEmpty());
104 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
105
106 // Check that selection is intially empty, then select entire word.
107 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
108 GetCPWLComboBox()->SetSelectText();
109 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
110
111 // Select other options.
112 GetCPWLComboBox()->SetSelect(0);
113 EXPECT_STREQ(L"Apple", GetCPWLComboBox()->GetSelectedText().c_str());
114 GetCPWLComboBox()->SetSelect(2);
115 EXPECT_STREQ(L"Cherry", GetCPWLComboBox()->GetSelectedText().c_str());
116
117 // Verify that combobox text cannot be edited.
118 EXPECT_FALSE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotNormal(), 'a', 0));
119 }
120
TEST_F(CPWLComboBoxEditEmbeddertest,GetSelectedTextFragmentsNormal)121 TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsNormal) {
122 FormFillerAndWindowSetup(GetCPDFSDKAnnotNormal());
123 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetText().c_str());
124
125 GetCPWLComboBox()->SetEditSelection(0, 0);
126 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
127
128 GetCPWLComboBox()->SetEditSelection(0, 1);
129 EXPECT_STREQ(L"B", GetCPWLComboBox()->GetSelectedText().c_str());
130
131 GetCPWLComboBox()->SetEditSelection(0, -1);
132 EXPECT_STREQ(L"Banana", GetCPWLComboBox()->GetSelectedText().c_str());
133
134 GetCPWLComboBox()->SetEditSelection(-8, -1);
135 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
136
137 GetCPWLComboBox()->SetEditSelection(4, 1);
138 EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
139
140 GetCPWLComboBox()->SetEditSelection(1, 4);
141 EXPECT_STREQ(L"ana", GetCPWLComboBox()->GetSelectedText().c_str());
142
143 GetCPWLComboBox()->SetEditSelection(5, 6);
144 EXPECT_STREQ(L"a", GetCPWLComboBox()->GetSelectedText().c_str());
145 }
146
TEST_F(CPWLComboBoxEditEmbeddertest,GetSelectedTextEmptyAndBasicEditable)147 TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextEmptyAndBasicEditable) {
148 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
149 EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
150
151 // Check selection is intially empty, then select a provided option.
152 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
153 GetCPWLComboBox()->SetSelect(0);
154 GetCPWLComboBox()->SetSelectText();
155 EXPECT_STREQ(L"Foo", GetCPWLComboBox()->GetSelectedText().c_str());
156
157 // Select another option and then select last char of that option.
158 GetCPWLComboBox()->SetSelect(1);
159 EXPECT_STREQ(L"Bar", GetCPWLComboBox()->GetSelectedText().c_str());
160 GetCPWLComboBox()->SetEditSelection(2, 3);
161 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
162
163 // Type into editable combobox text field and select new text.
164 EXPECT_TRUE(
165 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'a', 0));
166 EXPECT_TRUE(
167 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'b', 0));
168 EXPECT_TRUE(
169 GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnotUserEditable(), 'c', 0));
170
171 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
172 GetCPWLComboBox()->SetEditSelection(0, 5);
173 EXPECT_STREQ(L"Baabc", GetCPWLComboBox()->GetSelectedText().c_str());
174 }
175
TEST_F(CPWLComboBoxEditEmbeddertest,GetSelectedTextFragmentsEditable)176 TEST_F(CPWLComboBoxEditEmbeddertest, GetSelectedTextFragmentsEditable) {
177 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
178 TypeTextIntoTextField(50);
179
180 GetCPWLComboBox()->SetEditSelection(0, 0);
181 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
182
183 GetCPWLComboBox()->SetEditSelection(0, 1);
184 EXPECT_STREQ(L"A", GetCPWLComboBox()->GetSelectedText().c_str());
185
186 GetCPWLComboBox()->SetEditSelection(0, -1);
187 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
188 GetCPWLComboBox()->GetSelectedText().c_str());
189
190 GetCPWLComboBox()->SetEditSelection(-8, -1);
191 EXPECT_TRUE(GetCPWLComboBox()->GetSelectedText().IsEmpty());
192
193 GetCPWLComboBox()->SetEditSelection(23, 12);
194 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
195
196 GetCPWLComboBox()->SetEditSelection(12, 23);
197 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
198
199 GetCPWLComboBox()->SetEditSelection(49, 50);
200 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
201
202 GetCPWLComboBox()->SetEditSelection(49, 55);
203 EXPECT_STREQ(L"r", GetCPWLComboBox()->GetSelectedText().c_str());
204 }
205
TEST_F(CPWLComboBoxEditEmbeddertest,DeleteEntireTextSelection)206 TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) {
207 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
208 TypeTextIntoTextField(50);
209
210 GetCPWLComboBox()->SetEditSelection(0, -1);
211 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
212 GetCPWLComboBox()->GetSelectedText().c_str());
213
214 GetCPWLComboBox()->ReplaceSelection(L"");
215 EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty());
216 }
217
TEST_F(CPWLComboBoxEditEmbeddertest,DeleteTextSelectionMiddle)218 TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) {
219 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
220 TypeTextIntoTextField(50);
221
222 GetCPWLComboBox()->SetEditSelection(12, 23);
223 EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str());
224
225 GetCPWLComboBox()->ReplaceSelection(L"");
226 EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr",
227 GetCPWLComboBox()->GetText().c_str());
228 }
229
TEST_F(CPWLComboBoxEditEmbeddertest,DeleteTextSelectionLeft)230 TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) {
231 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
232 TypeTextIntoTextField(50);
233
234 GetCPWLComboBox()->SetEditSelection(0, 5);
235 EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
236
237 GetCPWLComboBox()->ReplaceSelection(L"");
238 EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
239 GetCPWLComboBox()->GetText().c_str());
240 }
241
TEST_F(CPWLComboBoxEditEmbeddertest,DeleteTextSelectionRight)242 TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) {
243 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
244 TypeTextIntoTextField(50);
245
246 GetCPWLComboBox()->SetEditSelection(45, 50);
247 EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str());
248
249 GetCPWLComboBox()->ReplaceSelection(L"");
250 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm",
251 GetCPWLComboBox()->GetText().c_str());
252 }
253
TEST_F(CPWLComboBoxEditEmbeddertest,DeleteEmptyTextSelection)254 TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) {
255 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
256 TypeTextIntoTextField(50);
257
258 GetCPWLComboBox()->ReplaceSelection(L"");
259 EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr",
260 GetCPWLComboBox()->GetText().c_str());
261 }
262
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextInEmptyEditableComboBox)263 TEST_F(CPWLComboBoxEditEmbeddertest, InsertTextInEmptyEditableComboBox) {
264 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
265 GetCPWLComboBox()->ReplaceSelection(L"Hello");
266 EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
267 }
268
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextInPopulatedEditableComboBoxLeft)269 TEST_F(CPWLComboBoxEditEmbeddertest,
270 InsertTextInPopulatedEditableComboBoxLeft) {
271 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
272 TypeTextIntoTextField(10);
273
274 // Move cursor to beginning of user-editable combobox text field.
275 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(),
276 FWL_VKEY_Home, 0));
277
278 GetCPWLComboBox()->ReplaceSelection(L"Hello");
279 EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLComboBox()->GetText().c_str());
280 }
281
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextInPopulatedEditableComboBoxMiddle)282 TEST_F(CPWLComboBoxEditEmbeddertest,
283 InsertTextInPopulatedEditableComboBoxMiddle) {
284 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
285 TypeTextIntoTextField(10);
286
287 // Move cursor to middle of user-editable combobox text field.
288 for (int i = 0; i < 5; ++i) {
289 EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(),
290 FWL_VKEY_Left, 0));
291 }
292
293 GetCPWLComboBox()->ReplaceSelection(L"Hello");
294 EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
295 }
296
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextInPopulatedEditableComboBoxRight)297 TEST_F(CPWLComboBoxEditEmbeddertest,
298 InsertTextInPopulatedEditableComboBoxRight) {
299 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
300 TypeTextIntoTextField(10);
301
302 GetCPWLComboBox()->ReplaceSelection(L"Hello");
303 EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLComboBox()->GetText().c_str());
304 }
305
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole)306 TEST_F(CPWLComboBoxEditEmbeddertest,
307 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) {
308 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
309 TypeTextIntoTextField(10);
310
311 GetCPWLComboBox()->SetEditSelection(0, -1);
312 EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
313 GetCPWLComboBox()->ReplaceSelection(L"Hello");
314 EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str());
315 }
316
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft)317 TEST_F(CPWLComboBoxEditEmbeddertest,
318 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) {
319 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
320 TypeTextIntoTextField(10);
321
322 GetCPWLComboBox()->SetEditSelection(0, 5);
323 EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str());
324 GetCPWLComboBox()->ReplaceSelection(L"Hello");
325 EXPECT_STREQ(L"HelloFGHIJ", GetCPWLComboBox()->GetText().c_str());
326 }
327
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle)328 TEST_F(CPWLComboBoxEditEmbeddertest,
329 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) {
330 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
331 TypeTextIntoTextField(10);
332
333 GetCPWLComboBox()->SetEditSelection(2, 7);
334 EXPECT_STREQ(L"CDEFG", GetCPWLComboBox()->GetSelectedText().c_str());
335 GetCPWLComboBox()->ReplaceSelection(L"Hello");
336 EXPECT_STREQ(L"ABHelloHIJ", GetCPWLComboBox()->GetText().c_str());
337 }
338
TEST_F(CPWLComboBoxEditEmbeddertest,InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight)339 TEST_F(CPWLComboBoxEditEmbeddertest,
340 InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) {
341 FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable());
342 TypeTextIntoTextField(10);
343
344 GetCPWLComboBox()->SetEditSelection(5, 10);
345 EXPECT_STREQ(L"FGHIJ", GetCPWLComboBox()->GetSelectedText().c_str());
346 GetCPWLComboBox()->ReplaceSelection(L"Hello");
347 EXPECT_STREQ(L"ABCDEHello", GetCPWLComboBox()->GetText().c_str());
348 }
349