diff options
27 files changed, 468 insertions, 12 deletions
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp index 52ab4dd2c6..37d5274bab 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp +++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp @@ -90,6 +90,22 @@ void CPDFSDK_AnnotHandlerMgr::Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, GetAnnotHandler(pAnnot)->ReplaceSelection(pAnnot, text); } +bool CPDFSDK_AnnotHandlerMgr::Annot_CanUndo(CPDFSDK_Annot* pAnnot) { + return GetAnnotHandler(pAnnot)->CanUndo(pAnnot); +} + +bool CPDFSDK_AnnotHandlerMgr::Annot_CanRedo(CPDFSDK_Annot* pAnnot) { + return GetAnnotHandler(pAnnot)->CanRedo(pAnnot); +} + +bool CPDFSDK_AnnotHandlerMgr::Annot_Undo(CPDFSDK_Annot* pAnnot) { + return GetAnnotHandler(pAnnot)->Undo(pAnnot); +} + +bool CPDFSDK_AnnotHandlerMgr::Annot_Redo(CPDFSDK_Annot* pAnnot) { + return GetAnnotHandler(pAnnot)->Redo(pAnnot); +} + IPDFSDK_AnnotHandler* CPDFSDK_AnnotHandlerMgr::GetAnnotHandler( CPDFSDK_Annot* pAnnot) const { return GetAnnotHandler(pAnnot->GetAnnotSubtype()); diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h index 7ea7a0e4f9..c983ef8881 100644 --- a/fpdfsdk/cpdfsdk_annothandlermgr.h +++ b/fpdfsdk/cpdfsdk_annothandlermgr.h @@ -46,6 +46,11 @@ class CPDFSDK_AnnotHandlerMgr { WideString Annot_GetSelectedText(CPDFSDK_Annot* pAnnot); void Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); + bool Annot_CanUndo(CPDFSDK_Annot* pAnnot); + bool Annot_CanRedo(CPDFSDK_Annot* pAnnot); + bool Annot_Undo(CPDFSDK_Annot* pAnnot); + bool Annot_Redo(CPDFSDK_Annot* pAnnot); + IPDFSDK_AnnotHandler* GetAnnotHandler(CPDFSDK_Annot* pAnnot) const; void Annot_OnDraw(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp index 24643eb70e..ab46a9683c 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.cpp +++ b/fpdfsdk/cpdfsdk_baannothandler.cpp @@ -204,6 +204,22 @@ WideString CPDFSDK_BAAnnotHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) { void CPDFSDK_BAAnnotHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) {} +bool CPDFSDK_BAAnnotHandler::CanUndo(CPDFSDK_Annot* pAnnot) { + return false; +} + +bool CPDFSDK_BAAnnotHandler::CanRedo(CPDFSDK_Annot* pAnnot) { + return false; +} + +bool CPDFSDK_BAAnnotHandler::Undo(CPDFSDK_Annot* pAnnot) { + return false; +} + +bool CPDFSDK_BAAnnotHandler::Redo(CPDFSDK_Annot* pAnnot) { + return false; +} + bool CPDFSDK_BAAnnotHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) { diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h index 2a03402fa5..3369839bb7 100644 --- a/fpdfsdk/cpdfsdk_baannothandler.h +++ b/fpdfsdk/cpdfsdk_baannothandler.h @@ -39,6 +39,10 @@ class CPDFSDK_BAAnnotHandler : public IPDFSDK_AnnotHandler { WideString GetText(CPDFSDK_Annot* pAnnot) override; WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; + bool CanUndo(CPDFSDK_Annot* pAnnot) override; + bool CanRedo(CPDFSDK_Annot* pAnnot) override; + bool Undo(CPDFSDK_Annot* pAnnot) override; + bool Redo(CPDFSDK_Annot* pAnnot) 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 b7f8cdfe10..b68828b144 100644 --- a/fpdfsdk/cpdfsdk_pageview.cpp +++ b/fpdfsdk/cpdfsdk_pageview.cpp @@ -268,6 +268,42 @@ void CPDFSDK_PageView::ReplaceSelection(const WideString& text) { } } +bool CPDFSDK_PageView::CanUndo() { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + return pAnnotHandlerMgr->Annot_CanUndo(pAnnot); + } + return false; +} + +bool CPDFSDK_PageView::CanRedo() { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + return pAnnotHandlerMgr->Annot_CanRedo(pAnnot); + } + return false; +} + +bool CPDFSDK_PageView::Undo() { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + return pAnnotHandlerMgr->Annot_Undo(pAnnot); + } + return false; +} + +bool CPDFSDK_PageView::Redo() { + if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) { + CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr = + m_pFormFillEnv->GetAnnotHandlerMgr(); + return pAnnotHandlerMgr->Annot_Redo(pAnnot); + } + return false; +} + bool CPDFSDK_PageView::OnFocus(const CFX_PointF& point, uint32_t nFlag) { CPDFSDK_Annot::ObservedPtr pAnnot(GetFXWidgetAtPoint(point)); if (!pAnnot) { diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h index 9f846cf2a4..e85b32aa78 100644 --- a/fpdfsdk/cpdfsdk_pageview.h +++ b/fpdfsdk/cpdfsdk_pageview.h @@ -65,6 +65,11 @@ class CPDFSDK_PageView final : public CPDF_Page::View { WideString GetSelectedText(); void ReplaceSelection(const WideString& text); + bool CanUndo(); + bool CanRedo(); + bool Undo(); + bool Redo(); + bool OnFocus(const CFX_PointF& point, uint32_t nFlag); 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 6281058059..17d783fcbe 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.cpp +++ b/fpdfsdk/cpdfsdk_widgethandler.cpp @@ -299,6 +299,30 @@ void CPDFSDK_WidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, m_pFormFiller->ReplaceSelection(pAnnot, text); } +bool CPDFSDK_WidgetHandler::CanUndo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + return m_pFormFiller->CanUndo(pAnnot); + return false; +} + +bool CPDFSDK_WidgetHandler::CanRedo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + return m_pFormFiller->CanRedo(pAnnot); + return false; +} + +bool CPDFSDK_WidgetHandler::Undo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + return m_pFormFiller->Undo(pAnnot); + return false; +} + +bool CPDFSDK_WidgetHandler::Redo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot->IsSignatureWidget() && m_pFormFiller) + return m_pFormFiller->Redo(pAnnot); + return false; +} + bool CPDFSDK_WidgetHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) { diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h index fbf9d2e906..80323deb72 100644 --- a/fpdfsdk/cpdfsdk_widgethandler.h +++ b/fpdfsdk/cpdfsdk_widgethandler.h @@ -40,6 +40,10 @@ class CPDFSDK_WidgetHandler : public IPDFSDK_AnnotHandler { WideString GetText(CPDFSDK_Annot* pAnnot) override; WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; + bool CanUndo(CPDFSDK_Annot* pAnnot) override; + bool CanRedo(CPDFSDK_Annot* pAnnot) override; + bool Undo(CPDFSDK_Annot* pAnnot) override; + bool Redo(CPDFSDK_Annot* pAnnot) 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 261c27c384..16692b3d25 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp @@ -125,6 +125,34 @@ void CPDFSDK_XFAWidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot, return pWidgetHandler->PasteText(pAnnot->GetXFAWidget(), text); } +bool CPDFSDK_XFAWidgetHandler::CanUndo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return false; + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->CanUndo(pAnnot->GetXFAWidget()); +} + +bool CPDFSDK_XFAWidgetHandler::CanRedo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return false; + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->CanRedo(pAnnot->GetXFAWidget()); +} + +bool CPDFSDK_XFAWidgetHandler::Undo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return false; + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->Undo(pAnnot->GetXFAWidget()); +} + +bool CPDFSDK_XFAWidgetHandler::Redo(CPDFSDK_Annot* pAnnot) { + if (!pAnnot) + return false; + CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot); + return pWidgetHandler->Redo(pAnnot->GetXFAWidget()); +} + bool CPDFSDK_XFAWidgetHandler::HitTest(CPDFSDK_PageView* pPageView, CPDFSDK_Annot* pAnnot, const CFX_PointF& point) { diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.h b/fpdfsdk/cpdfsdk_xfawidgethandler.h index dbdb99bada..b49c90577a 100644 --- a/fpdfsdk/cpdfsdk_xfawidgethandler.h +++ b/fpdfsdk/cpdfsdk_xfawidgethandler.h @@ -35,6 +35,10 @@ class CPDFSDK_XFAWidgetHandler : public IPDFSDK_AnnotHandler { WideString GetText(CPDFSDK_Annot* pAnnot) override; WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override; void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override; + bool CanUndo(CPDFSDK_Annot* pAnnot) override; + bool CanRedo(CPDFSDK_Annot* pAnnot) override; + bool Undo(CPDFSDK_Annot* pAnnot) override; + bool Redo(CPDFSDK_Annot* pAnnot) 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 32bbcb73d2..ac82e3ed47 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.cpp +++ b/fpdfsdk/formfiller/cffl_formfiller.cpp @@ -256,6 +256,50 @@ void CFFL_FormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, pWnd->ReplaceSelection(text); } +bool CFFL_FormFiller::CanUndo(CPDFSDK_Annot* pAnnot) { + if (!IsValid()) + return false; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->CanUndo(); +} + +bool CFFL_FormFiller::CanRedo(CPDFSDK_Annot* pAnnot) { + if (!IsValid()) + return false; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->CanRedo(); +} + +bool CFFL_FormFiller::Undo(CPDFSDK_Annot* pAnnot) { + if (!IsValid()) + return false; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->Undo(); +} + +bool CFFL_FormFiller::Redo(CPDFSDK_Annot* pAnnot) { + if (!IsValid()) + return false; + + CPDFSDK_PageView* pPageView = GetCurPageView(true); + ASSERT(pPageView); + + CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false); + return pWnd && pWnd->Redo(); +} + void CFFL_FormFiller::SetFocusForAnnot(CPDFSDK_Annot* pAnnot, uint32_t nFlag) { CPDFSDK_Widget* pWidget = (CPDFSDK_Widget*)pAnnot; UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h index a9d90ab902..bad42ecaf4 100644 --- a/fpdfsdk/formfiller/cffl_formfiller.h +++ b/fpdfsdk/formfiller/cffl_formfiller.h @@ -79,6 +79,11 @@ class CFFL_FormFiller : public CPWL_Wnd::ProviderIface, WideString GetSelectedText(CPDFSDK_Annot* pAnnot); void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); + bool CanUndo(CPDFSDK_Annot* pAnnot); + bool CanRedo(CPDFSDK_Annot* pAnnot); + bool Undo(CPDFSDK_Annot* pAnnot); + bool Redo(CPDFSDK_Annot* pAnnot); + 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 5972d1dd67..6b34ca3ae2 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp @@ -533,6 +533,30 @@ void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot, pFormFiller->ReplaceSelection(pAnnot, text); } +bool CFFL_InteractiveFormFiller::CanUndo(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->CanUndo(pAnnot); +} + +bool CFFL_InteractiveFormFiller::CanRedo(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->CanRedo(pAnnot); +} + +bool CFFL_InteractiveFormFiller::Undo(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->Undo(pAnnot); +} + +bool CFFL_InteractiveFormFiller::Redo(CPDFSDK_Annot* pAnnot) { + ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET); + CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false); + return pFormFiller && pFormFiller->Redo(pAnnot); +} + void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) { auto it = m_Maps.find(pAnnot); if (it == m_Maps.end()) diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h index bb0d2233fc..1f049d03ef 100644 --- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h +++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h @@ -86,6 +86,11 @@ class CFFL_InteractiveFormFiller : public IPWL_Filler_Notify { WideString GetSelectedText(CPDFSDK_Annot* pAnnot); void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text); + bool CanUndo(CPDFSDK_Annot* pAnnot); + bool CanRedo(CPDFSDK_Annot* pAnnot); + bool Undo(CPDFSDK_Annot* pAnnot); + bool Redo(CPDFSDK_Annot* pAnnot); + static bool IsVisible(CPDFSDK_Widget* pWidget); static bool IsReadOnly(CPDFSDK_Widget* pWidget); static bool IsFillingAllowed(CPDFSDK_Widget* pWidget); diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp index 7676463edc..b70bd9da50 100644 --- a/fpdfsdk/fpdf_formfill.cpp +++ b/fpdfsdk/fpdf_formfill.cpp @@ -465,6 +465,38 @@ FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, pPageView->ReplaceSelection(wide_str_text); } +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanUndo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->CanUndo(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanRedo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->CanRedo(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Undo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->Undo(); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Redo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->Redo(); +} + FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { CPDFSDK_FormFillEnvironment* pFormFillEnv = diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp index 5dd4d1e1c1..09e0c200d3 100644 --- a/fpdfsdk/fpdf_formfill_embeddertest.cpp +++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp @@ -134,6 +134,18 @@ class FPDFFormFillInteractiveEmbeddertest : public FPDFFormFillEmbeddertest { EXPECT_EQ(expected_string, WideString::FromUTF16LE(buf.data(), num_chars)); } + void CheckCanUndo(bool expected_result) { + EXPECT_EQ(expected_result, !!FORM_CanUndo(form_handle(), page_)); + } + + void CheckCanRedo(bool expected_result) { + EXPECT_EQ(expected_result, !!FORM_CanRedo(form_handle(), page_)); + } + + void PerformUndo() { EXPECT_TRUE(FORM_Undo(form_handle(), page_)); } + + void PerformRedo() { EXPECT_TRUE(FORM_Redo(form_handle(), page_)); } + private: FPDF_PAGE page_ = nullptr; }; @@ -1544,3 +1556,68 @@ TEST_F(FPDFFormFillComboBoxFormEmbeddertest, FocusChanges) { SelectEditableFormOption(0); CheckFocusedFieldText(L"Foo"); } + +TEST_F(FPDFFormFillTextFormEmbeddertest, UndoRedo) { + ClickOnFormFieldAtPoint(RegularFormBegin()); + CheckFocusedFieldText(L""); + CheckCanUndo(false); + CheckCanRedo(false); + + TypeTextIntoTextField(5, RegularFormBegin()); + CheckFocusedFieldText(L"ABCDE"); + CheckCanUndo(true); + CheckCanRedo(false); + + PerformUndo(); + CheckFocusedFieldText(L"ABCD"); + CheckCanUndo(true); + CheckCanRedo(true); + PerformUndo(); + CheckFocusedFieldText(L"ABC"); + CheckCanUndo(true); + CheckCanRedo(true); + + PerformRedo(); + CheckFocusedFieldText(L"ABCD"); + CheckCanUndo(true); + CheckCanRedo(true); + PerformRedo(); + CheckFocusedFieldText(L"ABCDE"); + CheckCanUndo(true); + CheckCanRedo(false); +} + +TEST_F(FPDFFormFillComboBoxFormEmbeddertest, UndoRedo) { + ClickOnFormFieldAtPoint(NonEditableFormBegin()); + CheckFocusedFieldText(L"Banana"); + CheckCanUndo(false); + CheckCanRedo(false); + + ClickOnFormFieldAtPoint(EditableFormBegin()); + CheckFocusedFieldText(L""); + CheckCanUndo(false); + CheckCanRedo(false); + + TypeTextIntoTextField(3, EditableFormBegin()); + CheckFocusedFieldText(L"ABC"); + CheckCanUndo(true); + CheckCanRedo(false); + + PerformUndo(); + CheckFocusedFieldText(L"AB"); + CheckCanUndo(true); + CheckCanRedo(true); + PerformUndo(); + CheckFocusedFieldText(L"A"); + CheckCanUndo(true); + CheckCanRedo(true); + PerformUndo(); + CheckFocusedFieldText(L""); + CheckCanUndo(false); + CheckCanRedo(true); + + PerformRedo(); + CheckFocusedFieldText(L"A"); + CheckCanUndo(true); + CheckCanRedo(true); +} diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c index e23efa2ff2..017487246b 100644 --- a/fpdfsdk/fpdf_view_c_api_test.c +++ b/fpdfsdk/fpdf_view_c_api_test.c @@ -217,6 +217,10 @@ int CheckPDFiumCApi() { CHK(FORM_GetFocusedText); CHK(FORM_GetSelectedText); CHK(FORM_ReplaceSelection); + CHK(FORM_CanUndo); + CHK(FORM_CanRedo); + CHK(FORM_Undo); + CHK(FORM_Redo); CHK(FORM_ForceToKillFocus); CHK(FPDFPage_HasFormFieldAtPoint); CHK(FPDFPage_FormFieldZOrderAtPoint); diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h index 91fd5ceee8..1476089253 100644 --- a/fpdfsdk/ipdfsdk_annothandler.h +++ b/fpdfsdk/ipdfsdk_annothandler.h @@ -39,6 +39,10 @@ class IPDFSDK_AnnotHandler { virtual WideString GetSelectedText(CPDFSDK_Annot* pAnnot) = 0; virtual void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) = 0; + virtual bool CanUndo(CPDFSDK_Annot* pAnnot) = 0; + virtual bool CanRedo(CPDFSDK_Annot* pAnnot) = 0; + virtual bool Undo(CPDFSDK_Annot* pAnnot) = 0; + virtual bool Redo(CPDFSDK_Annot* pAnnot) = 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 1576b022fd..2e6e56c52b 100644 --- a/fpdfsdk/pwl/cpwl_combo_box.cpp +++ b/fpdfsdk/pwl/cpwl_combo_box.cpp @@ -196,6 +196,22 @@ void CPWL_ComboBox::ReplaceSelection(const WideString& text) { m_pEdit->ReplaceSelection(text); } +bool CPWL_ComboBox::CanUndo() { + return m_pEdit && m_pEdit->CanUndo(); +} + +bool CPWL_ComboBox::CanRedo() { + return m_pEdit && m_pEdit->CanRedo(); +} + +bool CPWL_ComboBox::Undo() { + return m_pEdit && m_pEdit->Undo(); +} + +bool CPWL_ComboBox::Redo() { + return m_pEdit && m_pEdit->Redo(); +} + WideString CPWL_ComboBox::GetText() { return m_pEdit ? m_pEdit->GetText() : WideString(); } diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h index 28c063d5fd..a4e823c4dc 100644 --- a/fpdfsdk/pwl/cpwl_combo_box.h +++ b/fpdfsdk/pwl/cpwl_combo_box.h @@ -63,6 +63,10 @@ class CPWL_ComboBox : public CPWL_Wnd { WideString GetText() override; WideString GetSelectedText() override; void ReplaceSelection(const WideString& text) override; + bool CanUndo() override; + bool CanRedo() override; + bool Undo() override; + bool Redo() override; void SetFillerNotify(IPWL_Filler_Notify* pNotify); diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp index 5e2f7acda6..579a587175 100644 --- a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp @@ -401,22 +401,20 @@ void CPWL_EditCtrl::Backspace() { m_pEdit->Backspace(); } -bool CPWL_EditCtrl::CanUndo() const { +bool CPWL_EditCtrl::CanUndo() { return !IsReadOnly() && m_pEdit->CanUndo(); } -bool CPWL_EditCtrl::CanRedo() const { +bool CPWL_EditCtrl::CanRedo() { return !IsReadOnly() && m_pEdit->CanRedo(); } -void CPWL_EditCtrl::Redo() { - if (CanRedo()) - m_pEdit->Redo(); +bool CPWL_EditCtrl::Undo() { + return CanUndo() && m_pEdit->Undo(); } -void CPWL_EditCtrl::Undo() { - if (CanUndo()) - m_pEdit->Undo(); +bool CPWL_EditCtrl::Redo() { + return CanRedo() && m_pEdit->Redo(); } int32_t CPWL_EditCtrl::GetCharSet() const { diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.h b/fpdfsdk/pwl/cpwl_edit_ctrl.h index 544464770f..a21c8a2700 100644 --- a/fpdfsdk/pwl/cpwl_edit_ctrl.h +++ b/fpdfsdk/pwl/cpwl_edit_ctrl.h @@ -36,10 +36,10 @@ class CPWL_EditCtrl : public CPWL_Wnd { void SetCharSet(uint8_t nCharSet) { m_nCharSet = nCharSet; } int32_t GetCharSet() const; - bool CanUndo() const; - bool CanRedo() const; - void Redo(); - void Undo(); + bool CanUndo() override; + bool CanRedo() override; + bool Undo() override; + bool Redo() override; void SetReadyToInput(); diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp index c6d6b79136..8782e85a14 100644 --- a/fpdfsdk/pwl/cpwl_wnd.cpp +++ b/fpdfsdk/pwl/cpwl_wnd.cpp @@ -365,6 +365,22 @@ WideString CPWL_Wnd::GetSelectedText() { void CPWL_Wnd::ReplaceSelection(const WideString& text) {} +bool CPWL_Wnd::CanUndo() { + return false; +} + +bool CPWL_Wnd::CanRedo() { + return false; +} + +bool CPWL_Wnd::Undo() { + return false; +} + +bool CPWL_Wnd::Redo() { + return false; +} + bool CPWL_Wnd::OnMouseWheel(short zDelta, const CFX_PointF& point, uint32_t nFlag) { diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h index 9c790eb5b8..a24635fa1f 100644 --- a/fpdfsdk/pwl/cpwl_wnd.h +++ b/fpdfsdk/pwl/cpwl_wnd.h @@ -184,6 +184,12 @@ class CPWL_Wnd : public CPWL_TimerHandler, public Observable<CPWL_Wnd> { virtual WideString GetText(); virtual WideString GetSelectedText(); virtual void ReplaceSelection(const WideString& text); + + virtual bool CanUndo(); + virtual bool CanRedo(); + virtual bool Undo(); + virtual bool Redo(); + virtual CFX_FloatRect GetFocusRect() const; virtual CFX_FloatRect GetClientRect() const; diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h index ff87d99ab5..73964b2a93 100644 --- a/public/fpdf_formfill.h +++ b/public/fpdf_formfill.h @@ -1452,6 +1452,64 @@ FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, FPDF_WIDESTRING wsText); /** + * Function: FORM_CanUndo + * Find out if it is possible for the current focused widget in a given + * form to perform an undo operation. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * Return Value: + * True if it is possible to undo. + **/ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanUndo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page); + +/** + * Function: FORM_CanRedo + * Find out if it is possible for the current focused widget in a given + * form to perform a redo operation. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * Return Value: + * True if it is possible to redo. + **/ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_CanRedo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page); + +/** + * Function: FORM_Undo + * Make the current focussed widget perform an undo operation. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * Return Value: + * True if the undo operation succeeded. + **/ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Undo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page); + +/** + * Function: FORM_Redo + * Make the current focussed widget perform a redo operation. + * Parameters: + * hHandle - Handle to the form fill module. Returned by + * FPDFDOC_InitFormFillEnvironment. + * page - Handle to the page. Returned by FPDF_LoadPage + * function. + * Return Value: + * True if the redo operation succeeded. + **/ +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_Redo(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page); + +/** * Function: FORM_ForceToKillFocus. * You can call this member function to force to kill the focus of the *form field which got focus. diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp index c3efd60b1d..a820db8083 100644 --- a/xfa/fxfa/cxfa_ffwidgethandler.cpp +++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp @@ -166,6 +166,22 @@ void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget, widget->Paste(text); } +bool CXFA_FFWidgetHandler::CanUndo(CXFA_FFWidget* widget) { + return widget->CanUndo(); +} + +bool CXFA_FFWidgetHandler::CanRedo(CXFA_FFWidget* widget) { + return widget->CanRedo(); +} + +bool CXFA_FFWidgetHandler::Undo(CXFA_FFWidget* widget) { + return widget->Undo(); +} + +bool CXFA_FFWidgetHandler::Redo(CXFA_FFWidget* widget) { + return widget->Redo(); +} + FWL_WidgetHit CXFA_FFWidgetHandler::OnHitTest(CXFA_FFWidget* hWidget, const CFX_PointF& point) { if (!(hWidget->GetStatus() & XFA_WidgetStatus_Visible)) diff --git a/xfa/fxfa/cxfa_ffwidgethandler.h b/xfa/fxfa/cxfa_ffwidgethandler.h index ba6a5a26ca..975f3607e4 100644 --- a/xfa/fxfa/cxfa_ffwidgethandler.h +++ b/xfa/fxfa/cxfa_ffwidgethandler.h @@ -58,6 +58,11 @@ class CXFA_FFWidgetHandler { WideString GetSelectedText(CXFA_FFWidget* widget); void PasteText(CXFA_FFWidget* widget, const WideString& text); + bool CanUndo(CXFA_FFWidget* widget); + bool CanRedo(CXFA_FFWidget* widget); + bool Undo(CXFA_FFWidget* widget); + bool Redo(CXFA_FFWidget* widget); + bool OnKeyDown(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); bool OnKeyUp(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags); bool OnChar(CXFA_FFWidget* hWidget, uint32_t dwChar, uint32_t dwFlags); |