From ab3909796cf2e9fa192040bcd7cb9da7bb3328a5 Mon Sep 17 00:00:00 2001 From: Diana Gage Date: Fri, 28 Jul 2017 17:07:39 -0700 Subject: Add FORM_ReplaceSelection() and embedder tests. This method replaces the selected text in a user-editable form text area with another text string (which can be empty or non-empty). If there is no selected text, FORM_ReplaceSelection() will append the replacement text after the current caret position. BUG=chromium:59266 Change-Id: I76448ef757d107888c33ebd5656457ebac93b952 Reviewed-on: https://pdfium-review.googlesource.com/8812 Reviewed-by: Lei Zhang Commit-Queue: Diana Gage --- fpdfsdk/cpdfsdk_annothandlermgr.cpp | 6 +- fpdfsdk/cpdfsdk_annothandlermgr.h | 3 +- fpdfsdk/cpdfsdk_baannothandler.cpp | 3 +- fpdfsdk/cpdfsdk_baannothandler.h | 3 +- fpdfsdk/cpdfsdk_pageview.cpp | 4 +- fpdfsdk/cpdfsdk_pageview.h | 2 +- fpdfsdk/cpdfsdk_widgethandler.cpp | 5 +- fpdfsdk/cpdfsdk_widgethandler.h | 3 +- fpdfsdk/cpdfsdk_xfawidgethandler.cpp | 7 +- fpdfsdk/cpdfsdk_xfawidgethandler.h | 3 +- fpdfsdk/formfiller/cffl_formfiller.cpp | 5 +- fpdfsdk/formfiller/cffl_formfiller.h | 2 +- fpdfsdk/formfiller/cffl_interactiveformfiller.cpp | 5 +- fpdfsdk/formfiller/cffl_interactiveformfiller.h | 2 +- fpdfsdk/fpdfformfill.cpp | 11 +- fpdfsdk/fpdfformfill_embeddertest.cpp | 647 +++++++++++++++++++++- fpdfsdk/fpdfview_c_api_test.c | 2 +- fpdfsdk/ipdfsdk_annothandler.h | 3 +- fpdfsdk/pwl/cpwl_combo_box.cpp | 4 +- fpdfsdk/pwl/cpwl_combo_box.h | 2 +- fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp | 97 +++- fpdfsdk/pwl/cpwl_edit_ctrl.cpp | 9 +- fpdfsdk/pwl/cpwl_edit_ctrl.h | 2 +- fpdfsdk/pwl/cpwl_edit_embeddertest.cpp | 232 +++++++- fpdfsdk/pwl/cpwl_wnd.cpp | 2 +- fpdfsdk/pwl/cpwl_wnd.h | 2 +- public/fpdf_formfill.h | 16 +- testing/resources/text_form_multiple.in | 16 +- testing/resources/text_form_multiple.pdf | 39 +- 29 files changed, 1044 insertions(+), 93 deletions(-) diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp index fd77a73460..a1ac14cc69 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp +++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp @@ -81,8 +81,10 @@ CFX_WideString CPDFSDK_AnnotHandlerMgr::Annot_GetSelectedText( return GetAnnotHandler(pAnnot)->GetSelectedText(pAnnot); } -void CPDFSDK_AnnotHandlerMgr::Annot_DeleteSelectedText(CPDFSDK_Annot* pAnnot) { - GetAnnotHandler(pAnnot)->DeleteSelectedText(pAnnot); +void CPDFSDK_AnnotHandlerMgr::Annot_ReplaceSelection( + CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) { + GetAnnotHandler(pAnnot)->ReplaceSelection(pAnnot, text); } IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler( diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h index 93c552bbfb..96765e5ef1 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.h +++ b/fpdfsdk/cpdfsdk_annothandlermgr.h @@ -44,7 +44,8 @@ class CPDFSDK_AnnotHandlerMgr { void Annot_OnLoad(CPDFSDK_Annot* pAnnot); CFX_WideString Annot_GetSelectedText(CPDFSDK_Annot* pAnnot); - void Annot_DeleteSelectedText(CPDFSDK_Annot* pAnnot); + void Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text); IPDFSDK_AnnotHandler* GetAnnotHandler(CPDFSDK_Annot* pAnnot) const; void Annot_OnDraw(CPDFSDK_PageView* pPageView, diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp index cf09d2bbcb..029df85bd7 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.cpp +++ b/fpdfsdk/cpdfsdk_baannothandler.cpp @@ -197,7 +197,8 @@ CFX_WideString CPDFSDK_BAAnnotHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { return CFX_WideString(); } -void CPDFSDK_BAAnnotHandler::DeleteSelectedText(CPDFSDK_Annot* pAnnot) {} +void CPDFSDK_BAAnnotHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) {} bool CPDFSDK_BAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h index 7db9a4d7d7..86f7b937e8 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.h +++ b/fpdfsdk/cpdfsdk_baannothandler.h @@ -38,7 +38,8 @@ class CPDFSDK_BAAnnotHandler : public IPDFSDK_AnnotHandler { CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; - void DeleteSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp index 84a60fa42f..209e8de482 100644 --- a/fpdfsdk/cpdfsdk_pageview.cpp +++ b/fpdfsdk/cpdfsdk_pageview.cpp @@ -253,11 +253,11 @@ CFX_WideString CPDFSDK_PageView::GetSelectedText() { return CFX_WideString(); } -void CPDFSDK_PageView::DeleteSelectedText() { +void CPDFSDK_PageView::ReplaceSelection(const CFX_WideString& text) { if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = m_pFormFillEnv->GetAnnotHandlerMgr(); - pAnnotHandlerMgr->Annot_DeleteSelectedText(pAnnot); + pAnnotHandlerMgr->Annot_ReplaceSelection(pAnnot, text); } } diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h index d4b7721575..c525bfc457 100644 --- a/fpdfsdk/cpdfsdk_pageview.h +++ b/fpdfsdk/cpdfsdk_pageview.h @@ -61,7 +61,7 @@ class CPDFSDK_PageView final : public CPDF_Page::View { } CFX_WideString GetSelectedText(); - void DeleteSelectedText(); + void ReplaceSelection(const CFX_WideString& text); bool OnLButtonDown(const CFX_PointF& point, uint32_t nFlag); bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag); diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp index 1c802a3ba7..f5cd802001 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.cpp +++ b/fpdfsdk/cpdfsdk_widgethandler.cpp @@ -287,9 +287,10 @@ CFX_WideString CPDFSDK_WidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { return CFX_WideString(); } -void CPDFSDK_WidgetHandler::DeleteSelectedText(CPDFSDK_Annot* pAnnot) { +void CPDFSDK_WidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) { if (!pAnnot->IsSignatureWidget() && m_pFormFiller) - m_pFormFiller->DeleteSelectedText(pAnnot); + m_pFormFiller->ReplaceSelection(pAnnot, text); } bool CPDFSDK_WidgetHandler::HitTest(CPDFSDK_PageView* pPageView, diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h index 2d33ff5686..60bfd834a2 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.h +++ b/fpdfsdk/cpdfsdk_widgethandler.h @@ -39,7 +39,8 @@ class CPDFSDK_WidgetHandler : public IPDFSDK_AnnotHandler { CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; - void DeleteSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp index 746d1ca763..e7bf702966 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp @@ -97,16 +97,17 @@ CFX_FloatRect CPDFSDK_XFAWidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView, return rcWidget; } -// TODO(crbug.com/62400): Implement so selected text can be obtained from XFA +// TODO(bug 840): Implement so selected text can be obtained from XFA // fields. CFX_WideString CPDFSDK_XFAWidgetHandler::GetSelectedText( CPDFSDK_Annot* pAnnot) { return CFX_WideString(); } -// TODO(crbug.com/62400): Implement so selected text can be deleted from XFA +// TODO(bug 840): Implement so text can be inserted into and deleted from XFA // fields. -void CPDFSDK_XFAWidgetHandler::DeleteSelectedText(CPDFSDK_Annot* pAnnot) {} +void CPDFSDK_XFAWidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) {} bool CPDFSDK_XFAWidgetHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.h b/fpdfsdk/cpdfsdk_xfawidgethandler.h index 3d06948116..26e991d6ed 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.h +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.h @@ -34,7 +34,8 @@ class CPDFSDK_XFAWidgetHandler : public IPDFSDK_AnnotHandler { CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) override; CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; - void DeleteSelectedText(CPDFSDK_Annot* pAnnot) override; + void ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) override; bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) override; diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp index a37a7501d0..e0af8955ac 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.cpp +++ b/fpdfsdk/formfiller/cffl_formfiller.cpp @@ -245,7 +245,8 @@ CFX_WideString CFFL_FormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) { return pWnd ? pWnd->GetSelectedText() : CFX_WideString(); } -void CFFL_FormFiller::DeleteSelectedText(CPDFSDK_Annot* pAnnot) { +void CFFL_FormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) { if (!IsValid()) return; @@ -256,7 +257,7 @@ void CFFL_FormFiller::DeleteSelectedText(CPDFSDK_Annot* pAnnot) { if (!pWnd) return; - pWnd->DeleteSelectedText(); + pWnd->ReplaceSelection(text); } void CFFL_FormFiller::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h index 96b7a69b29..4769716be5 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.h +++ b/fpdfsdk/formfiller/cffl_formfiller.h @@ -75,7 +75,7 @@ class CFFL_FormFiller : public IPWL_Provider, public CPWL_TimerHandler { virtual bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags); CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot); - void DeleteSelectedText(CPDFSDK_Annot* pAnnot); + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const CFX_WideString& text); void SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag); void KillFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag); diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp index 24bfd3c3b2..6d250408f0 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp @@ -523,13 +523,14 @@ CFX_WideString CFFL_InteractiveFormFiller::GetSelectedText( return pFormFiller ? pFormFiller->GetSelectedText(pAnnot) : CFX_WideString(); } -void CFFL_InteractiveFormFiller::DeleteSelectedText(CPDFSDK_Annot* pAnnot) { +void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) { ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); if (!pFormFiller) return; - pFormFiller->DeleteSelectedText(pAnnot); + pFormFiller->ReplaceSelection(pAnnot, text); } void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) { diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h index 17e9407924..b71f3a6ef7 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h @@ -84,7 +84,7 @@ class CFFL_InteractiveFormFiller : public IPWL_Filler_Notify { void RemoveFormFiller(CPDFSDK_Annot* pAnnot); CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot); - void DeleteSelectedText(CPDFSDK_Annot* pAnnot); + void ReplaceSelection(CPDFSDK_Annot* pAnnot, const CFX_WideString& text); static bool IsVisible(CPDFSDK_Widget* pWidget); static bool IsReadOnly(CPDFSDK_Widget* pWidget); diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp index e541b81cc3..7f4e3dfd69 100644 --- a/fpdfsdk/fpdfformfill.cpp +++ b/fpdfsdk/fpdfformfill.cpp @@ -383,12 +383,17 @@ DLLEXPORT unsigned long STDCALL FORM_GetSelectedText(FPDF_FORMHANDLE hHandle, return form_text_len; } -DLLEXPORT void STDCALL FORM_DeleteSelectedText(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page) { +DLLEXPORT void STDCALL FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + FPDF_WIDESTRING wsText) { CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); if (!pPageView) return; - pPageView->DeleteSelectedText(); + + FX_STRSIZE len = CFX_WideString::WStringLength(wsText); + CFX_WideString wide_str_text = CFX_WideString::FromUTF16LE(wsText, len); + + pPageView->ReplaceSelection(wide_str_text); } DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { diff --git a/fpdfsdk/fpdfformfill_embeddertest.cpp b/fpdfsdk/fpdfformfill_embeddertest.cpp index 1505fdc390..13d5f08d56 100644 --- a/fpdfsdk/fpdfformfill_embeddertest.cpp +++ b/fpdfsdk/fpdfformfill_embeddertest.cpp @@ -656,7 +656,8 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteTextFieldEntireSelection) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); + SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 191.0, 115.5); CheckSelection(page, CFX_WideString()); @@ -676,7 +677,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteTextFieldSelectionMiddle) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 191.0, 115.5); CheckSelection(page, CFX_WideString(L"ABCJKL")); @@ -696,7 +697,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteTextFieldSelectionLeft) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 191.0, 115.5); CheckSelection(page, CFX_WideString(L"EFGHIJKL")); @@ -716,7 +717,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteTextFieldSelectionRight) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 191.0, 115.5); CheckSelection(page, CFX_WideString(L"ABCDEFGH")); @@ -734,7 +735,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEmptyTextFieldSelection) { CheckSelection(page, CFX_WideString()); // Test that attempt to delete empty text selection has no effect. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 191.0, 115.5); CheckSelection(page, CFX_WideString(L"ABCDEFGHIJKL")); @@ -754,7 +755,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEditableComboBoxEntireSelection) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithMouse(page, 178.0, 102.0, 62.0); CheckSelection(page, CFX_WideString()); @@ -774,7 +775,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEditableComboBoxSelectionMiddle) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithMouse(page, 178.0, 102.0, 62.0); CheckSelection(page, CFX_WideString(L"ABCIJ")); @@ -794,7 +795,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEditableComboBoxSelectionLeft) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithMouse(page, 178.0, 102.0, 62.0); CheckSelection(page, CFX_WideString(L"EFGHIJ")); @@ -814,7 +815,7 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEditableComboBoxSelectionRight) { // Test deleting current text selection. Select what remains after deletion to // check that remaining text is as expected. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithMouse(page, 178.0, 102.0, 62.0); CheckSelection(page, CFX_WideString(L"ABCDEF")); @@ -832,9 +833,635 @@ TEST_F(FPDFFormFillEmbeddertest, DeleteEmptyEditableComboBoxSelection) { CheckSelection(page, CFX_WideString()); // Test that attempt to delete empty text selection has no effect. - FORM_DeleteSelectedText(form_handle(), page); + FORM_ReplaceSelection(form_handle(), page, nullptr); SelectTextWithMouse(page, 178.0, 102.0, 62.0); CheckSelection(page, CFX_WideString(L"ABCDEFGHIJ")); UnloadPage(page); } + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInEmptyTextField) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + ClickOnFormFieldAtPoint(page, 120.0, 120.0); + + // Test inserting text into empty text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"Hello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedTextFieldLeft) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 8, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Click on the leftmost part of the text field. + ClickOnFormFieldAtPoint(page, 102.0, 115.5); + + // Test inserting text in front of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"HelloABCDEFGH")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedTextFieldMiddle) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 8, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Click on the middle of the text field. + ClickOnFormFieldAtPoint(page, 134.0, 115.5); + + // Test inserting text in the middle of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"ABCDHelloEFGH")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedTextFieldRight) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 8, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Click on the rightmost part of the text field. + ClickOnFormFieldAtPoint(page, 166.0, 115.5); + + // Test inserting text behind existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"ABCDEFGHHello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select entire string in text field. + SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 195.0, 115.0); + CheckSelection(page, CFX_WideString(L"ABCDEFGHIJKL")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"Hello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select left portion of string in text field. + SelectTextWithKeyboard(page, 6, FWL_VKEY_Left, 148.0, 115.0); + CheckSelection(page, CFX_WideString(L"ABCDEF")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"HelloGHIJKL")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select middle portion of string in text field. + SelectTextWithKeyboard(page, 6, FWL_VKEY_Left, 171.0, 115.0); + CheckSelection(page, CFX_WideString(L"DEFGHI")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"ABCHelloJKL")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldRight) { + // Open file with form text field. + EXPECT_TRUE(OpenDocument("text_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select right portion of string in text field. + SelectTextWithKeyboard(page, 6, FWL_VKEY_Left, 195.0, 115.0); + CheckSelection(page, CFX_WideString(L"GHIJKL")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 115.5); + CheckSelection(page, CFX_WideString(L"ABCDEFHello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInEmptyEditableComboBox) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + ClickOnFormFieldAtPoint(page, 102.0, 62.0); + + // Test inserting text into empty user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"Hello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedEditableComboBoxLeft) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 6, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Click on the leftmost part of the user-editable combobox. + ClickOnFormFieldAtPoint(page, 102.0, 62.0); + + // Test inserting text in front of existing text in user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"HelloABCDEF")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedEditableComboBoxMiddle) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 6, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Click on the middle of the user-editable combobox. + ClickOnFormFieldAtPoint(page, 126.0, 62.0); + + // Test inserting text in the middle of existing text in user-editable + // combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCHelloDEF")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedEditableComboBoxRight) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 6, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Click on the rightmost part of the user-editable combobox. + ClickOnFormFieldAtPoint(page, 150.0, 62.0); + + // Test inserting text behind existing text in user-editable combobox. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCDEFHello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 10, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Select entire string in user-editable combobox. + SelectTextWithKeyboard(page, 10, FWL_VKEY_Left, 183.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCDEFGHIJ")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"Hello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 10, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Select left portion of string in user-editable combobox. + SelectTextWithKeyboard(page, 5, FWL_VKEY_Left, 142.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCDE")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"HelloFGHIJ")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 10, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Select middle portion of string in user-editable combobox. + SelectTextWithKeyboard(page, 5, FWL_VKEY_Left, 167.0, 62.0); + CheckSelection(page, CFX_WideString(L"DEFGH")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCHelloIJ")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) { + // Open file with form comboboxes. + EXPECT_TRUE(OpenDocument("combobox_form.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 10, FPDF_FORMFIELD_COMBOBOX, 102.0, 62.0); + + // Select right portion of string in user-editable combobox. + SelectTextWithKeyboard(page, 5, FWL_VKEY_Left, 183.0, 62.0); + CheckSelection(page, CFX_WideString(L"FGHIJ")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hello"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of user-editable combobox text field to check that + // insertion worked as expected. + SelectTextWithMouse(page, 183.0, 102.0, 62.0); + CheckSelection(page, CFX_WideString(L"ABCDEHello")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInEmptyCharLimitTextFieldOverflow) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Click on the textfield. + ClickOnFormFieldAtPoint(page, 195.0, 60.0); + + // Delete pre-filled contents of text field with char limit. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Elephant")); + FORM_ReplaceSelection(form_handle(), page, nullptr); + + // Test inserting text into now empty text field so text to be inserted + // exceeds the char limit and is cut off. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Hippopotam")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInEmptyCharLimitTextFieldFit) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Click on the textfield. + ClickOnFormFieldAtPoint(page, 195.0, 60.0); + + // Delete pre-filled contents of text field with char limit. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Elephant")); + FORM_ReplaceSelection(form_handle(), page, nullptr); + + // Test inserting text into now empty text field so text to be inserted + // exceeds the char limit and is cut off. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Zebra"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Zebra")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedCharLimitTextFieldLeft) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + // Click on the leftmost part of the text field. + ClickOnFormFieldAtPoint(page, 102.0, 60.0); + + // Test inserting text in front of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"HiElephant")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextInPopulatedCharLimitTextFieldMiddle) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 8, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Click on the middle of the text field. + ClickOnFormFieldAtPoint(page, 134.0, 60.0); + + // Test inserting text in the middle of existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"ElephHiant")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, InsertTextInPopulatedCharLimitTextFieldRight) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 8, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Click on the rightmost part of the text field. + ClickOnFormFieldAtPoint(page, 166.0, 60.0); + + // Test inserting text behind existing text in text field. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"ElephantHi")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select entire string in text field. + SelectTextWithKeyboard(page, 12, FWL_VKEY_Left, 195.0, 60.0); + CheckSelection(page, CFX_WideString(L"Elephant")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Hippopotam")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select left portion of string in text field. + SelectTextWithKeyboard(page, 4, FWL_VKEY_Left, 122.0, 60.0); + CheckSelection(page, CFX_WideString(L"Elep")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"Hippophant")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select middle portion of string in text field. + SelectTextWithKeyboard(page, 4, FWL_VKEY_Left, 136.0, 60.0); + CheckSelection(page, CFX_WideString(L"epha")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"ElHippopnt")); + + UnloadPage(page); +} + +TEST_F(FPDFFormFillEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) { + // Open file with form text field with a character limit of 10. + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + TypeTextIntoTextField(page, 12, FPDF_FORMFIELD_TEXTFIELD, 120.0, 120.0); + + // Select right portion of string in text field. + SelectTextWithKeyboard(page, 4, FWL_VKEY_Left, 152.0, 60.0); + CheckSelection(page, CFX_WideString(L"hant")); + + // Test replacing text selection with text to be inserted. + std::unique_ptr text_to_insert = + GetFPDFWideString(L"Hippopotamus"); + FORM_ReplaceSelection(form_handle(), page, text_to_insert.get()); + + // Select entire contents of text field to check that insertion worked + // as expected. + SelectTextWithMouse(page, 195.0, 102.0, 60.0); + CheckSelection(page, CFX_WideString(L"ElepHippop")); + + UnloadPage(page); +} diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c index 95a0175999..7d42be8792 100644 --- a/fpdfsdk/fpdfview_c_api_test.c +++ b/fpdfsdk/fpdfview_c_api_test.c @@ -182,7 +182,7 @@ int CheckPDFiumCApi() { CHK(FORM_OnKeyUp); CHK(FORM_OnChar); CHK(FORM_GetSelectedText); - CHK(FORM_DeleteSelectedText); + CHK(FORM_ReplaceSelection); CHK(FORM_ForceToKillFocus); CHK(FPDFPage_HasFormFieldAtPoint); CHK(FPDFPage_FormFieldZOrderAtPoint); diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h index 5340978308..3a35cdc8ff 100644 --- a/fpdfsdk/ipdfsdk_annothandler.h +++ b/fpdfsdk/ipdfsdk_annothandler.h @@ -37,7 +37,8 @@ class IPDFSDK_AnnotHandler { virtual CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot) = 0; virtual CFX_WideString GetSelectedText(CPDFSDK_Annot* pAnnot) = 0; - virtual void DeleteSelectedText(CPDFSDK_Annot* pAnnot) = 0; + virtual void ReplaceSelection(CPDFSDK_Annot* pAnnot, + const CFX_WideString& text) = 0; virtual bool HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) = 0; diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp index 9514e55646..49254b8171 100644 --- a/fpdfsdk/pwl/cpwl_combo_box.cpp +++ b/fpdfsdk/pwl/cpwl_combo_box.cpp @@ -184,9 +184,9 @@ CFX_WideString CPWL_ComboBox::GetSelectedText() { return CFX_WideString(); } -void CPWL_ComboBox::DeleteSelectedText() { +void CPWL_ComboBox::ReplaceSelection(const CFX_WideString& text) { if (m_pEdit) - m_pEdit->DeleteSelectedText(); + m_pEdit->ReplaceSelection(text); } CFX_WideString CPWL_ComboBox::GetText() const { diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h index a50c4cee37..81e4256e18 100644 --- a/fpdfsdk/pwl/cpwl_combo_box.h +++ b/fpdfsdk/pwl/cpwl_combo_box.h @@ -63,7 +63,7 @@ class CPWL_ComboBox : public CPWL_Wnd { void SetFocus() override; void KillFocus() override; CFX_WideString GetSelectedText() override; - void DeleteSelectedText() override; + void ReplaceSelection(const CFX_WideString& text) override; void SetFillerNotify(IPWL_Filler_Notify* pNotify); diff --git a/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp index 30fe32bc53..308ee4ac40 100644 --- a/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp +++ b/fpdfsdk/pwl/cpwl_combo_box_embeddertest.cpp @@ -211,7 +211,7 @@ TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEntireTextSelection) { EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLComboBox()->GetSelectedText().c_str()); - GetCPWLComboBox()->DeleteSelectedText(); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString()); EXPECT_TRUE(GetCPWLComboBox()->GetText().IsEmpty()); } @@ -222,7 +222,7 @@ TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionMiddle) { GetCPWLComboBox()->SetEditSelection(12, 23); EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLComboBox()->GetSelectedText().c_str()); - GetCPWLComboBox()->DeleteSelectedText(); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLComboBox()->GetText().c_str()); } @@ -234,7 +234,7 @@ TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionLeft) { GetCPWLComboBox()->SetEditSelection(0, 5); EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); - GetCPWLComboBox()->DeleteSelectedText(); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLComboBox()->GetText().c_str()); } @@ -246,7 +246,7 @@ TEST_F(CPWLComboBoxEditEmbeddertest, DeleteTextSelectionRight) { GetCPWLComboBox()->SetEditSelection(45, 50); EXPECT_STREQ(L"nopqr", GetCPWLComboBox()->GetSelectedText().c_str()); - GetCPWLComboBox()->DeleteSelectedText(); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", GetCPWLComboBox()->GetText().c_str()); } @@ -255,7 +255,94 @@ TEST_F(CPWLComboBoxEditEmbeddertest, DeleteEmptyTextSelection) { FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); TypeTextIntoTextField(50); - GetCPWLComboBox()->DeleteSelectedText(); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLComboBox()->GetText().c_str()); } + +TEST_F(CPWLComboBoxEditEmbeddertest, InsertTextInEmptyEditableComboBox) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + // Move cursor to beginning of user-editable combobox text field. + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(), + FWL_VKEY_Home, 0)); + + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + // Move cursor to middle of user-editable combobox text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotUserEditable(), + FWL_VKEY_Left, 0)); + } + + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextInPopulatedEditableComboBoxRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"Hello", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"HelloFGHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(2, 7); + EXPECT_STREQ(L"CDEFG", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABHelloHIJ", GetCPWLComboBox()->GetText().c_str()); +} + +TEST_F(CPWLComboBoxEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedEditableComboBoxRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotUserEditable()); + TypeTextIntoTextField(10); + + GetCPWLComboBox()->SetEditSelection(5, 10); + EXPECT_STREQ(L"FGHIJ", GetCPWLComboBox()->GetSelectedText().c_str()); + GetCPWLComboBox()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEHello", GetCPWLComboBox()->GetText().c_str()); +} diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp index a852cb6231..1a7b0e4c49 100644 --- a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp @@ -59,9 +59,12 @@ CFX_WideString CPWL_EditCtrl::GetSelectedText() { return CFX_WideString(); } -void CPWL_EditCtrl::DeleteSelectedText() { - if (m_pEdit) - m_pEdit->ClearSelection(); +void CPWL_EditCtrl::ReplaceSelection(const CFX_WideString& text) { + if (!m_pEdit) + return; + + m_pEdit->ClearSelection(); + m_pEdit->InsertText(text, FX_CHARSET_Default); } void CPWL_EditCtrl::RePosChildWnd() { diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.h b/fpdfsdk/pwl/cpwl_edit_ctrl.h index 4fb86fab62..03dc4be1e1 100644 --- a/fpdfsdk/pwl/cpwl_edit_ctrl.h +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.h @@ -61,7 +61,7 @@ class CPWL_EditCtrl : public CPWL_Wnd { float GetFontSize() const override; void SetCursor() override; CFX_WideString GetSelectedText() override; - void DeleteSelectedText() override; + void ReplaceSelection(const CFX_WideString& text) override; void SetCaret(bool bVisible, const CFX_PointF& ptHead, diff --git a/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp index 98cc44ab86..34569b2491 100644 --- a/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp +++ b/fpdfsdk/pwl/cpwl_edit_embeddertest.cpp @@ -24,35 +24,44 @@ class CPWLEditEmbeddertest : public EmbedderTest { } void CreateAndInitializeFormPDF() { - EXPECT_TRUE(OpenDocument("text_form.pdf")); + EXPECT_TRUE(OpenDocument("text_form_multiple.pdf")); m_page = LoadPage(0); ASSERT_TRUE(m_page); - CPDFSDK_FormFillEnvironment* pFormFillEnv = - static_cast(form_handle()); - - { - CBA_AnnotIterator iter(pFormFillEnv->GetPageView(0), - CPDF_Annot::Subtype::WIDGET); - m_pAnnot = iter.GetFirstAnnot(); - CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); - ASSERT_EQ(m_pAnnot, pLastAnnot); - ASSERT_TRUE(m_pAnnot); - ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); - } + m_pFormFillEnv = static_cast(form_handle()); + CBA_AnnotIterator iter(m_pFormFillEnv->GetPageView(0), + CPDF_Annot::Subtype::WIDGET); + // Normal text field. + m_pAnnot = iter.GetFirstAnnot(); + ASSERT_TRUE(m_pAnnot); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, m_pAnnot->GetAnnotSubtype()); + + // Read-only text field. + CPDFSDK_Annot* pAnnotReadOnly = iter.GetNextAnnot(m_pAnnot); + + // Pre-filled text field with char limit of 10. + m_pAnnotCharLimit = iter.GetNextAnnot(pAnnotReadOnly); + ASSERT_TRUE(m_pAnnotCharLimit); + ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, + m_pAnnotCharLimit->GetAnnotSubtype()); + CPDFSDK_Annot* pLastAnnot = iter.GetLastAnnot(); + ASSERT_EQ(m_pAnnotCharLimit, pLastAnnot); + } + void FormFillerAndWindowSetup(CPDFSDK_Annot* pAnnotTextField) { CFFL_InteractiveFormFiller* pInteractiveFormFiller = - pFormFillEnv->GetInteractiveFormFiller(); + m_pFormFillEnv->GetInteractiveFormFiller(); { - CPDFSDK_Annot::ObservedPtr pObserved(m_pAnnot); + CPDFSDK_Annot::ObservedPtr pObserved(pAnnotTextField); EXPECT_TRUE(pInteractiveFormFiller->OnSetFocus(&pObserved, 0)); } - m_pFormFiller = pInteractiveFormFiller->GetFormFiller(m_pAnnot, false); + m_pFormFiller = + pInteractiveFormFiller->GetFormFiller(pAnnotTextField, false); ASSERT_TRUE(m_pFormFiller); CPWL_Wnd* pWindow = - m_pFormFiller->GetPDFWindow(pFormFillEnv->GetPageView(0), false); + m_pFormFiller->GetPDFWindow(m_pFormFillEnv->GetPageView(0), false); ASSERT_TRUE(pWindow); ASSERT_EQ(PWL_CLASSNAME_EDIT, pWindow->GetClassName()); @@ -70,15 +79,19 @@ class CPWLEditEmbeddertest : public EmbedderTest { CPWL_Edit* GetCPWLEdit() { return m_pEdit; } CFFL_FormFiller* GetCFFLFormFiller() { return m_pFormFiller; } CPDFSDK_Annot* GetCPDFSDKAnnot() { return m_pAnnot; } + CPDFSDK_Annot* GetCPDFSDKAnnotCharLimit() { return m_pAnnotCharLimit; } private: FPDF_PAGE m_page; CPWL_Edit* m_pEdit; CFFL_FormFiller* m_pFormFiller; CPDFSDK_Annot* m_pAnnot; + CPDFSDK_Annot* m_pAnnotCharLimit; + CPDFSDK_FormFillEnvironment* m_pFormFillEnv; }; TEST_F(CPWLEditEmbeddertest, TypeText) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'a', 0)); EXPECT_TRUE(GetCFFLFormFiller()->OnChar(GetCPDFSDKAnnot(), 'b', 0)); @@ -88,6 +101,7 @@ TEST_F(CPWLEditEmbeddertest, TypeText) { } TEST_F(CPWLEditEmbeddertest, GetSelectedTextEmptyAndBasic) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); // Attempt to set selection before text has been typed to test that // selection is identified as empty. // @@ -104,6 +118,7 @@ TEST_F(CPWLEditEmbeddertest, GetSelectedTextEmptyAndBasic) { } TEST_F(CPWLEditEmbeddertest, GetSelectedTextFragments) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); GetCPWLEdit()->SetSelection(0, 0); @@ -133,53 +148,226 @@ TEST_F(CPWLEditEmbeddertest, GetSelectedTextFragments) { } TEST_F(CPWLEditEmbeddertest, DeleteEntireTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); GetCPWLEdit()->SetSelection(0, -1); EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLEdit()->GetSelectedText().c_str()); - GetCPWLEdit()->DeleteSelectedText(); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); EXPECT_TRUE(GetCPWLEdit()->GetText().IsEmpty()); } TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); GetCPWLEdit()->SetSelection(12, 23); EXPECT_STREQ(L"MNOPQRSTUVW", GetCPWLEdit()->GetSelectedText().c_str()); - GetCPWLEdit()->DeleteSelectedText(); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLEdit()->GetText().c_str()); } TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); GetCPWLEdit()->SetSelection(0, 5); EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); - GetCPWLEdit()->DeleteSelectedText(); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"FGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLEdit()->GetText().c_str()); } TEST_F(CPWLEditEmbeddertest, DeleteTextSelectionRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); GetCPWLEdit()->SetSelection(45, 50); EXPECT_STREQ(L"nopqr", GetCPWLEdit()->GetSelectedText().c_str()); - GetCPWLEdit()->DeleteSelectedText(); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm", GetCPWLEdit()->GetText().c_str()); } TEST_F(CPWLEditEmbeddertest, DeleteEmptyTextSelection) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); TypeTextIntoTextField(50); - GetCPWLEdit()->DeleteSelectedText(); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); EXPECT_STREQ(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqr", GetCPWLEdit()->GetText().c_str()); } + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyTextField) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + // Move cursor to beginning of text field. + EXPECT_TRUE( + GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Home, 0)); + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"HelloABCDEFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + // Move cursor to middle of text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE( + GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnot(), FWL_VKEY_Left, 0)); + } + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEHelloFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEFGHIJHello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"ABCDEFGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"Hello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(0, 5); + EXPECT_STREQ(L"ABCDE", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"HelloFGHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(2, 7); + EXPECT_STREQ(L"CDEFG", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABHelloHIJ", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnot()); + TypeTextIntoTextField(10); + + GetCPWLEdit()->SetSelection(5, 10); + EXPECT_STREQ(L"FGHIJ", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hello")); + EXPECT_STREQ(L"ABCDEHello", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldOverflow) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInEmptyCharLimitTextFieldFit) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString()); + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Zebra")); + EXPECT_STREQ(L"Zebra", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"HiElephant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + // Move cursor to middle of text field. + for (int i = 0; i < 5; ++i) { + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), + FWL_VKEY_Right, 0)); + } + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"ElephHiant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, InsertTextInPopulatedCharLimitTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + // Move cursor to end of text field. + EXPECT_TRUE(GetCFFLFormFiller()->OnKeyDown(GetCPDFSDKAnnotCharLimit(), + FWL_VKEY_End, 0)); + + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"ElephantHi", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldWhole) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, -1); + EXPECT_STREQ(L"Elephant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"Hippopotam", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldLeft) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(0, 4); + EXPECT_STREQ(L"Elep", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"Hippophant", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldMiddle) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(2, 6); + EXPECT_STREQ(L"epha", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"ElHippopnt", GetCPWLEdit()->GetText().c_str()); +} + +TEST_F(CPWLEditEmbeddertest, + InsertTextAndReplaceSelectionInPopulatedCharLimitTextFieldRight) { + FormFillerAndWindowSetup(GetCPDFSDKAnnotCharLimit()); + GetCPWLEdit()->SetSelection(4, 8); + EXPECT_STREQ(L"hant", GetCPWLEdit()->GetSelectedText().c_str()); + GetCPWLEdit()->ReplaceSelection(CFX_WideString(L"Hippopotamus")); + EXPECT_STREQ(L"ElepHippop", GetCPWLEdit()->GetText().c_str()); +} diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp index 2269162260..c7bf23ce60 100644 --- a/fpdfsdk/pwl/cpwl_wnd.cpp +++ b/fpdfsdk/pwl/cpwl_wnd.cpp @@ -369,7 +369,7 @@ CFX_WideString CPWL_Wnd::GetSelectedText() { return CFX_WideString(); } -void CPWL_Wnd::DeleteSelectedText() {} +void CPWL_Wnd::ReplaceSelection(const CFX_WideString& text) {} bool CPWL_Wnd::OnMouseWheel(short zDelta, const CFX_PointF& point, diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h index 7c93216a58..15487a3c07 100644 --- a/fpdfsdk/pwl/cpwl_wnd.h +++ b/fpdfsdk/pwl/cpwl_wnd.h @@ -202,7 +202,7 @@ class CPWL_Wnd : public CPWL_TimerHandler, public CFX_Observable { virtual float GetFontSize() const; virtual CFX_WideString GetSelectedText(); - virtual void DeleteSelectedText(); + virtual void ReplaceSelection(const CFX_WideString& text); virtual CFX_FloatRect GetFocusRect() const; virtual CFX_FloatRect GetClientRect() const; diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index 83a4e58bdc..617bc34b17 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h @@ -1378,20 +1378,24 @@ DLLEXPORT unsigned long STDCALL FORM_GetSelectedText(FPDF_FORMHANDLE hHandle, unsigned long buflen); /** - * Function: FORM_DeleteSelectedText - * You can call this function to delete the current text selection in - * a form text field or user-editable form combobox text field. If - * there is no selected text, this function does nothing. + * Function: FORM_ReplaceSelection + * You can call this function to replace the selected text in a form + * text field or user-editable form combobox text field with another + * text string (which can be empty or non-empty). If there is no + * selected text, this function will append the replacement text after + * the current caret position. * Parameters: * hHandle - Handle to the form fill module. Returned by * FPDFDOC_InitFormFillEnvironment. * page - Handle to the page. Returned by FPDF_LoadPage * function. + * wsText - The text to be inserted, in UTF-16LE format. * Return Value: * None. **/ -DLLEXPORT void STDCALL FORM_DeleteSelectedText(FPDF_FORMHANDLE hHandle, - FPDF_PAGE page); +DLLEXPORT void STDCALL FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + FPDF_WIDESTRING wsText); /** * Function: FORM_ForceToKillFocus. diff --git a/testing/resources/text_form_multiple.in b/testing/resources/text_form_multiple.in index 43919eb200..576e15597c 100644 --- a/testing/resources/text_form_multiple.in +++ b/testing/resources/text_form_multiple.in @@ -3,7 +3,7 @@ << /Type /Catalog /Pages 2 0 R - /AcroForm << /Fields [ 4 0 R 9 0 R ] /DR 5 0 R >> + /AcroForm << /Fields [ 4 0 R 9 0 R 10 0 R ] /DR 5 0 R >> >> endobj {{object 2 0}} @@ -16,7 +16,7 @@ endobj /Resources 5 0 R /MediaBox [ 0 0 300 300 ] /Contents 8 0 R - /Annots [ 4 0 R 9 0 R ] + /Annots [ 4 0 R 9 0 R 10 0 R ] >> endobj {{object 4 0}} @@ -63,6 +63,18 @@ endobj /Subtype /Widget >> endobj +{{object 10 0}} +<< + /Type /Annot + /FT /Tx + /T (CharLimit) + /MaxLen 10 + /DA (0 0 0 rg /F1 12 Tf) + /V (Elephant) + /Rect [ 100 50 200 75 ] + /Subtype /Widget +>> +endobj {{xref}} {{trailer}} {{startxref}} diff --git a/testing/resources/text_form_multiple.pdf b/testing/resources/text_form_multiple.pdf index 6b14cefa82..172ab5e864 100644 --- a/testing/resources/text_form_multiple.pdf +++ b/testing/resources/text_form_multiple.pdf @@ -4,7 +4,7 @@ << /Type /Catalog /Pages 2 0 R - /AcroForm << /Fields [ 4 0 R 9 0 R ] /DR 5 0 R >> + /AcroForm << /Fields [ 4 0 R 9 0 R 10 0 R ] /DR 5 0 R >> >> endobj 2 0 obj @@ -17,7 +17,7 @@ endobj /Resources 5 0 R /MediaBox [ 0 0 300 300 ] /Contents 8 0 R - /Annots [ 4 0 R 9 0 R ] + /Annots [ 4 0 R 9 0 R 10 0 R ] >> endobj 4 0 obj @@ -64,19 +64,32 @@ endobj /Subtype /Widget >> endobj +10 0 obj +<< + /Type /Annot + /FT /Tx + /T (CharLimit) + /MaxLen 10 + /DA (0 0 0 rg /F1 12 Tf) + /V (Elephant) + /Rect [ 100 50 200 75 ] + /Subtype /Widget +>> +endobj xref -0 10 +0 11 0000000000 65535 f 0000000015 00000 n -0000000120 00000 n -0000000179 00000 n -0000000321 00000 n -0000000457 00000 n -0000000490 00000 n -0000000521 00000 n -0000000597 00000 n -0000000697 00000 n -trailer<< /Root 1 0 R /Size 10 >> +0000000127 00000 n +0000000186 00000 n +0000000335 00000 n +0000000471 00000 n +0000000504 00000 n +0000000535 00000 n +0000000611 00000 n +0000000711 00000 n +0000000855 00000 n +trailer<< /Root 1 0 R /Size 11 >> startxref -841 +1020 %%EOF -- cgit v1.2.3