Home | History | Annotate | Download | only in formfiller
      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 
     29 CFFL_InteractiveFormFiller::CFFL_InteractiveFormFiller(
     30     CPDFSDK_FormFillEnvironment* pFormFillEnv)
     31     : m_pFormFillEnv(pFormFillEnv), m_bNotifying(false) {}
     32 
     33 CFFL_InteractiveFormFiller::~CFFL_InteractiveFormFiller() {}
     34 
     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 
     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 
     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 
    106 void CFFL_InteractiveFormFiller::OnDelete(CPDFSDK_Annot* pAnnot) {
    107   UnRegisterFormFiller(pAnnot);
    108 }
    109 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    450 bool CFFL_InteractiveFormFiller::IsVisible(CPDFSDK_Widget* pWidget) {
    451   return pWidget->IsVisible();
    452 }
    453 
    454 bool CFFL_InteractiveFormFiller::IsReadOnly(CPDFSDK_Widget* pWidget) {
    455   int nFieldFlags = pWidget->GetFieldFlags();
    456   return (nFieldFlags & FIELDFLAG_READONLY) == FIELDFLAG_READONLY;
    457 }
    458 
    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 
    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 
    516 void CFFL_InteractiveFormFiller::RemoveFormFiller(CPDFSDK_Annot* pAnnot) {
    517   if (pAnnot)
    518     UnRegisterFormFiller(pAnnot);
    519 }
    520 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    872 bool CFFL_InteractiveFormFiller::IsValidAnnot(CPDFSDK_PageView* pPageView,
    873                                               CPDFSDK_Annot* pAnnot) {
    874   return pPageView && pPageView->IsValidAnnot(pAnnot->GetPDFAnnot());
    875 }
    876 
    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