1 // Copyright 2014 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/formfiller/cffl_interactiveformfiller.h"
8
9 #include "core/fpdfapi/page/cpdf_page.h"
10 #include "core/fpdfapi/parser/cpdf_document.h"
11 #include "core/fxcrt/autorestorer.h"
12 #include "core/fxge/cfx_graphstatedata.h"
13 #include "core/fxge/cfx_pathdata.h"
14 #include "core/fxge/cfx_renderdevice.h"
15 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
16 #include "fpdfsdk/cpdfsdk_interform.h"
17 #include "fpdfsdk/cpdfsdk_pageview.h"
18 #include "fpdfsdk/cpdfsdk_widget.h"
19 #include "fpdfsdk/formfiller/cffl_checkbox.h"
20 #include "fpdfsdk/formfiller/cffl_combobox.h"
21 #include "fpdfsdk/formfiller/cffl_formfiller.h"
22 #include "fpdfsdk/formfiller/cffl_listbox.h"
23 #include "fpdfsdk/formfiller/cffl_pushbutton.h"
24 #include "fpdfsdk/formfiller/cffl_radiobutton.h"
25 #include "fpdfsdk/formfiller/cffl_textfield.h"
26 #include "third_party/base/stl_util.h"
27
CFFL_InteractiveFormFiller(CPDFSDK_FormFillEnvironment * pFormFillEnv)28 CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller(
29 CPDFSDK_FormFillEnvironment* pFormFillEnv)
30 : m_pFormFillEnv(pFormFillEnv), m_bNotifying(false) {}
31
~CFFL_InteractiveFormFiller()32 CFFL_InteractiveFormFiller::~CFFL_InteractiveFormFiller() {}
33
Annot_HitTest(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,const CFX_PointF & point)34 bool CFFL_InteractiveFormFiller::Annot_HitTest(CPDFSDK_PageView* pPageView,
35 CPDFSDK_Annot* pAnnot,
36 const CFX_PointF& point) {
37 return pAnnot->GetRect().Contains(point);
38 }
39
GetViewBBox(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot)40 FX_RECT CFFL_InteractiveFormFiller::GetViewBBox(CPDFSDK_PageView* pPageView,
41 CPDFSDK_Annot* pAnnot) {
42 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false))
43 return pFormFiller->GetViewBBox(pPageView, pAnnot);
44
45 ASSERT(pPageView);
46
47 CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
48 CFX_FloatRect rcWin = pPDFAnnot->GetRect();
49 if (!rcWin.IsEmpty()) {
50 rcWin.Inflate(1, 1);
51 rcWin.Normalize();
52 }
53 return rcWin.GetOuterRect();
54 }
55
OnDraw(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot,CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)56 void CFFL_InteractiveFormFiller::OnDraw(CPDFSDK_PageView* pPageView,
57 CPDFSDK_Annot* pAnnot,
58 CFX_RenderDevice* pDevice,
59 CFX_Matrix* pUser2Device) {
60 ASSERT(pPageView);
61 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
62 if (!IsVisible(pWidget))
63 return;
64
65 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
66 if (pFormFiller && pFormFiller->IsValid()) {
67 pFormFiller->OnDraw(pPageView, pAnnot, pDevice, *pUser2Device);
68 pAnnot->GetPDFPage();
69
70 if (m_pFormFillEnv->GetFocusAnnot() != pAnnot)
71 return;
72
73 CFX_FloatRect rcFocus = pFormFiller->GetFocusBox(pPageView);
74 if (rcFocus.IsEmpty())
75 return;
76
77 CFX_PathData path;
78 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::MoveTo,
79 false);
80 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.bottom),
81 FXPT_TYPE::LineTo, false);
82 path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.bottom),
83 FXPT_TYPE::LineTo, false);
84 path.AppendPoint(CFX_PointF(rcFocus.right, rcFocus.top), FXPT_TYPE::LineTo,
85 false);
86 path.AppendPoint(CFX_PointF(rcFocus.left, rcFocus.top), FXPT_TYPE::LineTo,
87 false);
88
89 CFX_GraphStateData gsd;
90 gsd.SetDashCount(1);
91 gsd.m_DashArray[0] = 1.0f;
92 gsd.m_DashPhase = 0;
93 gsd.m_LineWidth = 1.0f;
94 pDevice->DrawPath(&path, pUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
95 FXFILL_ALTERNATE);
96 return;
97 }
98
99 pFormFiller = GetFormFiller(pAnnot, false);
100 if (pFormFiller) {
101 pFormFiller->OnDrawDeactive(pPageView, pAnnot, pDevice, *pUser2Device);
102 } else {
103 pWidget->DrawAppearance(pDevice, *pUser2Device, CPDF_Annot::Normal,
104 nullptr);
105 }
106
107 if (!IsReadOnly(pWidget) && IsFillingAllowed(pWidget))
108 pWidget->DrawShadow(pDevice, pPageView);
109 }
110
OnDelete(CPDFSDK_Annot * pAnnot)111 void CFFL_InteractiveFormFiller::OnDelete(CPDFSDK_Annot* pAnnot) {
112 UnRegisterFormFiller(pAnnot);
113 }
114
OnMouseEnter(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlag)115 void CFFL_InteractiveFormFiller::OnMouseEnter(
116 CPDFSDK_PageView* pPageView,
117 CPDFSDK_Annot::ObservedPtr* pAnnot,
118 uint32_t nFlag) {
119 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
120 if (!m_bNotifying) {
121 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
122 if (pWidget->GetAAction(CPDF_AAction::CursorEnter).GetDict()) {
123 m_bNotifying = true;
124
125 uint32_t nValueAge = pWidget->GetValueAge();
126 pWidget->ClearAppModified();
127 ASSERT(pPageView);
128
129 PDFSDK_FieldAction fa;
130 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
131 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
132 pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView);
133 m_bNotifying = false;
134 if (!(*pAnnot))
135 return;
136
137 if (pWidget->IsAppModified()) {
138 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
139 pFormFiller->ResetPDFWindow(pPageView,
140 pWidget->GetValueAge() == nValueAge);
141 }
142 }
143 }
144 }
145 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true))
146 pFormFiller->OnMouseEnter(pPageView, pAnnot->Get());
147 }
148
OnMouseExit(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlag)149 void CFFL_InteractiveFormFiller::OnMouseExit(CPDFSDK_PageView* pPageView,
150 CPDFSDK_Annot::ObservedPtr* pAnnot,
151 uint32_t nFlag) {
152 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
153 if (!m_bNotifying) {
154 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
155 if (pWidget->GetAAction(CPDF_AAction::CursorExit).GetDict()) {
156 m_bNotifying = true;
157
158 uint32_t nValueAge = pWidget->GetValueAge();
159 pWidget->ClearAppModified();
160 ASSERT(pPageView);
161
162 PDFSDK_FieldAction fa;
163 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
164 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
165 pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView);
166 m_bNotifying = false;
167 if (!(*pAnnot))
168 return;
169
170 if (pWidget->IsAppModified()) {
171 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
172 pFormFiller->ResetPDFWindow(pPageView,
173 nValueAge == pWidget->GetValueAge());
174 }
175 }
176 }
177 }
178 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false))
179 pFormFiller->OnMouseExit(pPageView, pAnnot->Get());
180 }
181
OnLButtonDown(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)182 bool CFFL_InteractiveFormFiller::OnLButtonDown(
183 CPDFSDK_PageView* pPageView,
184 CPDFSDK_Annot::ObservedPtr* pAnnot,
185 uint32_t nFlags,
186 const CFX_PointF& point) {
187 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
188 if (!m_bNotifying) {
189 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
190 if (Annot_HitTest(pPageView, pAnnot->Get(), point) &&
191 pWidget->GetAAction(CPDF_AAction::ButtonDown).GetDict()) {
192 m_bNotifying = true;
193
194 uint32_t nValueAge = pWidget->GetValueAge();
195 pWidget->ClearAppModified();
196 ASSERT(pPageView);
197
198 PDFSDK_FieldAction fa;
199 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlags);
200 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlags);
201 pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView);
202 m_bNotifying = false;
203 if (!(*pAnnot))
204 return true;
205
206 if (!IsValidAnnot(pPageView, pAnnot->Get()))
207 return true;
208
209 if (pWidget->IsAppModified()) {
210 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false)) {
211 pFormFiller->ResetPDFWindow(pPageView,
212 nValueAge == pWidget->GetValueAge());
213 }
214 }
215 }
216 }
217 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
218 return pFormFiller &&
219 pFormFiller->OnLButtonDown(pPageView, pAnnot->Get(), nFlags, point);
220 }
221
OnLButtonUp(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)222 bool CFFL_InteractiveFormFiller::OnLButtonUp(CPDFSDK_PageView* pPageView,
223 CPDFSDK_Annot::ObservedPtr* pAnnot,
224 uint32_t nFlags,
225 const CFX_PointF& point) {
226 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
227 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
228
229 bool bSetFocus;
230 switch (pWidget->GetFieldType()) {
231 case FormFieldType::kPushButton:
232 case FormFieldType::kCheckBox:
233 case FormFieldType::kRadioButton: {
234 FX_RECT bbox = GetViewBBox(pPageView, pAnnot->Get());
235 bSetFocus =
236 bbox.Contains(static_cast<int>(point.x), static_cast<int>(point.y));
237 break;
238 }
239 default:
240 bSetFocus = true;
241 break;
242 }
243 if (bSetFocus)
244 m_pFormFillEnv->SetFocusAnnot(pAnnot);
245
246 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
247 bool bRet = pFormFiller &&
248 pFormFiller->OnLButtonUp(pPageView, pAnnot->Get(), nFlags, point);
249 if (m_pFormFillEnv->GetFocusAnnot() != pAnnot->Get())
250 return bRet;
251 if (OnButtonUp(pAnnot, pPageView, nFlags) || !pAnnot)
252 return true;
253 #ifdef PDF_ENABLE_XFA
254 if (OnClick(pAnnot, pPageView, nFlags) || !pAnnot)
255 return true;
256 #endif // PDF_ENABLE_XFA
257 return bRet;
258 }
259
OnButtonUp(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)260 bool CFFL_InteractiveFormFiller::OnButtonUp(CPDFSDK_Annot::ObservedPtr* pAnnot,
261 CPDFSDK_PageView* pPageView,
262 uint32_t nFlag) {
263 if (m_bNotifying)
264 return false;
265
266 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
267 if (!pWidget->GetAAction(CPDF_AAction::ButtonUp).GetDict())
268 return false;
269
270 m_bNotifying = true;
271
272 uint32_t nAge = pWidget->GetAppearanceAge();
273 uint32_t nValueAge = pWidget->GetValueAge();
274 ASSERT(pPageView);
275
276 PDFSDK_FieldAction fa;
277 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
278 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
279 pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView);
280 m_bNotifying = false;
281 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
282 return true;
283 if (nAge == pWidget->GetAppearanceAge())
284 return false;
285
286 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
287 if (pFormFiller)
288 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
289 return true;
290 }
291
OnLButtonDblClk(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)292 bool CFFL_InteractiveFormFiller::OnLButtonDblClk(
293 CPDFSDK_PageView* pPageView,
294 CPDFSDK_Annot::ObservedPtr* pAnnot,
295 uint32_t nFlags,
296 const CFX_PointF& point) {
297 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
298 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
299 return pFormFiller &&
300 pFormFiller->OnLButtonDblClk(pPageView, pAnnot->Get(), nFlags, point);
301 }
302
OnMouseMove(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)303 bool CFFL_InteractiveFormFiller::OnMouseMove(CPDFSDK_PageView* pPageView,
304 CPDFSDK_Annot::ObservedPtr* pAnnot,
305 uint32_t nFlags,
306 const CFX_PointF& point) {
307 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
308 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true);
309 return pFormFiller &&
310 pFormFiller->OnMouseMove(pPageView, pAnnot->Get(), nFlags, point);
311 }
312
OnMouseWheel(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,short zDelta,const CFX_PointF & point)313 bool CFFL_InteractiveFormFiller::OnMouseWheel(
314 CPDFSDK_PageView* pPageView,
315 CPDFSDK_Annot::ObservedPtr* pAnnot,
316 uint32_t nFlags,
317 short zDelta,
318 const CFX_PointF& point) {
319 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
320 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
321 return pFormFiller &&
322 pFormFiller->OnMouseWheel(pPageView, pAnnot->Get(), nFlags, zDelta,
323 point);
324 }
325
OnRButtonDown(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)326 bool CFFL_InteractiveFormFiller::OnRButtonDown(
327 CPDFSDK_PageView* pPageView,
328 CPDFSDK_Annot::ObservedPtr* pAnnot,
329 uint32_t nFlags,
330 const CFX_PointF& point) {
331 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
332 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
333 return pFormFiller &&
334 pFormFiller->OnRButtonDown(pPageView, pAnnot->Get(), nFlags, point);
335 }
336
OnRButtonUp(CPDFSDK_PageView * pPageView,CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlags,const CFX_PointF & point)337 bool CFFL_InteractiveFormFiller::OnRButtonUp(CPDFSDK_PageView* pPageView,
338 CPDFSDK_Annot::ObservedPtr* pAnnot,
339 uint32_t nFlags,
340 const CFX_PointF& point) {
341 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
342 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
343 return pFormFiller &&
344 pFormFiller->OnRButtonUp(pPageView, pAnnot->Get(), nFlags, point);
345 }
346
OnKeyDown(CPDFSDK_Annot * pAnnot,uint32_t nKeyCode,uint32_t nFlags)347 bool CFFL_InteractiveFormFiller::OnKeyDown(CPDFSDK_Annot* pAnnot,
348 uint32_t nKeyCode,
349 uint32_t nFlags) {
350 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
351
352 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
353 return pFormFiller && pFormFiller->OnKeyDown(pAnnot, nKeyCode, nFlags);
354 }
355
OnChar(CPDFSDK_Annot * pAnnot,uint32_t nChar,uint32_t nFlags)356 bool CFFL_InteractiveFormFiller::OnChar(CPDFSDK_Annot* pAnnot,
357 uint32_t nChar,
358 uint32_t nFlags) {
359 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
360 if (nChar == FWL_VKEY_Tab)
361 return true;
362
363 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
364 return pFormFiller && pFormFiller->OnChar(pAnnot, nChar, nFlags);
365 }
366
OnSetFocus(CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlag)367 bool CFFL_InteractiveFormFiller::OnSetFocus(CPDFSDK_Annot::ObservedPtr* pAnnot,
368 uint32_t nFlag) {
369 if (!(*pAnnot))
370 return false;
371
372 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
373 if (!m_bNotifying) {
374 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
375 if (pWidget->GetAAction(CPDF_AAction::GetFocus).GetDict()) {
376 m_bNotifying = true;
377
378 uint32_t nValueAge = pWidget->GetValueAge();
379 pWidget->ClearAppModified();
380
381 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, true);
382 if (!pFormFiller)
383 return false;
384
385 CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView();
386 ASSERT(pPageView);
387
388 PDFSDK_FieldAction fa;
389 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
390 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
391 pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa);
392 pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView);
393 m_bNotifying = false;
394 if (!(*pAnnot))
395 return false;
396
397 if (pWidget->IsAppModified()) {
398 if (CFFL_FormFiller* pFiller = GetFormFiller(pWidget, false)) {
399 pFiller->ResetPDFWindow(pPageView,
400 nValueAge == pWidget->GetValueAge());
401 }
402 }
403 }
404 }
405
406 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), true))
407 pFormFiller->SetFocusForAnnot(pAnnot->Get(), nFlag);
408
409 return true;
410 }
411
OnKillFocus(CPDFSDK_Annot::ObservedPtr * pAnnot,uint32_t nFlag)412 bool CFFL_InteractiveFormFiller::OnKillFocus(CPDFSDK_Annot::ObservedPtr* pAnnot,
413 uint32_t nFlag) {
414 if (!(*pAnnot))
415 return false;
416
417 ASSERT((*pAnnot)->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
418 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot->Get(), false);
419 if (!pFormFiller)
420 return true;
421
422 pFormFiller->KillFocusForAnnot(pAnnot->Get(), nFlag);
423 if (!(*pAnnot))
424 return false;
425
426 if (m_bNotifying)
427 return true;
428
429 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
430 if (!pWidget->GetAAction(CPDF_AAction::LoseFocus).GetDict())
431 return true;
432
433 m_bNotifying = true;
434 pWidget->ClearAppModified();
435
436 CPDFSDK_PageView* pPageView = pWidget->GetPageView();
437 ASSERT(pPageView);
438
439 PDFSDK_FieldAction fa;
440 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
441 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
442 pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa);
443 pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView);
444 m_bNotifying = false;
445 return !!(*pAnnot);
446 }
447
IsVisible(CPDFSDK_Widget * pWidget)448 bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) {
449 return pWidget->IsVisible();
450 }
451
IsReadOnly(CPDFSDK_Widget * pWidget)452 bool CFFL_InteractiveFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) {
453 int nFieldFlags = pWidget->GetFieldFlags();
454 return (nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY;
455 }
456
IsFillingAllowed(CPDFSDK_Widget * pWidget)457 bool CFFL_InteractiveFormFiller::IsFillingAllowed(CPDFSDK_Widget* pWidget) {
458 if (pWidget->GetFieldType() == FormFieldType::kPushButton)
459 return false;
460
461 CPDF_Page* pPage = pWidget->GetPDFPage();
462 uint32_t dwPermissions = pPage->m_pDocument->GetUserPermissions();
463 return (dwPermissions & FPDFPERM_FILL_FORM) ||
464 (dwPermissions & FPDFPERM_ANNOT_FORM) ||
465 (dwPermissions & FPDFPERM_MODIFY);
466 }
467
GetFormFiller(CPDFSDK_Annot * pAnnot,bool bRegister)468 CFFL_FormFiller* CFFL_InteractiveFormFiller::GetFormFiller(
469 CPDFSDK_Annot* pAnnot,
470 bool bRegister) {
471 auto it = m_Maps.find(pAnnot);
472 if (it != m_Maps.end())
473 return it->second.get();
474
475 if (!bRegister)
476 return nullptr;
477
478 // TODO(thestig): How do we know |pAnnot| is a CPDFSDK_Widget?
479 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot);
480 FormFieldType fieldType = pWidget->GetFieldType();
481 CFFL_FormFiller* pFormFiller;
482 switch (fieldType) {
483 case FormFieldType::kPushButton:
484 pFormFiller = new CFFL_PushButton(m_pFormFillEnv.Get(), pWidget);
485 break;
486 case FormFieldType::kCheckBox:
487 pFormFiller = new CFFL_CheckBox(m_pFormFillEnv.Get(), pWidget);
488 break;
489 case FormFieldType::kRadioButton:
490 pFormFiller = new CFFL_RadioButton(m_pFormFillEnv.Get(), pWidget);
491 break;
492 case FormFieldType::kTextField:
493 pFormFiller = new CFFL_TextField(m_pFormFillEnv.Get(), pWidget);
494 break;
495 case FormFieldType::kListBox:
496 pFormFiller = new CFFL_ListBox(m_pFormFillEnv.Get(), pWidget);
497 break;
498 case FormFieldType::kComboBox:
499 pFormFiller = new CFFL_ComboBox(m_pFormFillEnv.Get(), pWidget);
500 break;
501 case FormFieldType::kUnknown:
502 default:
503 pFormFiller = nullptr;
504 break;
505 }
506
507 if (!pFormFiller)
508 return nullptr;
509
510 m_Maps[pAnnot].reset(pFormFiller);
511 return pFormFiller;
512 }
513
GetSelectedText(CPDFSDK_Annot * pAnnot)514 WideString CFFL_InteractiveFormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) {
515 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
516 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
517 return pFormFiller ? pFormFiller->GetSelectedText(pAnnot) : WideString();
518 }
519
ReplaceSelection(CPDFSDK_Annot * pAnnot,const WideString & text)520 void CFFL_InteractiveFormFiller::ReplaceSelection(CPDFSDK_Annot* pAnnot,
521 const WideString& text) {
522 ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
523 CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
524 if (!pFormFiller)
525 return;
526
527 pFormFiller->ReplaceSelection(pAnnot, text);
528 }
529
UnRegisterFormFiller(CPDFSDK_Annot * pAnnot)530 void CFFL_InteractiveFormFiller::UnRegisterFormFiller(CPDFSDK_Annot* pAnnot) {
531 auto it = m_Maps.find(pAnnot);
532 if (it == m_Maps.end())
533 return;
534
535 m_Maps.erase(it);
536 }
537
QueryWherePopup(CPWL_Wnd::PrivateData * pAttached,float fPopupMin,float fPopupMax,bool * bBottom,float * fPopupRet)538 void CFFL_InteractiveFormFiller::QueryWherePopup(
539 CPWL_Wnd::PrivateData* pAttached,
540 float fPopupMin,
541 float fPopupMax,
542 bool* bBottom,
543 float* fPopupRet) {
544 auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
545 CPDFSDK_Widget* pWidget = pData->pWidget;
546 CPDF_Page* pPage = pWidget->GetPDFPage();
547
548 CFX_FloatRect rcPageView(0, pPage->GetPageHeight(), pPage->GetPageWidth(), 0);
549 rcPageView.Normalize();
550
551 CFX_FloatRect rcAnnot = pWidget->GetRect();
552 float fTop = 0.0f;
553 float fBottom = 0.0f;
554 switch (pWidget->GetRotate() / 90) {
555 default:
556 case 0:
557 fTop = rcPageView.top - rcAnnot.top;
558 fBottom = rcAnnot.bottom - rcPageView.bottom;
559 break;
560 case 1:
561 fTop = rcAnnot.left - rcPageView.left;
562 fBottom = rcPageView.right - rcAnnot.right;
563 break;
564 case 2:
565 fTop = rcAnnot.bottom - rcPageView.bottom;
566 fBottom = rcPageView.top - rcAnnot.top;
567 break;
568 case 3:
569 fTop = rcPageView.right - rcAnnot.right;
570 fBottom = rcAnnot.left - rcPageView.left;
571 break;
572 }
573
574 constexpr float kMaxListBoxHeight = 140;
575 const float fMaxListBoxHeight =
576 pdfium::clamp(kMaxListBoxHeight, fPopupMin, fPopupMax);
577
578 if (fBottom > fMaxListBoxHeight) {
579 *fPopupRet = fMaxListBoxHeight;
580 *bBottom = true;
581 return;
582 }
583
584 if (fTop > fMaxListBoxHeight) {
585 *fPopupRet = fMaxListBoxHeight;
586 *bBottom = false;
587 return;
588 }
589
590 if (fTop > fBottom) {
591 *fPopupRet = fTop;
592 *bBottom = false;
593 } else {
594 *fPopupRet = fBottom;
595 *bBottom = true;
596 }
597 }
598
OnKeyStrokeCommit(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)599 bool CFFL_InteractiveFormFiller::OnKeyStrokeCommit(
600 CPDFSDK_Annot::ObservedPtr* pAnnot,
601 CPDFSDK_PageView* pPageView,
602 uint32_t nFlag) {
603 if (m_bNotifying)
604 return true;
605
606 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
607 if (!pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict())
608 return true;
609
610 ASSERT(pPageView);
611 m_bNotifying = true;
612 pWidget->ClearAppModified();
613
614 PDFSDK_FieldAction fa;
615 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
616 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
617 fa.bWillCommit = true;
618 fa.bKeyDown = true;
619 fa.bRC = true;
620
621 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
622 pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa);
623 pFormFiller->SaveState(pPageView);
624 pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView);
625 if (!(*pAnnot))
626 return true;
627
628 m_bNotifying = false;
629 return fa.bRC;
630 }
631
OnValidate(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)632 bool CFFL_InteractiveFormFiller::OnValidate(CPDFSDK_Annot::ObservedPtr* pAnnot,
633 CPDFSDK_PageView* pPageView,
634 uint32_t nFlag) {
635 if (m_bNotifying)
636 return true;
637
638 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
639 if (!pWidget->GetAAction(CPDF_AAction::Validate).GetDict())
640 return true;
641
642 ASSERT(pPageView);
643 m_bNotifying = true;
644 pWidget->ClearAppModified();
645
646 PDFSDK_FieldAction fa;
647 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
648 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
649 fa.bKeyDown = true;
650 fa.bRC = true;
651
652 CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
653 pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa);
654 pFormFiller->SaveState(pPageView);
655 pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView);
656 if (!(*pAnnot))
657 return true;
658
659 m_bNotifying = false;
660 return fa.bRC;
661 }
662
OnCalculate(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)663 void CFFL_InteractiveFormFiller::OnCalculate(CPDFSDK_Annot::ObservedPtr* pAnnot,
664 CPDFSDK_PageView* pPageView,
665 uint32_t nFlag) {
666 if (m_bNotifying)
667 return;
668
669 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
670 if (pWidget) {
671 CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm();
672 pInterForm->OnCalculate(pWidget->GetFormField());
673 }
674 m_bNotifying = false;
675 }
676
OnFormat(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)677 void CFFL_InteractiveFormFiller::OnFormat(CPDFSDK_Annot::ObservedPtr* pAnnot,
678 CPDFSDK_PageView* pPageView,
679 uint32_t nFlag) {
680 if (m_bNotifying)
681 return;
682
683 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
684 ASSERT(pWidget);
685 CPDFSDK_InterForm* pInterForm = pPageView->GetFormFillEnv()->GetInterForm();
686
687 bool bFormatted = false;
688 WideString sValue = pInterForm->OnFormat(pWidget->GetFormField(), bFormatted);
689 if (!(*pAnnot))
690 return;
691
692 if (bFormatted) {
693 pInterForm->ResetFieldAppearance(pWidget->GetFormField(), &sValue, true);
694 pInterForm->UpdateField(pWidget->GetFormField());
695 }
696
697 m_bNotifying = false;
698 }
699
700 #ifdef PDF_ENABLE_XFA
OnClick(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)701 bool CFFL_InteractiveFormFiller::OnClick(CPDFSDK_Annot::ObservedPtr* pAnnot,
702 CPDFSDK_PageView* pPageView,
703 uint32_t nFlag) {
704 if (m_bNotifying)
705 return false;
706
707 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
708 if (!pWidget->HasXFAAAction(PDFSDK_XFA_Click))
709 return false;
710
711 m_bNotifying = true;
712 uint32_t nAge = pWidget->GetAppearanceAge();
713 uint32_t nValueAge = pWidget->GetValueAge();
714
715 PDFSDK_FieldAction fa;
716 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
717 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
718
719 pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView);
720 m_bNotifying = false;
721 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
722 return true;
723 if (nAge == pWidget->GetAppearanceAge())
724 return false;
725
726 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
727 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
728 return false;
729 }
730
OnFull(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)731 bool CFFL_InteractiveFormFiller::OnFull(CPDFSDK_Annot::ObservedPtr* pAnnot,
732 CPDFSDK_PageView* pPageView,
733 uint32_t nFlag) {
734 if (m_bNotifying)
735 return false;
736
737 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
738 if (!pWidget->HasXFAAAction(PDFSDK_XFA_Full))
739 return false;
740
741 m_bNotifying = true;
742 uint32_t nAge = pWidget->GetAppearanceAge();
743 uint32_t nValueAge = pWidget->GetValueAge();
744
745 PDFSDK_FieldAction fa;
746 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
747 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
748
749 pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView);
750 m_bNotifying = false;
751 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
752 return true;
753 if (nAge == pWidget->GetAppearanceAge())
754 return false;
755
756 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
757 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
758
759 return true;
760 }
761
OnPopupPreOpen(CPWL_Wnd::PrivateData * pAttached,uint32_t nFlag)762 bool CFFL_InteractiveFormFiller::OnPopupPreOpen(
763 CPWL_Wnd::PrivateData* pAttached,
764 uint32_t nFlag) {
765 auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
766 ASSERT(pData);
767 ASSERT(pData->pWidget);
768
769 CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
770 return OnPreOpen(&pObserved, pData->pPageView, nFlag) || !pObserved;
771 }
772
OnPopupPostOpen(CPWL_Wnd::PrivateData * pAttached,uint32_t nFlag)773 bool CFFL_InteractiveFormFiller::OnPopupPostOpen(
774 CPWL_Wnd::PrivateData* pAttached,
775 uint32_t nFlag) {
776 auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
777 ASSERT(pData);
778 ASSERT(pData->pWidget);
779
780 CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
781 return OnPostOpen(&pObserved, pData->pPageView, nFlag) || !pObserved;
782 }
783
OnPreOpen(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)784 bool CFFL_InteractiveFormFiller::OnPreOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
785 CPDFSDK_PageView* pPageView,
786 uint32_t nFlag) {
787 if (m_bNotifying)
788 return false;
789
790 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
791 if (!pWidget->HasXFAAAction(PDFSDK_XFA_PreOpen))
792 return false;
793
794 m_bNotifying = true;
795 uint32_t nAge = pWidget->GetAppearanceAge();
796 uint32_t nValueAge = pWidget->GetValueAge();
797
798 PDFSDK_FieldAction fa;
799 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
800 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
801
802 pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView);
803 m_bNotifying = false;
804 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
805 return true;
806 if (nAge == pWidget->GetAppearanceAge())
807 return false;
808
809 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
810 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
811
812 return true;
813 }
814
OnPostOpen(CPDFSDK_Annot::ObservedPtr * pAnnot,CPDFSDK_PageView * pPageView,uint32_t nFlag)815 bool CFFL_InteractiveFormFiller::OnPostOpen(CPDFSDK_Annot::ObservedPtr* pAnnot,
816 CPDFSDK_PageView* pPageView,
817 uint32_t nFlag) {
818 if (m_bNotifying)
819 return false;
820
821 CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pAnnot->Get());
822 if (!pWidget->HasXFAAAction(PDFSDK_XFA_PostOpen))
823 return false;
824
825 m_bNotifying = true;
826 uint32_t nAge = pWidget->GetAppearanceAge();
827 uint32_t nValueAge = pWidget->GetValueAge();
828
829 PDFSDK_FieldAction fa;
830 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
831 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
832
833 pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView);
834 m_bNotifying = false;
835 if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
836 return true;
837 if (nAge == pWidget->GetAppearanceAge())
838 return false;
839
840 if (CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false))
841 pFormFiller->ResetPDFWindow(pPageView, nValueAge == pWidget->GetValueAge());
842
843 return true;
844 }
845 #endif // PDF_ENABLE_XFA
846
IsValidAnnot(CPDFSDK_PageView * pPageView,CPDFSDK_Annot * pAnnot)847 bool CFFL_InteractiveFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView,
848 CPDFSDK_Annot* pAnnot) {
849 return pPageView && pPageView->IsValidAnnot(pAnnot->GetPDFAnnot());
850 }
851
OnBeforeKeyStroke(CPWL_Wnd::PrivateData * pAttached,WideString & strChange,const WideString & strChangeEx,int nSelStart,int nSelEnd,bool bKeyDown,uint32_t nFlag)852 std::pair<bool, bool> CFFL_InteractiveFormFiller::OnBeforeKeyStroke(
853 CPWL_Wnd::PrivateData* pAttached,
854 WideString& strChange,
855 const WideString& strChangeEx,
856 int nSelStart,
857 int nSelEnd,
858 bool bKeyDown,
859 uint32_t nFlag) {
860 // Copy the private data since the window owning it may not survive.
861 CFFL_PrivateData privateData = *static_cast<CFFL_PrivateData*>(pAttached);
862 ASSERT(privateData.pWidget);
863
864 CFFL_FormFiller* pFormFiller = GetFormFiller(privateData.pWidget, false);
865
866 #ifdef PDF_ENABLE_XFA
867 if (pFormFiller->IsFieldFull(privateData.pPageView)) {
868 CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget);
869 if (OnFull(&pObserved, privateData.pPageView, nFlag) || !pObserved)
870 return {true, true};
871 }
872 #endif // PDF_ENABLE_XFA
873
874 if (m_bNotifying ||
875 !privateData.pWidget->GetAAction(CPDF_AAction::KeyStroke).GetDict()) {
876 return {true, false};
877 }
878
879 AutoRestorer<bool> restorer(&m_bNotifying);
880 m_bNotifying = true;
881
882 uint32_t nAge = privateData.pWidget->GetAppearanceAge();
883 uint32_t nValueAge = privateData.pWidget->GetValueAge();
884 CPDFSDK_FormFillEnvironment* pFormFillEnv =
885 privateData.pPageView->GetFormFillEnv();
886
887 PDFSDK_FieldAction fa;
888 fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
889 fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
890 fa.sChange = strChange;
891 fa.sChangeEx = strChangeEx;
892 fa.bKeyDown = bKeyDown;
893 fa.bWillCommit = false;
894 fa.bRC = true;
895 fa.nSelStart = nSelStart;
896 fa.nSelEnd = nSelEnd;
897 pFormFiller->GetActionData(privateData.pPageView, CPDF_AAction::KeyStroke,
898 fa);
899 pFormFiller->SaveState(privateData.pPageView);
900
901 CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget);
902 bool action_status = privateData.pWidget->OnAAction(
903 CPDF_AAction::KeyStroke, fa, privateData.pPageView);
904
905 if (!pObserved || !IsValidAnnot(privateData.pPageView, privateData.pWidget))
906 return {true, true};
907
908 if (!action_status)
909 return {true, false};
910
911 bool bExit = false;
912 if (nAge != privateData.pWidget->GetAppearanceAge()) {
913 CPWL_Wnd* pWnd = pFormFiller->ResetPDFWindow(
914 privateData.pPageView, nValueAge == privateData.pWidget->GetValueAge());
915 if (!pWnd)
916 return {true, true};
917 privateData = *static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
918 bExit = true;
919 }
920 if (fa.bRC) {
921 pFormFiller->SetActionData(privateData.pPageView, CPDF_AAction::KeyStroke,
922 fa);
923 } else {
924 pFormFiller->RestoreState(privateData.pPageView);
925 }
926 if (pFormFillEnv->GetFocusAnnot() == privateData.pWidget)
927 return {false, bExit};
928
929 pFormFiller->CommitData(privateData.pPageView, nFlag);
930 return {false, true};
931 }
932