• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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