summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpdfsdk/cpdfsdk_annothandlermgr.cpp16
-rw-r--r--fpdfsdk/cpdfsdk_annothandlermgr.h5
-rw-r--r--fpdfsdk/cpdfsdk_baannothandler.cpp16
-rw-r--r--fpdfsdk/cpdfsdk_baannothandler.h4
-rw-r--r--fpdfsdk/cpdfsdk_pageview.cpp36
-rw-r--r--fpdfsdk/cpdfsdk_pageview.h5
-rw-r--r--fpdfsdk/cpdfsdk_widgethandler.cpp24
-rw-r--r--fpdfsdk/cpdfsdk_widgethandler.h4
-rw-r--r--fpdfsdk/cpdfsdk_xfawidgethandler.cpp28
-rw-r--r--fpdfsdk/cpdfsdk_xfawidgethandler.h4
-rw-r--r--fpdfsdk/formfiller/cffl_formfiller.cpp44
-rw-r--r--fpdfsdk/formfiller/cffl_formfiller.h5
-rw-r--r--fpdfsdk/formfiller/cffl_interactiveformfiller.cpp24
-rw-r--r--fpdfsdk/formfiller/cffl_interactiveformfiller.h5
-rw-r--r--fpdfsdk/fpdf_formfill.cpp32
-rw-r--r--fpdfsdk/fpdf_formfill_embeddertest.cpp77
-rw-r--r--fpdfsdk/fpdf_view_c_api_test.c4
-rw-r--r--fpdfsdk/ipdfsdk_annothandler.h4
-rw-r--r--fpdfsdk/pwl/cpwl_combo_box.cpp16
-rw-r--r--fpdfsdk/pwl/cpwl_combo_box.h4
-rw-r--r--fpdfsdk/pwl/cpwl_edit_ctrl.cpp14
-rw-r--r--fpdfsdk/pwl/cpwl_edit_ctrl.h8
-rw-r--r--fpdfsdk/pwl/cpwl_wnd.cpp16
-rw-r--r--fpdfsdk/pwl/cpwl_wnd.h6
-rw-r--r--public/fpdf_formfill.h58
-rw-r--r--xfa/fxfa/cxfa_ffwidgethandler.cpp16
-rw-r--r--xfa/fxfa/cxfa_ffwidgethandler.h5
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);