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