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