Home | History | Annotate | Download | only in app
      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 "xfa/fxfa/xfa_ffdocview.h"
      8 
      9 #include "core/fxcrt/fx_ext.h"
     10 #include "third_party/base/ptr_util.h"
     11 #include "third_party/base/stl_util.h"
     12 #include "xfa/fxfa/app/xfa_ffbarcode.h"
     13 #include "xfa/fxfa/app/xfa_ffcheckbutton.h"
     14 #include "xfa/fxfa/app/xfa_ffchoicelist.h"
     15 #include "xfa/fxfa/app/xfa_ffdraw.h"
     16 #include "xfa/fxfa/app/xfa_ffexclgroup.h"
     17 #include "xfa/fxfa/app/xfa_fffield.h"
     18 #include "xfa/fxfa/app/xfa_ffimage.h"
     19 #include "xfa/fxfa/app/xfa_ffimageedit.h"
     20 #include "xfa/fxfa/app/xfa_ffpath.h"
     21 #include "xfa/fxfa/app/xfa_ffpushbutton.h"
     22 #include "xfa/fxfa/app/xfa_ffsignature.h"
     23 #include "xfa/fxfa/app/xfa_ffsubform.h"
     24 #include "xfa/fxfa/app/xfa_fftext.h"
     25 #include "xfa/fxfa/app/xfa_fftextedit.h"
     26 #include "xfa/fxfa/app/xfa_ffwidgetacc.h"
     27 #include "xfa/fxfa/app/xfa_fwladapter.h"
     28 #include "xfa/fxfa/parser/cxfa_binditems.h"
     29 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
     30 #include "xfa/fxfa/parser/cxfa_scriptcontext.h"
     31 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
     32 #include "xfa/fxfa/xfa_ffapp.h"
     33 #include "xfa/fxfa/xfa_ffdoc.h"
     34 #include "xfa/fxfa/xfa_ffpageview.h"
     35 #include "xfa/fxfa/xfa_ffwidget.h"
     36 #include "xfa/fxfa/xfa_ffwidgethandler.h"
     37 
     38 const XFA_ATTRIBUTEENUM gs_EventActivity[] = {
     39     XFA_ATTRIBUTEENUM_Click,      XFA_ATTRIBUTEENUM_Change,
     40     XFA_ATTRIBUTEENUM_DocClose,   XFA_ATTRIBUTEENUM_DocReady,
     41     XFA_ATTRIBUTEENUM_Enter,      XFA_ATTRIBUTEENUM_Exit,
     42     XFA_ATTRIBUTEENUM_Full,       XFA_ATTRIBUTEENUM_IndexChange,
     43     XFA_ATTRIBUTEENUM_Initialize, XFA_ATTRIBUTEENUM_MouseDown,
     44     XFA_ATTRIBUTEENUM_MouseEnter, XFA_ATTRIBUTEENUM_MouseExit,
     45     XFA_ATTRIBUTEENUM_MouseUp,    XFA_ATTRIBUTEENUM_PostExecute,
     46     XFA_ATTRIBUTEENUM_PostOpen,   XFA_ATTRIBUTEENUM_PostPrint,
     47     XFA_ATTRIBUTEENUM_PostSave,   XFA_ATTRIBUTEENUM_PostSign,
     48     XFA_ATTRIBUTEENUM_PostSubmit, XFA_ATTRIBUTEENUM_PreExecute,
     49     XFA_ATTRIBUTEENUM_PreOpen,    XFA_ATTRIBUTEENUM_PrePrint,
     50     XFA_ATTRIBUTEENUM_PreSave,    XFA_ATTRIBUTEENUM_PreSign,
     51     XFA_ATTRIBUTEENUM_PreSubmit,  XFA_ATTRIBUTEENUM_Ready,
     52     XFA_ATTRIBUTEENUM_Unknown,
     53 };
     54 
     55 CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc)
     56     : m_bLayoutEvent(false),
     57       m_pListFocusWidget(nullptr),
     58       m_bInLayoutStatus(false),
     59       m_pDoc(pDoc),
     60       m_pXFADocLayout(nullptr),
     61       m_pFocusAcc(nullptr),
     62       m_pFocusWidget(nullptr),
     63       m_pOldFocusWidget(nullptr),
     64       m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None),
     65       m_iLock(0) {}
     66 
     67 CXFA_FFDocView::~CXFA_FFDocView() {
     68   DestroyDocView();
     69 }
     70 
     71 void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
     72   RunBindItems();
     73   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true,
     74                                nullptr);
     75   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true,
     76                                nullptr);
     77 }
     78 int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) {
     79   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
     80   m_pDoc->GetXFADoc()->DoProtoMerge();
     81   m_pDoc->GetXFADoc()->DoDataMerge();
     82   m_pXFADocLayout = GetXFALayout();
     83   int32_t iStatus = m_pXFADocLayout->StartLayout();
     84   if (iStatus < 0) {
     85     return iStatus;
     86   }
     87   CXFA_Node* pRootItem =
     88       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
     89   if (!pRootItem) {
     90     return iStatus;
     91   }
     92   InitLayout(pRootItem);
     93   InitCalculate(pRootItem);
     94   InitValidate(pRootItem);
     95   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr);
     96   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
     97   return iStatus;
     98 }
     99 int32_t CXFA_FFDocView::DoLayout(IFX_Pause* pPause) {
    100   int32_t iStatus = 100;
    101   iStatus = m_pXFADocLayout->DoLayout(pPause);
    102   if (iStatus != 100) {
    103     return iStatus;
    104   }
    105   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing;
    106   return iStatus;
    107 }
    108 void CXFA_FFDocView::StopLayout() {
    109   CXFA_Node* pRootItem =
    110       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
    111   if (!pRootItem) {
    112     return;
    113   }
    114   CXFA_Node* pSubformNode = pRootItem->GetChild(0, XFA_Element::Subform);
    115   if (!pSubformNode) {
    116     return;
    117   }
    118   CXFA_Node* pPageSetNode =
    119       pSubformNode->GetFirstChildByClass(XFA_Element::PageSet);
    120   if (!pPageSetNode) {
    121     return;
    122   }
    123   RunCalculateWidgets();
    124   RunValidate();
    125   InitLayout(pPageSetNode);
    126   InitCalculate(pPageSetNode);
    127   InitValidate(pPageSetNode);
    128   ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true,
    129                                nullptr);
    130   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
    131                                nullptr);
    132   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true,
    133                                nullptr);
    134   RunCalculateWidgets();
    135   RunValidate();
    136   if (RunLayout()) {
    137     ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
    138                                  nullptr);
    139   }
    140   m_CalculateAccs.clear();
    141   if (m_pFocusAcc && !m_pFocusWidget) {
    142     SetFocusWidgetAcc(m_pFocusAcc);
    143   }
    144   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End;
    145 }
    146 int32_t CXFA_FFDocView::GetLayoutStatus() {
    147   return m_iStatus;
    148 }
    149 void CXFA_FFDocView::ShowNullTestMsg() {
    150   int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg);
    151   CXFA_FFApp* pApp = m_pDoc->GetApp();
    152   IXFA_AppProvider* pAppProvider = pApp->GetAppProvider();
    153   if (pAppProvider && iCount) {
    154     int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
    155     iCount -= iRemain;
    156     CFX_WideString wsMsg;
    157     for (int32_t i = 0; i < iCount; i++) {
    158       wsMsg += m_arrNullTestMsg[i] + L"\n";
    159     }
    160     if (iRemain > 0) {
    161       CFX_WideString wsTemp;
    162       wsTemp.Format(
    163           L"Message limit exceeded. Remaining %d "
    164           L"validation errors not reported.",
    165           iRemain);
    166       wsMsg += L"\n" + wsTemp;
    167     }
    168     pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status,
    169                          XFA_MB_OK);
    170   }
    171   m_arrNullTestMsg.clear();
    172 }
    173 
    174 void CXFA_FFDocView::UpdateDocView() {
    175   if (IsUpdateLocked())
    176     return;
    177 
    178   LockUpdate();
    179   for (CXFA_Node* pNode : m_NewAddedNodes) {
    180     InitCalculate(pNode);
    181     InitValidate(pNode);
    182     ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr);
    183   }
    184   m_NewAddedNodes.clear();
    185   RunSubformIndexChange();
    186   RunCalculateWidgets();
    187   RunValidate();
    188   ShowNullTestMsg();
    189   if (RunLayout() && m_bLayoutEvent)
    190     RunEventLayoutReady();
    191 
    192   m_bLayoutEvent = false;
    193   m_CalculateAccs.clear();
    194   RunInvalidate();
    195   UnlockUpdate();
    196 }
    197 
    198 int32_t CXFA_FFDocView::CountPageViews() {
    199   if (!m_pXFADocLayout) {
    200     return 0;
    201   }
    202   return m_pXFADocLayout->CountPages();
    203 }
    204 CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) {
    205   if (!m_pXFADocLayout) {
    206     return nullptr;
    207   }
    208   return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex));
    209 }
    210 
    211 CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const {
    212   return m_pDoc->GetXFADoc()->GetDocLayout();
    213 }
    214 bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) {
    215   CXFA_Node* pNode = pWidgetAcc->GetNode();
    216   XFA_Element eType = pNode->GetElementType();
    217   if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) {
    218     return false;
    219   }
    220   pWidgetAcc->ResetData();
    221   pWidgetAcc->UpdateUIDisplay();
    222   if (CXFA_Validate validate = pWidgetAcc->GetValidate()) {
    223     AddValidateWidget(pWidgetAcc);
    224     validate.GetNode()->SetFlag(XFA_NodeFlag_NeedsInitApp, false);
    225   }
    226   return true;
    227 }
    228 void CXFA_FFDocView::ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc) {
    229   m_bLayoutEvent = true;
    230   bool bChanged = false;
    231   CXFA_Node* pFormNode = nullptr;
    232   if (pWidgetAcc) {
    233     bChanged = ResetSingleWidgetAccData(pWidgetAcc);
    234     pFormNode = pWidgetAcc->GetNode();
    235   } else {
    236     pFormNode = GetRootSubform();
    237   }
    238   if (!pFormNode) {
    239     return;
    240   }
    241   if (pFormNode->GetElementType() != XFA_Element::Field &&
    242       pFormNode->GetElementType() != XFA_Element::ExclGroup) {
    243     CXFA_WidgetAccIterator Iterator(this, pFormNode);
    244     while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) {
    245       bChanged |= ResetSingleWidgetAccData(pAcc);
    246       if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup) {
    247         Iterator.SkipTree();
    248       }
    249     }
    250   }
    251   if (bChanged) {
    252     m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc);
    253   }
    254 }
    255 int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam,
    256                                            CXFA_WidgetAcc* pWidgetAcc) {
    257   if (!pParam)
    258     return XFA_EVENTERROR_Error;
    259 
    260   if (pParam->m_eType == XFA_EVENT_Validate) {
    261     CFX_WideString wsValidateStr(L"preSubmit");
    262     CXFA_Node* pConfigItem =
    263         ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config));
    264     if (pConfigItem) {
    265       CXFA_Node* pValidateNode = nullptr;
    266       CXFA_Node* pAcrobatNode = pConfigItem->GetChild(0, XFA_Element::Acrobat);
    267       pValidateNode = pAcrobatNode
    268                           ? pAcrobatNode->GetChild(0, XFA_Element::Validate)
    269                           : nullptr;
    270       if (!pValidateNode) {
    271         CXFA_Node* pPresentNode =
    272             pConfigItem->GetChild(0, XFA_Element::Present);
    273         pValidateNode = pPresentNode
    274                             ? pPresentNode->GetChild(0, XFA_Element::Validate)
    275                             : nullptr;
    276       }
    277       if (pValidateNode) {
    278         wsValidateStr = pValidateNode->GetContent();
    279       }
    280     }
    281     bool bValidate = false;
    282     switch (pParam->m_iValidateActivities) {
    283       case XFA_VALIDATE_preSubmit:
    284         bValidate = wsValidateStr.Find(L"preSubmit") != -1;
    285         break;
    286       case XFA_VALIDATE_prePrint:
    287         bValidate = wsValidateStr.Find(L"prePrint") != -1;
    288         break;
    289       case XFA_VALIDATE_preExecute:
    290         bValidate = wsValidateStr.Find(L"preExecute") != -1;
    291         break;
    292       case XFA_VALIDATE_preSave:
    293         bValidate = wsValidateStr.Find(L"preSave") != -1;
    294         break;
    295     }
    296     if (!bValidate) {
    297       return XFA_EVENTERROR_Success;
    298     }
    299   }
    300   CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr;
    301   if (!pNode) {
    302     CXFA_Node* pRootItem =
    303         ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
    304     if (!pRootItem) {
    305       return XFA_EVENTERROR_Error;
    306     }
    307     pNode = pRootItem->GetChild(0, XFA_Element::Subform);
    308   }
    309   ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady,
    310                                true, nullptr);
    311   return XFA_EVENTERROR_Success;
    312 }
    313 CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
    314   if (!m_pWidgetHandler)
    315     m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this);
    316 
    317   return m_pWidgetHandler.get();
    318 }
    319 
    320 CXFA_WidgetAccIterator* CXFA_FFDocView::CreateWidgetAccIterator(
    321     XFA_WIDGETORDER eOrder) {
    322   CXFA_Node* pFormRoot = GetRootSubform();
    323   return pFormRoot ? new CXFA_WidgetAccIterator(this, pFormRoot) : nullptr;
    324 }
    325 CXFA_FFWidget* CXFA_FFDocView::GetFocusWidget() {
    326   return m_pFocusWidget;
    327 }
    328 void CXFA_FFDocView::KillFocus() {
    329   if (m_pFocusWidget &&
    330       (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) {
    331     (m_pFocusWidget)->OnKillFocus(nullptr);
    332   }
    333   m_pFocusAcc = nullptr;
    334   m_pFocusWidget = nullptr;
    335   m_pOldFocusWidget = nullptr;
    336 }
    337 bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) {
    338   CXFA_FFWidget* pNewFocus = hWidget;
    339   if (m_pOldFocusWidget == pNewFocus) {
    340     return false;
    341   }
    342   CXFA_FFWidget* pOldFocus = m_pOldFocusWidget;
    343   m_pOldFocusWidget = pNewFocus;
    344   if (pOldFocus) {
    345     if (m_pFocusWidget != m_pOldFocusWidget &&
    346         (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) {
    347       m_pFocusWidget = pOldFocus;
    348       pOldFocus->OnKillFocus(pNewFocus);
    349     } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
    350       if (!pOldFocus->IsLoaded()) {
    351         pOldFocus->LoadWidget();
    352       }
    353       pOldFocus->OnSetFocus(m_pFocusWidget);
    354       m_pFocusWidget = pOldFocus;
    355       pOldFocus->OnKillFocus(pNewFocus);
    356     }
    357   }
    358   if (m_pFocusWidget == m_pOldFocusWidget) {
    359     return false;
    360   }
    361   pNewFocus = m_pOldFocusWidget;
    362   if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) {
    363     m_pFocusAcc = nullptr;
    364     m_pFocusWidget = nullptr;
    365     m_pListFocusWidget = nullptr;
    366     m_pOldFocusWidget = nullptr;
    367     return false;
    368   }
    369   if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
    370     if (!pNewFocus->IsLoaded()) {
    371       pNewFocus->LoadWidget();
    372     }
    373     pNewFocus->OnSetFocus(m_pFocusWidget);
    374   }
    375   m_pFocusAcc = pNewFocus ? pNewFocus->GetDataAcc() : nullptr;
    376   m_pFocusWidget = pNewFocus;
    377   m_pOldFocusWidget = m_pFocusWidget;
    378   return true;
    379 }
    380 CXFA_WidgetAcc* CXFA_FFDocView::GetFocusWidgetAcc() {
    381   return m_pFocusAcc;
    382 }
    383 void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
    384   CXFA_FFWidget* pNewFocus =
    385       pWidgetAcc ? pWidgetAcc->GetNextWidget(nullptr) : nullptr;
    386   if (SetFocus(pNewFocus)) {
    387     m_pFocusAcc = pWidgetAcc;
    388     if (m_iStatus == XFA_DOCVIEW_LAYOUTSTATUS_End) {
    389       m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc, m_pFocusWidget);
    390     }
    391   }
    392 }
    393 void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
    394   if (m_pFocusAcc == pWidget->GetDataAcc()) {
    395     m_pFocusAcc = nullptr;
    396     m_pFocusWidget = nullptr;
    397     m_pOldFocusWidget = nullptr;
    398   }
    399 }
    400 static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView,
    401                                 CXFA_WidgetAcc* pWidgetAcc,
    402                                 CXFA_EventParam* pParam) {
    403   if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) {
    404     return XFA_EVENTERROR_NotExist;
    405   }
    406   if (!pWidgetAcc || pWidgetAcc->GetElementType() == XFA_Element::Draw) {
    407     return XFA_EVENTERROR_NotExist;
    408   }
    409   switch (pParam->m_eType) {
    410     case XFA_EVENT_Calculate:
    411       return pWidgetAcc->ProcessCalculate();
    412     case XFA_EVENT_Validate:
    413       if (((CXFA_FFDoc*)pDocView->GetDoc())
    414               ->GetDocEnvironment()
    415               ->IsValidationsEnabled(pDocView->GetDoc())) {
    416         return pWidgetAcc->ProcessValidate(0x01);
    417       }
    418       return XFA_EVENTERROR_Disabled;
    419     case XFA_EVENT_InitCalculate: {
    420       CXFA_Calculate calc = pWidgetAcc->GetCalculate();
    421       if (!calc) {
    422         return XFA_EVENTERROR_NotExist;
    423       }
    424       if (pWidgetAcc->GetNode()->IsUserInteractive())
    425         return XFA_EVENTERROR_Disabled;
    426 
    427       CXFA_Script script = calc.GetScript();
    428       return pWidgetAcc->ExecuteScript(script, pParam);
    429     }
    430     default:
    431       break;
    432   }
    433   int32_t iRet =
    434       pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam);
    435   return iRet;
    436 }
    437 int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
    438                                                      XFA_EVENTTYPE eEventType,
    439                                                      bool bIsFormReady,
    440                                                      bool bRecursive,
    441                                                      CXFA_Node* pExclude) {
    442   int32_t iRet = XFA_EVENTERROR_NotExist;
    443   if (pFormNode == pExclude) {
    444     return iRet;
    445   }
    446   XFA_Element elementType = pFormNode->GetElementType();
    447   if (elementType == XFA_Element::Field) {
    448     if (eEventType == XFA_EVENT_IndexChange) {
    449       return iRet;
    450     }
    451     CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData();
    452     if (!pWidgetAcc) {
    453       return iRet;
    454     }
    455     CXFA_EventParam eParam;
    456     eParam.m_eType = eEventType;
    457     eParam.m_pTarget = pWidgetAcc;
    458     eParam.m_bIsFormReady = bIsFormReady;
    459     return XFA_ProcessEvent(this, pWidgetAcc, &eParam);
    460   }
    461   if (bRecursive) {
    462     for (CXFA_Node* pNode = pFormNode->GetNodeItem(
    463              XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode);
    464          pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling,
    465                                            XFA_ObjectType::ContainerNode)) {
    466       elementType = pNode->GetElementType();
    467       if (elementType != XFA_Element::Variables &&
    468           elementType != XFA_Element::Draw) {
    469         iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
    470                                              bRecursive, pExclude);
    471       }
    472     }
    473   }
    474   CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData();
    475   if (!pWidgetAcc) {
    476     return iRet;
    477   }
    478   CXFA_EventParam eParam;
    479   eParam.m_eType = eEventType;
    480   eParam.m_pTarget = pWidgetAcc;
    481   eParam.m_bIsFormReady = bIsFormReady;
    482   iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam);
    483   return iRet;
    484 }
    485 
    486 CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const CFX_WideString& wsName,
    487                                                CXFA_FFWidget* pRefWidget) {
    488   CXFA_WidgetAcc* pRefAcc = pRefWidget ? pRefWidget->GetDataAcc() : nullptr;
    489   CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc);
    490   return pAcc ? pAcc->GetNextWidget(nullptr) : nullptr;
    491 }
    492 
    493 CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName(
    494     const CFX_WideString& wsName,
    495     CXFA_WidgetAcc* pRefWidgetAcc) {
    496   CFX_WideString wsExpression;
    497   uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    498                      XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
    499   CXFA_ScriptContext* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
    500   if (!pScriptContext) {
    501     return nullptr;
    502   }
    503   CXFA_Node* refNode = nullptr;
    504   if (pRefWidgetAcc) {
    505     refNode = pRefWidgetAcc->GetNode();
    506     wsExpression = wsName;
    507   } else {
    508     wsExpression = L"$form." + wsName;
    509   }
    510   XFA_RESOLVENODE_RS resoveNodeRS;
    511   int32_t iRet = pScriptContext->ResolveObjects(
    512       refNode, wsExpression.AsStringC(), resoveNodeRS, dwStyle);
    513   if (iRet < 1) {
    514     return nullptr;
    515   }
    516   if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
    517     CXFA_Node* pNode = resoveNodeRS.nodes[0]->AsNode();
    518     if (pNode) {
    519       return (CXFA_WidgetAcc*)pNode->GetWidgetData();
    520     }
    521   }
    522   return nullptr;
    523 }
    524 
    525 void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender,
    526                                  uint32_t dwEvent) {
    527   CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender);
    528   m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent);
    529 }
    530 
    531 void CXFA_FFDocView::LockUpdate() {
    532   m_iLock++;
    533 }
    534 void CXFA_FFDocView::UnlockUpdate() {
    535   m_iLock--;
    536 }
    537 bool CXFA_FFDocView::IsUpdateLocked() {
    538   return m_iLock > 0;
    539 }
    540 void CXFA_FFDocView::ClearInvalidateList() {
    541   m_mapPageInvalidate.clear();
    542 }
    543 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
    544                                        const CFX_RectF& rtInvalidate) {
    545   AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
    546 }
    547 
    548 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView,
    549                                        const CFX_RectF& rtInvalidate) {
    550   if (m_mapPageInvalidate[pPageView]) {
    551     m_mapPageInvalidate[pPageView]->Union(rtInvalidate);
    552     return;
    553   }
    554   m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate);
    555 }
    556 
    557 void CXFA_FFDocView::RunInvalidate() {
    558   for (const auto& pair : m_mapPageInvalidate)
    559     m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second, 0);
    560   m_mapPageInvalidate.clear();
    561 }
    562 
    563 bool CXFA_FFDocView::RunLayout() {
    564   LockUpdate();
    565   m_bInLayoutStatus = true;
    566   if (!m_pXFADocLayout->IncrementLayout() &&
    567       m_pXFADocLayout->StartLayout() < 100) {
    568     m_pXFADocLayout->DoLayout();
    569     UnlockUpdate();
    570     m_bInLayoutStatus = false;
    571     m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
    572                                                XFA_PAGEVIEWEVENT_StopLayout);
    573     return true;
    574   }
    575   m_bInLayoutStatus = false;
    576   m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
    577                                              XFA_PAGEVIEWEVENT_StopLayout);
    578   UnlockUpdate();
    579   return false;
    580 }
    581 
    582 void CXFA_FFDocView::RunSubformIndexChange() {
    583   for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) {
    584     CXFA_WidgetAcc* pWidgetAcc =
    585         static_cast<CXFA_WidgetAcc*>(pSubformNode->GetWidgetData());
    586     if (!pWidgetAcc)
    587       continue;
    588 
    589     CXFA_EventParam eParam;
    590     eParam.m_eType = XFA_EVENT_IndexChange;
    591     eParam.m_pTarget = pWidgetAcc;
    592     pWidgetAcc->ProcessEvent(XFA_ATTRIBUTEENUM_IndexChange, &eParam);
    593   }
    594   m_IndexChangedSubforms.clear();
    595 }
    596 
    597 void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
    598   m_NewAddedNodes.push_back(pNode);
    599   InitLayout(pNode);
    600 }
    601 
    602 void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
    603   ASSERT(pNode->GetElementType() == XFA_Element::Subform);
    604   m_IndexChangedSubforms.push_back(pNode);
    605 }
    606 
    607 void CXFA_FFDocView::RunDocClose() {
    608   CXFA_Node* pRootItem =
    609       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
    610   if (!pRootItem) {
    611     return;
    612   }
    613   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true,
    614                                nullptr);
    615 }
    616 void CXFA_FFDocView::DestroyDocView() {
    617   ClearInvalidateList();
    618   m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None;
    619   m_iLock = 0;
    620   m_ValidateAccs.clear();
    621   m_BindItems.clear();
    622   m_CalculateAccs.clear();
    623 }
    624 bool CXFA_FFDocView::IsStaticNotify() {
    625   return m_pDoc->GetDocType() == XFA_DOCTYPE_Static;
    626 }
    627 
    628 void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
    629   CXFA_WidgetAcc* pCurrentAcc =
    630       !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr;
    631   if (pCurrentAcc != pWidgetAcc)
    632     m_CalculateAccs.push_back(pWidgetAcc);
    633 }
    634 
    635 void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
    636   auto pGlobalData =
    637       static_cast<CXFA_CalcData*>(pNodeChange->GetUserData(XFA_CalcData));
    638   if (!pGlobalData)
    639     return;
    640 
    641   for (const auto& pResultAcc : pGlobalData->m_Globals) {
    642     if (!pResultAcc->GetNode()->HasRemovedChildren())
    643       AddCalculateWidgetAcc(pResultAcc);
    644   }
    645 }
    646 
    647 void CXFA_FFDocView::RunCalculateRecursive(int32_t& iIndex) {
    648   while (iIndex < pdfium::CollectionSize<int32_t>(m_CalculateAccs)) {
    649     CXFA_WidgetAcc* pCurAcc = m_CalculateAccs[iIndex];
    650     AddCalculateNodeNotify(pCurAcc->GetNode());
    651     int32_t iRefCount =
    652         (int32_t)(uintptr_t)pCurAcc->GetNode()->GetUserData(XFA_CalcRefCount);
    653     iRefCount++;
    654     pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount,
    655                                     (void*)(uintptr_t)iRefCount);
    656     if (iRefCount > 11) {
    657       break;
    658     }
    659     if ((pCurAcc->ProcessCalculate()) == XFA_EVENTERROR_Success) {
    660       AddValidateWidget(pCurAcc);
    661     }
    662     iIndex++;
    663     RunCalculateRecursive(iIndex);
    664   }
    665 }
    666 
    667 int32_t CXFA_FFDocView::RunCalculateWidgets() {
    668   if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc)) {
    669     return XFA_EVENTERROR_Disabled;
    670   }
    671   int32_t iCounts = pdfium::CollectionSize<int32_t>(m_CalculateAccs);
    672   int32_t iIndex = 0;
    673   if (iCounts > 0)
    674     RunCalculateRecursive(iIndex);
    675 
    676   for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs)
    677     pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, (void*)(uintptr_t)0);
    678 
    679   m_CalculateAccs.clear();
    680   return XFA_EVENTERROR_Success;
    681 }
    682 
    683 void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
    684   if (!pdfium::ContainsValue(m_ValidateAccs, pWidget))
    685     m_ValidateAccs.push_back(pWidget);
    686 }
    687 
    688 bool CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
    689   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true,
    690                                nullptr);
    691   return true;
    692 }
    693 
    694 bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
    695   if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc))
    696     return false;
    697 
    698   ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr);
    699   m_ValidateAccs.clear();
    700   return true;
    701 }
    702 
    703 bool CXFA_FFDocView::RunValidate() {
    704   if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc))
    705     return false;
    706 
    707   for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) {
    708     if (!pAcc->GetNode()->HasRemovedChildren())
    709       pAcc->ProcessValidate();
    710   }
    711   m_ValidateAccs.clear();
    712   return true;
    713 }
    714 bool CXFA_FFDocView::RunEventLayoutReady() {
    715   CXFA_Node* pRootItem =
    716       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
    717   if (!pRootItem) {
    718     return false;
    719   }
    720   ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
    721                                nullptr);
    722   RunLayout();
    723   return true;
    724 }
    725 void CXFA_FFDocView::RunBindItems() {
    726   for (const auto& item : m_BindItems) {
    727     if (item->HasRemovedChildren())
    728       continue;
    729 
    730     CXFA_Node* pWidgetNode = item->GetNodeItem(XFA_NODEITEM_Parent);
    731     CXFA_WidgetAcc* pAcc =
    732         static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData());
    733     if (!pAcc)
    734       continue;
    735 
    736     CXFA_BindItems binditems(item);
    737     CXFA_ScriptContext* pScriptContext =
    738         pWidgetNode->GetDocument()->GetScriptContext();
    739     CFX_WideStringC wsRef;
    740     binditems.GetRef(wsRef);
    741     uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    742                        XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
    743                        XFA_RESOLVENODE_ALL;
    744     XFA_RESOLVENODE_RS rs;
    745     pScriptContext->ResolveObjects(pWidgetNode, wsRef, rs, dwStyle);
    746     int32_t iCount = rs.nodes.GetSize();
    747     pAcc->DeleteItem(-1);
    748     if (rs.dwFlags != XFA_RESOVENODE_RSTYPE_Nodes || iCount < 1)
    749       continue;
    750 
    751     CFX_WideStringC wsValueRef, wsLabelRef;
    752     binditems.GetValueRef(wsValueRef);
    753     binditems.GetLabelRef(wsLabelRef);
    754     const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
    755     const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$";
    756     const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$";
    757     CFX_WideString wsValue;
    758     CFX_WideString wsLabel;
    759     uint32_t uValueHash = FX_HashCode_GetW(wsValueRef, false);
    760     for (int32_t j = 0; j < iCount; j++) {
    761       CXFA_Object* refObj = rs.nodes[j];
    762       if (!refObj->IsNode()) {
    763         continue;
    764       }
    765       CXFA_Node* refNode = refObj->AsNode();
    766       if (bValueUseContent) {
    767         wsValue = refNode->GetContent();
    768       } else {
    769         CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
    770         wsValue = nodeValue ? nodeValue->GetContent() : refNode->GetContent();
    771       }
    772       if (!bUseValue) {
    773         if (bLabelUseContent) {
    774           wsLabel = refNode->GetContent();
    775         } else {
    776           CXFA_Node* nodeLabel = refNode->GetFirstChildByName(wsLabelRef);
    777           if (nodeLabel)
    778             wsLabel = nodeLabel->GetContent();
    779         }
    780       } else {
    781         wsLabel = wsValue;
    782       }
    783       pAcc->InsertItem(wsLabel, wsValue);
    784     }
    785   }
    786   m_BindItems.clear();
    787 }
    788 void CXFA_FFDocView::SetChangeMark() {
    789   if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) {
    790     return;
    791   }
    792   m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc);
    793 }
    794 CXFA_Node* CXFA_FFDocView::GetRootSubform() {
    795   CXFA_Node* pFormPacketNode =
    796       ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
    797   if (!pFormPacketNode) {
    798     return nullptr;
    799   }
    800   return pFormPacketNode->GetFirstChildByClass(XFA_Element::Subform);
    801 }
    802 
    803 CXFA_WidgetAccIterator::CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView,
    804                                                CXFA_Node* pTravelRoot)
    805     : m_ContentIterator(pTravelRoot),
    806       m_pDocView(pDocView),
    807       m_pCurWidgetAcc(nullptr) {}
    808 
    809 CXFA_WidgetAccIterator::~CXFA_WidgetAccIterator() {}
    810 void CXFA_WidgetAccIterator::Reset() {
    811   m_pCurWidgetAcc = nullptr;
    812   m_ContentIterator.Reset();
    813 }
    814 
    815 CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToFirst() {
    816   return nullptr;
    817 }
    818 
    819 CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToLast() {
    820   return nullptr;
    821 }
    822 
    823 CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToNext() {
    824   CXFA_Node* pItem = m_pCurWidgetAcc ? m_ContentIterator.MoveToNext()
    825                                      : m_ContentIterator.GetCurrent();
    826   while (pItem) {
    827     m_pCurWidgetAcc = static_cast<CXFA_WidgetAcc*>(pItem->GetWidgetData());
    828     if (m_pCurWidgetAcc)
    829       return m_pCurWidgetAcc;
    830     pItem = m_ContentIterator.MoveToNext();
    831   }
    832   return nullptr;
    833 }
    834 
    835 CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToPrevious() {
    836   return nullptr;
    837 }
    838 
    839 CXFA_WidgetAcc* CXFA_WidgetAccIterator::GetCurrentWidgetAcc() {
    840   return nullptr;
    841 }
    842 
    843 bool CXFA_WidgetAccIterator::SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget) {
    844   return false;
    845 }
    846 
    847 void CXFA_WidgetAccIterator::SkipTree() {
    848   m_ContentIterator.SkipChildrenAndMoveToNext();
    849   m_pCurWidgetAcc = nullptr;
    850 }
    851