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
38const 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
55CXFA_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
67CXFA_FFDocView::~CXFA_FFDocView() {
68  DestroyDocView();
69}
70
71void 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}
78int32_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}
99int32_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}
108void 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}
146int32_t CXFA_FFDocView::GetLayoutStatus() {
147  return m_iStatus;
148}
149void 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
174void 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
198int32_t CXFA_FFDocView::CountPageViews() {
199  if (!m_pXFADocLayout) {
200    return 0;
201  }
202  return m_pXFADocLayout->CountPages();
203}
204CXFA_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
211CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const {
212  return m_pDoc->GetXFADoc()->GetDocLayout();
213}
214bool 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}
228void 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}
255int32_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}
313CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
314  if (!m_pWidgetHandler)
315    m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this);
316
317  return m_pWidgetHandler.get();
318}
319
320CXFA_WidgetAccIterator* CXFA_FFDocView::CreateWidgetAccIterator(
321    XFA_WIDGETORDER eOrder) {
322  CXFA_Node* pFormRoot = GetRootSubform();
323  return pFormRoot ? new CXFA_WidgetAccIterator(this, pFormRoot) : nullptr;
324}
325CXFA_FFWidget* CXFA_FFDocView::GetFocusWidget() {
326  return m_pFocusWidget;
327}
328void 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}
337bool 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}
380CXFA_WidgetAcc* CXFA_FFDocView::GetFocusWidgetAcc() {
381  return m_pFocusAcc;
382}
383void 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}
393void 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}
400static 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}
437int32_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
486CXFA_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
493CXFA_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
525void 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
531void CXFA_FFDocView::LockUpdate() {
532  m_iLock++;
533}
534void CXFA_FFDocView::UnlockUpdate() {
535  m_iLock--;
536}
537bool CXFA_FFDocView::IsUpdateLocked() {
538  return m_iLock > 0;
539}
540void CXFA_FFDocView::ClearInvalidateList() {
541  m_mapPageInvalidate.clear();
542}
543void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
544                                       const CFX_RectF& rtInvalidate) {
545  AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
546}
547
548void 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
557void 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
563bool 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
582void 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
597void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
598  m_NewAddedNodes.push_back(pNode);
599  InitLayout(pNode);
600}
601
602void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
603  ASSERT(pNode->GetElementType() == XFA_Element::Subform);
604  m_IndexChangedSubforms.push_back(pNode);
605}
606
607void 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}
616void 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}
624bool CXFA_FFDocView::IsStaticNotify() {
625  return m_pDoc->GetDocType() == XFA_DOCTYPE_Static;
626}
627
628void 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
635void 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
647void 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
667int32_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
683void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
684  if (!pdfium::ContainsValue(m_ValidateAccs, pWidget))
685    m_ValidateAccs.push_back(pWidget);
686}
687
688bool CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
689  ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true,
690                               nullptr);
691  return true;
692}
693
694bool 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
703bool 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}
714bool 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}
725void 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}
788void CXFA_FFDocView::SetChangeMark() {
789  if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) {
790    return;
791  }
792  m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc);
793}
794CXFA_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
803CXFA_WidgetAccIterator::CXFA_WidgetAccIterator(CXFA_FFDocView* pDocView,
804                                               CXFA_Node* pTravelRoot)
805    : m_ContentIterator(pTravelRoot),
806      m_pDocView(pDocView),
807      m_pCurWidgetAcc(nullptr) {}
808
809CXFA_WidgetAccIterator::~CXFA_WidgetAccIterator() {}
810void CXFA_WidgetAccIterator::Reset() {
811  m_pCurWidgetAcc = nullptr;
812  m_ContentIterator.Reset();
813}
814
815CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToFirst() {
816  return nullptr;
817}
818
819CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToLast() {
820  return nullptr;
821}
822
823CXFA_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
835CXFA_WidgetAcc* CXFA_WidgetAccIterator::MoveToPrevious() {
836  return nullptr;
837}
838
839CXFA_WidgetAcc* CXFA_WidgetAccIterator::GetCurrentWidgetAcc() {
840  return nullptr;
841}
842
843bool CXFA_WidgetAccIterator::SetCurrentWidgetAcc(CXFA_WidgetAcc* hWidget) {
844  return false;
845}
846
847void CXFA_WidgetAccIterator::SkipTree() {
848  m_ContentIterator.SkipChildrenAndMoveToNext();
849  m_pCurWidgetAcc = nullptr;
850}
851