1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/cpdfsdk_widgethandler.h"
8
9 #include <memory>
10 #include <vector>
11
12 #include "constants/form_flags.h"
13 #include "core/fpdfapi/page/cpdf_page.h"
14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfdoc/cpdf_interactiveform.h"
16 #include "fpdfsdk/cpdfsdk_annot.h"
17 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
18 #include "fpdfsdk/cpdfsdk_interactiveform.h"
19 #include "fpdfsdk/cpdfsdk_pageview.h"
20 #include "fpdfsdk/cpdfsdk_widget.h"
21 #include "fpdfsdk/formfiller/cffl_formfiller.h"
22
23 CPDFSDK_WidgetHandler::CPDFSDK_WidgetHandler() = default;
24
25 CPDFSDK_WidgetHandler::~CPDFSDK_WidgetHandler() = default;
26
SetFormFillEnvironment(CPDFSDK_FormFillEnvironment * pFormFillEnv)27 void CPDFSDK_WidgetHandler::SetFormFillEnvironment(
28 CPDFSDK_FormFillEnvironment* pFormFillEnv) {
29 m_pFormFillEnv = pFormFillEnv;
30 m_pFormFiller = m_pFormFillEnv->GetInteractiveFormFiller();
31 }
32
CanAnswer(CPDFSDK_Annot * pAnnot)33 bool CPDFSDK_WidgetHandler::CanAnswer(CPDFSDK_Annot* pAnnot) {
34 CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot);
35 if (pWidget->IsSignatureWidget())
36 return false;
37
38 if (!pWidget->IsVisible())
39 return false;
40
41 int nFieldFlags = pWidget->GetFieldFlags();
42 if (nFieldFlags & pdfium::form_flags::kReadOnly)
43 return false;
44
45 if (pWidget->GetFieldType() == FormFieldType::kPushButton)
46 return true;
47
48 CPDF_Page* pPage = pWidget->GetPDFPage();
49 uint32_t dwPermissions = pPage->GetDocument()->GetUserPermissions();
50 return (dwPermissions & FPDFPERM_FILL_FORM) ||
51 (dwPermissions & FPDFPERM_ANNOT_FORM);
52 }
53
NewAnnot(CPDF_Annot * pAnnot,CPDFSDK_PageView * pPage)54 CPDFSDK_Annot* CPDFSDK_WidgetHandler::NewAnnot(CPDF_Annot* pAnnot,
55 CPDFSDK_PageView* pPage) {
56 CPDFSDK_InteractiveForm* pForm = m_pFormFillEnv->GetInteractiveForm();
57 CPDF_InteractiveForm* pPDFForm = pForm->GetInteractiveForm();
58 CPDF_FormControl* pCtrl = pPDFForm->GetControlByDict(pAnnot->GetAnnotDict());
59 if (!pCtrl)
60 return nullptr;
61
62 CPDFSDK_Widget* pWidget = new CPDFSDK_Widget(pAnnot, pPage, pForm);
63 pForm->AddMap(pCtrl, pWidget);
64 if (pPDFForm->NeedConstructAP())
65 pWidget->ResetAppearance(pdfium::nullopt, false);
66 return pWidget;
67 }
68
ReleaseAnnot(std::unique_ptr<CPDFSDK_Annot> pAnnot)69 void CPDFSDK_WidgetHandler::ReleaseAnnot(
70 std::unique_ptr<CPDFSDK_Annot> pAnnot) {
71 ASSERT(pAnnot);
72 m_pFormFiller->OnDelete(pAnnot.get());
73
74 std::unique_ptr<CPDFSDK_Widget> pWidget(ToCPDFSDKWidget(pAnnot.release()));
75 CPDFSDK_InteractiveForm* pForm = pWidget->GetInteractiveForm();
76 CPDF_FormControl* pControl = pWidget->GetFormControl();
77 pForm->RemoveMap(pControl);
78 }
79
OnDraw(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device,bool bDrawAnnots)80 void CPDFSDK_WidgetHandler::OnDraw(CPDFSDK_PageView* pPageView,
81 CPDFSDK_Annot* pAnnot,
82 CFX_RenderDevice* pDevice,
83 const CFX_Matrix& mtUser2Device,
84 bool bDrawAnnots) {
85 if (pAnnot->IsSignatureWidget()) {
86 pAnnot->AsBAAnnot()->DrawAppearance(pDevice, mtUser2Device,
87 CPDF_Annot::Normal, nullptr);
88 } else {
89 m_pFormFiller->OnDraw(pPageView, pAnnot, pDevice, mtUser2Device);
90 }
91 }
92
OnMouseEnter(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlag)93 void CPDFSDK_WidgetHandler::OnMouseEnter(CPDFSDK_PageView* pPageView,
94 ObservedPtr<CPDFSDK_Annot>* pAnnot,
95 uint32_t nFlag) {
96 if (!(*pAnnot)->IsSignatureWidget())
97 m_pFormFiller->OnMouseEnter(pPageView, pAnnot, nFlag);
98 }
99
OnMouseExit(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlag)100 void CPDFSDK_WidgetHandler::OnMouseExit(CPDFSDK_PageView* pPageView,
101 ObservedPtr<CPDFSDK_Annot>* pAnnot,
102 uint32_t nFlag) {
103 if (!(*pAnnot)->IsSignatureWidget())
104 m_pFormFiller->OnMouseExit(pPageView, pAnnot, nFlag);
105 }
106
OnLButtonDown(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)107 bool CPDFSDK_WidgetHandler::OnLButtonDown(CPDFSDK_PageView* pPageView,
108 ObservedPtr<CPDFSDK_Annot>* pAnnot,
109 uint32_t nFlags,
110 const CFX_PointF& point) {
111 return !(*pAnnot)->IsSignatureWidget() &&
112 m_pFormFiller->OnLButtonDown(pPageView, pAnnot, nFlags, point);
113 }
114
OnLButtonUp(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)115 bool CPDFSDK_WidgetHandler::OnLButtonUp(CPDFSDK_PageView* pPageView,
116 ObservedPtr<CPDFSDK_Annot>* pAnnot,
117 uint32_t nFlags,
118 const CFX_PointF& point) {
119 return !(*pAnnot)->IsSignatureWidget() &&
120 m_pFormFiller->OnLButtonUp(pPageView, pAnnot, nFlags, point);
121 }
122
OnLButtonDblClk(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)123 bool CPDFSDK_WidgetHandler::OnLButtonDblClk(CPDFSDK_PageView* pPageView,
124 ObservedPtr<CPDFSDK_Annot>* pAnnot,
125 uint32_t nFlags,
126 const CFX_PointF& point) {
127 return !(*pAnnot)->IsSignatureWidget() &&
128 m_pFormFiller->OnLButtonDblClk(pPageView, pAnnot, nFlags, point);
129 }
130
OnMouseMove(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)131 bool CPDFSDK_WidgetHandler::OnMouseMove(CPDFSDK_PageView* pPageView,
132 ObservedPtr<CPDFSDK_Annot>* pAnnot,
133 uint32_t nFlags,
134 const CFX_PointF& point) {
135 return !(*pAnnot)->IsSignatureWidget() &&
136 m_pFormFiller->OnMouseMove(pPageView, pAnnot, nFlags, point);
137 }
138
OnMouseWheel(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,short zDelta,const CFX_PointF & point)139 bool CPDFSDK_WidgetHandler::OnMouseWheel(CPDFSDK_PageView* pPageView,
140 ObservedPtr<CPDFSDK_Annot>* pAnnot,
141 uint32_t nFlags,
142 short zDelta,
143 const CFX_PointF& point) {
144 return !(*pAnnot)->IsSignatureWidget() &&
145 m_pFormFiller->OnMouseWheel(pPageView, pAnnot, nFlags, zDelta, point);
146 }
147
OnRButtonDown(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)148 bool CPDFSDK_WidgetHandler::OnRButtonDown(CPDFSDK_PageView* pPageView,
149 ObservedPtr<CPDFSDK_Annot>* pAnnot,
150 uint32_t nFlags,
151 const CFX_PointF& point) {
152 return !(*pAnnot)->IsSignatureWidget() &&
153 m_pFormFiller->OnRButtonDown(pPageView, pAnnot, nFlags, point);
154 }
155
OnRButtonUp(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)156 bool CPDFSDK_WidgetHandler::OnRButtonUp(CPDFSDK_PageView* pPageView,
157 ObservedPtr<CPDFSDK_Annot>* pAnnot,
158 uint32_t nFlags,
159 const CFX_PointF& point) {
160 return !(*pAnnot)->IsSignatureWidget() &&
161 m_pFormFiller->OnRButtonUp(pPageView, pAnnot, nFlags, point);
162 }
163
OnRButtonDblClk(CPDFSDK_PageView * pPageView,ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlags,const CFX_PointF & point)164 bool CPDFSDK_WidgetHandler::OnRButtonDblClk(CPDFSDK_PageView* pPageView,
165 ObservedPtr<CPDFSDK_Annot>* pAnnot,
166 uint32_t nFlags,
167 const CFX_PointF& point) {
168 return false;
169 }
170
OnChar(CPDFSDK_Annot * pAnnot,uint32_t nChar,uint32_t nFlags)171 bool CPDFSDK_WidgetHandler::OnChar(CPDFSDK_Annot* pAnnot,
172 uint32_t nChar,
173 uint32_t nFlags) {
174 return !pAnnot->IsSignatureWidget() &&
175 m_pFormFiller->OnChar(pAnnot, nChar, nFlags);
176 }
177
OnKeyDown(CPDFSDK_Annot * pAnnot,int nKeyCode,int nFlag)178 bool CPDFSDK_WidgetHandler::OnKeyDown(CPDFSDK_Annot* pAnnot,
179 int nKeyCode,
180 int nFlag) {
181 return !pAnnot->IsSignatureWidget() &&
182 m_pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlag);
183 }
184
OnKeyUp(CPDFSDK_Annot * pAnnot,int nKeyCode,int nFlag)185 bool CPDFSDK_WidgetHandler::OnKeyUp(CPDFSDK_Annot* pAnnot,
186 int nKeyCode,
187 int nFlag) {
188 return false;
189 }
190
OnLoad(CPDFSDK_Annot * pAnnot)191 void CPDFSDK_WidgetHandler::OnLoad(CPDFSDK_Annot* pAnnot) {
192 if (pAnnot->IsSignatureWidget())
193 return;
194
195 CPDFSDK_Widget* pWidget = ToCPDFSDKWidget(pAnnot);
196 if (!pWidget->IsAppearanceValid())
197 pWidget->ResetAppearance(pdfium::nullopt, false);
198
199 FormFieldType fieldType = pWidget->GetFieldType();
200 if (fieldType == FormFieldType::kTextField ||
201 fieldType == FormFieldType::kComboBox) {
202 ObservedPtr<CPDFSDK_Annot> pObserved(pWidget);
203 Optional<WideString> sValue = pWidget->OnFormat();
204 if (!pObserved)
205 return;
206
207 if (sValue.has_value() && fieldType == FormFieldType::kComboBox)
208 pWidget->ResetAppearance(sValue, false);
209 }
210
211 #ifdef PDF_ENABLE_XFA
212 CPDFSDK_PageView* pPageView = pAnnot->GetPageView();
213 auto* pContext = pPageView->GetFormFillEnv()->GetDocExtension();
214 if (pContext && pContext->ContainsExtensionForegroundForm()) {
215 if (!pWidget->IsAppearanceValid() && !pWidget->GetValue().IsEmpty())
216 pWidget->ResetXFAAppearance(false);
217 }
218 #endif // PDF_ENABLE_XFA
219 }
220
OnSetFocus(ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlag)221 bool CPDFSDK_WidgetHandler::OnSetFocus(ObservedPtr<CPDFSDK_Annot>* pAnnot,
222 uint32_t nFlag) {
223 return (*pAnnot)->IsSignatureWidget() ||
224 m_pFormFiller->OnSetFocus(pAnnot, nFlag);
225 }
226
OnKillFocus(ObservedPtr<CPDFSDK_Annot> * pAnnot,uint32_t nFlag)227 bool CPDFSDK_WidgetHandler::OnKillFocus(ObservedPtr<CPDFSDK_Annot>* pAnnot,
228 uint32_t nFlag) {
229 return (*pAnnot)->IsSignatureWidget() ||
230 m_pFormFiller->OnKillFocus(pAnnot, nFlag);
231 }
232
SetIndexSelected(ObservedPtr<CPDFSDK_Annot> * pAnnot,int index,bool selected)233 bool CPDFSDK_WidgetHandler::SetIndexSelected(ObservedPtr<CPDFSDK_Annot>* pAnnot,
234 int index,
235 bool selected) {
236 return !(*pAnnot)->IsSignatureWidget() &&
237 m_pFormFiller->SetIndexSelected(pAnnot, index, selected);
238 }
239
IsIndexSelected(ObservedPtr<CPDFSDK_Annot> * pAnnot,int index)240 bool CPDFSDK_WidgetHandler::IsIndexSelected(ObservedPtr<CPDFSDK_Annot>* pAnnot,
241 int index) {
242 return !(*pAnnot)->IsSignatureWidget() &&
243 m_pFormFiller->IsIndexSelected(pAnnot, index);
244 }
245
GetViewBBox(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot)246 CFX_FloatRect CPDFSDK_WidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView,
247 CPDFSDK_Annot* pAnnot) {
248 if (!pAnnot->IsSignatureWidget())
249 return CFX_FloatRect(m_pFormFiller->GetViewBBox(pPageView, pAnnot));
250 return CFX_FloatRect();
251 }
252
GetText(CPDFSDK_Annot * pAnnot)253 WideString CPDFSDK_WidgetHandler::GetText(CPDFSDK_Annot* pAnnot) {
254 if (!pAnnot->IsSignatureWidget())
255 return m_pFormFiller->GetText(pAnnot);
256 return WideString();
257 }
258
GetSelectedText(CPDFSDK_Annot * pAnnot)259 WideString CPDFSDK_WidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
260 if (!pAnnot->IsSignatureWidget())
261 return m_pFormFiller->GetSelectedText(pAnnot);
262 return WideString();
263 }
264
ReplaceSelection(CPDFSDK_Annot * pAnnot,const WideString & text)265 void CPDFSDK_WidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot,
266 const WideString& text) {
267 if (!pAnnot->IsSignatureWidget())
268 m_pFormFiller->ReplaceSelection(pAnnot, text);
269 }
270
CanUndo(CPDFSDK_Annot * pAnnot)271 bool CPDFSDK_WidgetHandler::CanUndo(CPDFSDK_Annot* pAnnot) {
272 return !pAnnot->IsSignatureWidget() && m_pFormFiller->CanUndo(pAnnot);
273 }
274
CanRedo(CPDFSDK_Annot * pAnnot)275 bool CPDFSDK_WidgetHandler::CanRedo(CPDFSDK_Annot* pAnnot) {
276 return !pAnnot->IsSignatureWidget() && m_pFormFiller->CanRedo(pAnnot);
277 }
278
Undo(CPDFSDK_Annot * pAnnot)279 bool CPDFSDK_WidgetHandler::Undo(CPDFSDK_Annot* pAnnot) {
280 return !pAnnot->IsSignatureWidget() && m_pFormFiller->Undo(pAnnot);
281 }
282
Redo(CPDFSDK_Annot * pAnnot)283 bool CPDFSDK_WidgetHandler::Redo(CPDFSDK_Annot* pAnnot) {
284 return !pAnnot->IsSignatureWidget() && m_pFormFiller->Redo(pAnnot);
285 }
286
HitTest(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,const CFX_PointF & point)287 bool CPDFSDK_WidgetHandler::HitTest(CPDFSDK_PageView* pPageView,
288 CPDFSDK_Annot* pAnnot,
289 const CFX_PointF& point) {
290 ASSERT(pPageView);
291 ASSERT(pAnnot);
292 return GetViewBBox(pPageView, pAnnot).Contains(point);
293 }
294