1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdocview.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <set>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_extension.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlparser.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/gc/container_trace.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_engine.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check_op.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffapp.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffbarcode.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffcheckbutton.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdoc.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffexclgroup.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fffield.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffimage.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffimageedit.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffpageview.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffpushbutton.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffsignature.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fftext.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidget.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffwidgethandler.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_readynodeiterator.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_textprovider.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_acrobat.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_binditems.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_calculate.h"
41*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_pageset.h"
42*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_present.h"
43*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_subform.h"
44*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_validate.h"
45*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
46*3ac0a46fSAndroid Build Coastguard Worker
47*3ac0a46fSAndroid Build Coastguard Worker namespace {
48*3ac0a46fSAndroid Build Coastguard Worker
IsValidXMLNameString(const WideString & str)49*3ac0a46fSAndroid Build Coastguard Worker bool IsValidXMLNameString(const WideString& str) {
50*3ac0a46fSAndroid Build Coastguard Worker bool first = true;
51*3ac0a46fSAndroid Build Coastguard Worker for (const auto ch : str) {
52*3ac0a46fSAndroid Build Coastguard Worker if (!CFX_XMLParser::IsXMLNameChar(ch, first)) {
53*3ac0a46fSAndroid Build Coastguard Worker return false;
54*3ac0a46fSAndroid Build Coastguard Worker }
55*3ac0a46fSAndroid Build Coastguard Worker first = false;
56*3ac0a46fSAndroid Build Coastguard Worker }
57*3ac0a46fSAndroid Build Coastguard Worker return true;
58*3ac0a46fSAndroid Build Coastguard Worker }
59*3ac0a46fSAndroid Build Coastguard Worker
60*3ac0a46fSAndroid Build Coastguard Worker } // namespace
61*3ac0a46fSAndroid Build Coastguard Worker
62*3ac0a46fSAndroid Build Coastguard Worker const XFA_AttributeValue kXFAEventActivity[] = {
63*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::Click, XFA_AttributeValue::Change,
64*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::DocClose, XFA_AttributeValue::DocReady,
65*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::Enter, XFA_AttributeValue::Exit,
66*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::Full, XFA_AttributeValue::IndexChange,
67*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::Initialize, XFA_AttributeValue::MouseDown,
68*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::MouseEnter, XFA_AttributeValue::MouseExit,
69*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::MouseUp, XFA_AttributeValue::PostExecute,
70*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PostOpen, XFA_AttributeValue::PostPrint,
71*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PostSave, XFA_AttributeValue::PostSign,
72*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PostSubmit, XFA_AttributeValue::PreExecute,
73*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PreOpen, XFA_AttributeValue::PrePrint,
74*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PreSave, XFA_AttributeValue::PreSign,
75*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::PreSubmit, XFA_AttributeValue::Ready,
76*3ac0a46fSAndroid Build Coastguard Worker XFA_AttributeValue::Unknown,
77*3ac0a46fSAndroid Build Coastguard Worker };
78*3ac0a46fSAndroid Build Coastguard Worker
UpdateScope(CXFA_FFDocView * pDocView)79*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView::UpdateScope::UpdateScope(CXFA_FFDocView* pDocView)
80*3ac0a46fSAndroid Build Coastguard Worker : m_pDocView(pDocView) {
81*3ac0a46fSAndroid Build Coastguard Worker m_pDocView->LockUpdate();
82*3ac0a46fSAndroid Build Coastguard Worker }
83*3ac0a46fSAndroid Build Coastguard Worker
~UpdateScope()84*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView::UpdateScope::~UpdateScope() {
85*3ac0a46fSAndroid Build Coastguard Worker m_pDocView->UnlockUpdate();
86*3ac0a46fSAndroid Build Coastguard Worker m_pDocView->UpdateDocView();
87*3ac0a46fSAndroid Build Coastguard Worker }
88*3ac0a46fSAndroid Build Coastguard Worker
CXFA_FFDocView(CXFA_FFDoc * pDoc)89*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {}
90*3ac0a46fSAndroid Build Coastguard Worker
91*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDocView::~CXFA_FFDocView() = default;
92*3ac0a46fSAndroid Build Coastguard Worker
Trace(cppgc::Visitor * visitor) const93*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::Trace(cppgc::Visitor* visitor) const {
94*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pDoc);
95*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pWidgetHandler);
96*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pFocusNode);
97*3ac0a46fSAndroid Build Coastguard Worker visitor->Trace(m_pFocusWidget);
98*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_ValidateNodes);
99*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_CalculateNodes);
100*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_NewAddedNodes);
101*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_BindItems);
102*3ac0a46fSAndroid Build Coastguard Worker ContainerTrace(visitor, m_IndexChangedSubforms);
103*3ac0a46fSAndroid Build Coastguard Worker }
104*3ac0a46fSAndroid Build Coastguard Worker
InitLayout(CXFA_Node * pNode)105*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
106*3ac0a46fSAndroid Build Coastguard Worker RunBindItems();
107*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true);
108*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true);
109*3ac0a46fSAndroid Build Coastguard Worker }
110*3ac0a46fSAndroid Build Coastguard Worker
StartLayout()111*3ac0a46fSAndroid Build Coastguard Worker int32_t CXFA_FFDocView::StartLayout() {
112*3ac0a46fSAndroid Build Coastguard Worker m_iStatus = LayoutStatus::kStart;
113*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->GetXFADoc()->DoProtoMerge();
114*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->GetXFADoc()->DoDataMerge();
115*3ac0a46fSAndroid Build Coastguard Worker
116*3ac0a46fSAndroid Build Coastguard Worker int32_t iStatus = GetLayoutProcessor()->StartLayout();
117*3ac0a46fSAndroid Build Coastguard Worker if (iStatus < 0)
118*3ac0a46fSAndroid Build Coastguard Worker return iStatus;
119*3ac0a46fSAndroid Build Coastguard Worker
120*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRootItem =
121*3ac0a46fSAndroid Build Coastguard Worker ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
122*3ac0a46fSAndroid Build Coastguard Worker if (!pRootItem)
123*3ac0a46fSAndroid Build Coastguard Worker return iStatus;
124*3ac0a46fSAndroid Build Coastguard Worker
125*3ac0a46fSAndroid Build Coastguard Worker InitLayout(pRootItem);
126*3ac0a46fSAndroid Build Coastguard Worker InitCalculate(pRootItem);
127*3ac0a46fSAndroid Build Coastguard Worker InitValidate(pRootItem);
128*3ac0a46fSAndroid Build Coastguard Worker
129*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true);
130*3ac0a46fSAndroid Build Coastguard Worker m_iStatus = LayoutStatus::kStart;
131*3ac0a46fSAndroid Build Coastguard Worker return iStatus;
132*3ac0a46fSAndroid Build Coastguard Worker }
133*3ac0a46fSAndroid Build Coastguard Worker
DoLayout()134*3ac0a46fSAndroid Build Coastguard Worker int32_t CXFA_FFDocView::DoLayout() {
135*3ac0a46fSAndroid Build Coastguard Worker int32_t iStatus = GetLayoutProcessor()->DoLayout();
136*3ac0a46fSAndroid Build Coastguard Worker if (iStatus != 100)
137*3ac0a46fSAndroid Build Coastguard Worker return iStatus;
138*3ac0a46fSAndroid Build Coastguard Worker
139*3ac0a46fSAndroid Build Coastguard Worker m_iStatus = LayoutStatus::kDoing;
140*3ac0a46fSAndroid Build Coastguard Worker return iStatus;
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker
StopLayout()143*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::StopLayout() {
144*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRootItem =
145*3ac0a46fSAndroid Build Coastguard Worker ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
146*3ac0a46fSAndroid Build Coastguard Worker if (!pRootItem)
147*3ac0a46fSAndroid Build Coastguard Worker return;
148*3ac0a46fSAndroid Build Coastguard Worker
149*3ac0a46fSAndroid Build Coastguard Worker CXFA_Subform* pSubformNode =
150*3ac0a46fSAndroid Build Coastguard Worker pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false);
151*3ac0a46fSAndroid Build Coastguard Worker if (!pSubformNode)
152*3ac0a46fSAndroid Build Coastguard Worker return;
153*3ac0a46fSAndroid Build Coastguard Worker
154*3ac0a46fSAndroid Build Coastguard Worker CXFA_PageSet* pPageSetNode =
155*3ac0a46fSAndroid Build Coastguard Worker pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
156*3ac0a46fSAndroid Build Coastguard Worker if (!pPageSetNode)
157*3ac0a46fSAndroid Build Coastguard Worker return;
158*3ac0a46fSAndroid Build Coastguard Worker
159*3ac0a46fSAndroid Build Coastguard Worker RunCalculateWidgets();
160*3ac0a46fSAndroid Build Coastguard Worker RunValidate();
161*3ac0a46fSAndroid Build Coastguard Worker
162*3ac0a46fSAndroid Build Coastguard Worker InitLayout(pPageSetNode);
163*3ac0a46fSAndroid Build Coastguard Worker InitCalculate(pPageSetNode);
164*3ac0a46fSAndroid Build Coastguard Worker InitValidate(pPageSetNode);
165*3ac0a46fSAndroid Build Coastguard Worker
166*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true);
167*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);
168*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true);
169*3ac0a46fSAndroid Build Coastguard Worker
170*3ac0a46fSAndroid Build Coastguard Worker RunCalculateWidgets();
171*3ac0a46fSAndroid Build Coastguard Worker RunValidate();
172*3ac0a46fSAndroid Build Coastguard Worker
173*3ac0a46fSAndroid Build Coastguard Worker if (RunLayout())
174*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);
175*3ac0a46fSAndroid Build Coastguard Worker
176*3ac0a46fSAndroid Build Coastguard Worker m_CalculateNodes.clear();
177*3ac0a46fSAndroid Build Coastguard Worker if (m_pFocusNode && !m_pFocusWidget)
178*3ac0a46fSAndroid Build Coastguard Worker SetFocusNode(m_pFocusNode);
179*3ac0a46fSAndroid Build Coastguard Worker
180*3ac0a46fSAndroid Build Coastguard Worker m_iStatus = LayoutStatus::kEnd;
181*3ac0a46fSAndroid Build Coastguard Worker }
182*3ac0a46fSAndroid Build Coastguard Worker
AddNullTestMsg(const WideString & msg)183*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddNullTestMsg(const WideString& msg) {
184*3ac0a46fSAndroid Build Coastguard Worker m_NullTestMsgArray.push_back(msg);
185*3ac0a46fSAndroid Build Coastguard Worker }
186*3ac0a46fSAndroid Build Coastguard Worker
ShowNullTestMsg()187*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::ShowNullTestMsg() {
188*3ac0a46fSAndroid Build Coastguard Worker int32_t iCount = fxcrt::CollectionSize<int32_t>(m_NullTestMsgArray);
189*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFApp* pApp = m_pDoc->GetApp();
190*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFApp::CallbackIface* pAppProvider = pApp->GetAppProvider();
191*3ac0a46fSAndroid Build Coastguard Worker if (pAppProvider && iCount) {
192*3ac0a46fSAndroid Build Coastguard Worker int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
193*3ac0a46fSAndroid Build Coastguard Worker iCount -= iRemain;
194*3ac0a46fSAndroid Build Coastguard Worker WideString wsMsg;
195*3ac0a46fSAndroid Build Coastguard Worker for (int32_t i = 0; i < iCount; i++)
196*3ac0a46fSAndroid Build Coastguard Worker wsMsg += m_NullTestMsgArray[i] + L"\n";
197*3ac0a46fSAndroid Build Coastguard Worker
198*3ac0a46fSAndroid Build Coastguard Worker if (iRemain > 0) {
199*3ac0a46fSAndroid Build Coastguard Worker wsMsg += L"\n" + WideString::Format(
200*3ac0a46fSAndroid Build Coastguard Worker L"Message limit exceeded. Remaining %d "
201*3ac0a46fSAndroid Build Coastguard Worker L"validation errors not reported.",
202*3ac0a46fSAndroid Build Coastguard Worker iRemain);
203*3ac0a46fSAndroid Build Coastguard Worker }
204*3ac0a46fSAndroid Build Coastguard Worker pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(),
205*3ac0a46fSAndroid Build Coastguard Worker static_cast<uint32_t>(AlertIcon::kStatus),
206*3ac0a46fSAndroid Build Coastguard Worker static_cast<uint32_t>(AlertButton::kOK));
207*3ac0a46fSAndroid Build Coastguard Worker }
208*3ac0a46fSAndroid Build Coastguard Worker m_NullTestMsgArray.clear();
209*3ac0a46fSAndroid Build Coastguard Worker }
210*3ac0a46fSAndroid Build Coastguard Worker
UpdateDocView()211*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::UpdateDocView() {
212*3ac0a46fSAndroid Build Coastguard Worker if (IsUpdateLocked())
213*3ac0a46fSAndroid Build Coastguard Worker return;
214*3ac0a46fSAndroid Build Coastguard Worker
215*3ac0a46fSAndroid Build Coastguard Worker LockUpdate();
216*3ac0a46fSAndroid Build Coastguard Worker while (!m_NewAddedNodes.empty()) {
217*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode = m_NewAddedNodes.front();
218*3ac0a46fSAndroid Build Coastguard Worker m_NewAddedNodes.pop_front();
219*3ac0a46fSAndroid Build Coastguard Worker InitCalculate(pNode);
220*3ac0a46fSAndroid Build Coastguard Worker InitValidate(pNode);
221*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true);
222*3ac0a46fSAndroid Build Coastguard Worker }
223*3ac0a46fSAndroid Build Coastguard Worker
224*3ac0a46fSAndroid Build Coastguard Worker RunSubformIndexChange();
225*3ac0a46fSAndroid Build Coastguard Worker RunCalculateWidgets();
226*3ac0a46fSAndroid Build Coastguard Worker RunValidate();
227*3ac0a46fSAndroid Build Coastguard Worker
228*3ac0a46fSAndroid Build Coastguard Worker ShowNullTestMsg();
229*3ac0a46fSAndroid Build Coastguard Worker
230*3ac0a46fSAndroid Build Coastguard Worker if (RunLayout() && m_bLayoutEvent)
231*3ac0a46fSAndroid Build Coastguard Worker RunEventLayoutReady();
232*3ac0a46fSAndroid Build Coastguard Worker
233*3ac0a46fSAndroid Build Coastguard Worker m_bLayoutEvent = false;
234*3ac0a46fSAndroid Build Coastguard Worker m_CalculateNodes.clear();
235*3ac0a46fSAndroid Build Coastguard Worker UnlockUpdate();
236*3ac0a46fSAndroid Build Coastguard Worker }
237*3ac0a46fSAndroid Build Coastguard Worker
UpdateUIDisplay(CXFA_Node * pNode,CXFA_FFWidget * pExcept)238*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::UpdateUIDisplay(CXFA_Node* pNode, CXFA_FFWidget* pExcept) {
239*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pWidget = GetWidgetForNode(pNode);
240*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pNext = nullptr;
241*3ac0a46fSAndroid Build Coastguard Worker for (; pWidget; pWidget = pNext) {
242*3ac0a46fSAndroid Build Coastguard Worker pNext = pWidget->GetNextFFWidget();
243*3ac0a46fSAndroid Build Coastguard Worker if (pWidget == pExcept || !pWidget->IsLoaded() ||
244*3ac0a46fSAndroid Build Coastguard Worker (pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton &&
245*3ac0a46fSAndroid Build Coastguard Worker pWidget->IsFocused())) {
246*3ac0a46fSAndroid Build Coastguard Worker continue;
247*3ac0a46fSAndroid Build Coastguard Worker }
248*3ac0a46fSAndroid Build Coastguard Worker pWidget->UpdateFWLData();
249*3ac0a46fSAndroid Build Coastguard Worker pWidget->InvalidateRect();
250*3ac0a46fSAndroid Build Coastguard Worker }
251*3ac0a46fSAndroid Build Coastguard Worker }
252*3ac0a46fSAndroid Build Coastguard Worker
CountPageViews() const253*3ac0a46fSAndroid Build Coastguard Worker int32_t CXFA_FFDocView::CountPageViews() const {
254*3ac0a46fSAndroid Build Coastguard Worker CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
255*3ac0a46fSAndroid Build Coastguard Worker return pProcessor ? pProcessor->CountPages() : 0;
256*3ac0a46fSAndroid Build Coastguard Worker }
257*3ac0a46fSAndroid Build Coastguard Worker
GetPageView(int32_t nIndex) const258*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const {
259*3ac0a46fSAndroid Build Coastguard Worker CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
260*3ac0a46fSAndroid Build Coastguard Worker if (!pProcessor)
261*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
262*3ac0a46fSAndroid Build Coastguard Worker
263*3ac0a46fSAndroid Build Coastguard Worker auto* pPage = pProcessor->GetPage(nIndex);
264*3ac0a46fSAndroid Build Coastguard Worker return pPage ? pPage->GetPageView() : nullptr;
265*3ac0a46fSAndroid Build Coastguard Worker }
266*3ac0a46fSAndroid Build Coastguard Worker
GetLayoutProcessor() const267*3ac0a46fSAndroid Build Coastguard Worker CXFA_LayoutProcessor* CXFA_FFDocView::GetLayoutProcessor() const {
268*3ac0a46fSAndroid Build Coastguard Worker return CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc());
269*3ac0a46fSAndroid Build Coastguard Worker }
270*3ac0a46fSAndroid Build Coastguard Worker
ResetSingleNodeData(CXFA_Node * pNode)271*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::ResetSingleNodeData(CXFA_Node* pNode) {
272*3ac0a46fSAndroid Build Coastguard Worker XFA_Element eType = pNode->GetElementType();
273*3ac0a46fSAndroid Build Coastguard Worker if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
274*3ac0a46fSAndroid Build Coastguard Worker return false;
275*3ac0a46fSAndroid Build Coastguard Worker
276*3ac0a46fSAndroid Build Coastguard Worker pNode->ResetData();
277*3ac0a46fSAndroid Build Coastguard Worker UpdateUIDisplay(pNode, nullptr);
278*3ac0a46fSAndroid Build Coastguard Worker CXFA_Validate* validate = pNode->GetValidateIfExists();
279*3ac0a46fSAndroid Build Coastguard Worker if (!validate)
280*3ac0a46fSAndroid Build Coastguard Worker return true;
281*3ac0a46fSAndroid Build Coastguard Worker
282*3ac0a46fSAndroid Build Coastguard Worker AddValidateNode(pNode);
283*3ac0a46fSAndroid Build Coastguard Worker validate->SetFlag(XFA_NodeFlag::kNeedsInitApp);
284*3ac0a46fSAndroid Build Coastguard Worker return true;
285*3ac0a46fSAndroid Build Coastguard Worker }
286*3ac0a46fSAndroid Build Coastguard Worker
ResetNode(CXFA_Node * pNode)287*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::ResetNode(CXFA_Node* pNode) {
288*3ac0a46fSAndroid Build Coastguard Worker m_bLayoutEvent = true;
289*3ac0a46fSAndroid Build Coastguard Worker bool bChanged = false;
290*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormNode = nullptr;
291*3ac0a46fSAndroid Build Coastguard Worker if (pNode) {
292*3ac0a46fSAndroid Build Coastguard Worker bChanged = ResetSingleNodeData(pNode);
293*3ac0a46fSAndroid Build Coastguard Worker pFormNode = pNode;
294*3ac0a46fSAndroid Build Coastguard Worker } else {
295*3ac0a46fSAndroid Build Coastguard Worker pFormNode = GetRootSubform();
296*3ac0a46fSAndroid Build Coastguard Worker }
297*3ac0a46fSAndroid Build Coastguard Worker if (!pFormNode)
298*3ac0a46fSAndroid Build Coastguard Worker return;
299*3ac0a46fSAndroid Build Coastguard Worker
300*3ac0a46fSAndroid Build Coastguard Worker if (pFormNode->GetElementType() != XFA_Element::Field &&
301*3ac0a46fSAndroid Build Coastguard Worker pFormNode->GetElementType() != XFA_Element::ExclGroup) {
302*3ac0a46fSAndroid Build Coastguard Worker CXFA_ReadyNodeIterator it(pFormNode);
303*3ac0a46fSAndroid Build Coastguard Worker while (CXFA_Node* next_node = it.MoveToNext()) {
304*3ac0a46fSAndroid Build Coastguard Worker bChanged |= ResetSingleNodeData(next_node);
305*3ac0a46fSAndroid Build Coastguard Worker if (next_node->GetElementType() == XFA_Element::ExclGroup)
306*3ac0a46fSAndroid Build Coastguard Worker it.SkipTree();
307*3ac0a46fSAndroid Build Coastguard Worker }
308*3ac0a46fSAndroid Build Coastguard Worker }
309*3ac0a46fSAndroid Build Coastguard Worker if (bChanged)
310*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->SetChangeMark();
311*3ac0a46fSAndroid Build Coastguard Worker }
312*3ac0a46fSAndroid Build Coastguard Worker
GetWidgetForNode(CXFA_Node * node)313*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
314*3ac0a46fSAndroid Build Coastguard Worker return GetFFWidget(
315*3ac0a46fSAndroid Build Coastguard Worker ToContentLayoutItem(GetLayoutProcessor()->GetLayoutItem(node)));
316*3ac0a46fSAndroid Build Coastguard Worker }
317*3ac0a46fSAndroid Build Coastguard Worker
GetWidgetHandler()318*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
319*3ac0a46fSAndroid Build Coastguard Worker if (!m_pWidgetHandler) {
320*3ac0a46fSAndroid Build Coastguard Worker m_pWidgetHandler = cppgc::MakeGarbageCollected<CXFA_FFWidgetHandler>(
321*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->GetHeap()->GetAllocationHandle(), this);
322*3ac0a46fSAndroid Build Coastguard Worker }
323*3ac0a46fSAndroid Build Coastguard Worker return m_pWidgetHandler;
324*3ac0a46fSAndroid Build Coastguard Worker }
325*3ac0a46fSAndroid Build Coastguard Worker
SetFocus(CXFA_FFWidget * pNewFocus)326*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* pNewFocus) {
327*3ac0a46fSAndroid Build Coastguard Worker if (pNewFocus == m_pFocusWidget)
328*3ac0a46fSAndroid Build Coastguard Worker return false;
329*3ac0a46fSAndroid Build Coastguard Worker
330*3ac0a46fSAndroid Build Coastguard Worker if (m_pFocusWidget) {
331*3ac0a46fSAndroid Build Coastguard Worker CXFA_ContentLayoutItem* pItem = m_pFocusWidget->GetLayoutItem();
332*3ac0a46fSAndroid Build Coastguard Worker if (pItem->TestStatusBits(XFA_WidgetStatus::kVisible) &&
333*3ac0a46fSAndroid Build Coastguard Worker !pItem->TestStatusBits(XFA_WidgetStatus::kFocused)) {
334*3ac0a46fSAndroid Build Coastguard Worker if (!m_pFocusWidget->IsLoaded())
335*3ac0a46fSAndroid Build Coastguard Worker m_pFocusWidget->LoadWidget();
336*3ac0a46fSAndroid Build Coastguard Worker if (!m_pFocusWidget->OnSetFocus(m_pFocusWidget))
337*3ac0a46fSAndroid Build Coastguard Worker m_pFocusWidget.Clear();
338*3ac0a46fSAndroid Build Coastguard Worker }
339*3ac0a46fSAndroid Build Coastguard Worker }
340*3ac0a46fSAndroid Build Coastguard Worker if (m_pFocusWidget) {
341*3ac0a46fSAndroid Build Coastguard Worker if (!m_pFocusWidget->OnKillFocus(pNewFocus))
342*3ac0a46fSAndroid Build Coastguard Worker return false;
343*3ac0a46fSAndroid Build Coastguard Worker }
344*3ac0a46fSAndroid Build Coastguard Worker
345*3ac0a46fSAndroid Build Coastguard Worker if (pNewFocus) {
346*3ac0a46fSAndroid Build Coastguard Worker if (pNewFocus->GetLayoutItem()->TestStatusBits(
347*3ac0a46fSAndroid Build Coastguard Worker XFA_WidgetStatus::kVisible)) {
348*3ac0a46fSAndroid Build Coastguard Worker if (!pNewFocus->IsLoaded())
349*3ac0a46fSAndroid Build Coastguard Worker pNewFocus->LoadWidget();
350*3ac0a46fSAndroid Build Coastguard Worker if (!pNewFocus->OnSetFocus(m_pFocusWidget))
351*3ac0a46fSAndroid Build Coastguard Worker pNewFocus = nullptr;
352*3ac0a46fSAndroid Build Coastguard Worker }
353*3ac0a46fSAndroid Build Coastguard Worker }
354*3ac0a46fSAndroid Build Coastguard Worker if (pNewFocus) {
355*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* node = pNewFocus->GetNode();
356*3ac0a46fSAndroid Build Coastguard Worker m_pFocusNode = node->IsWidgetReady() ? node : nullptr;
357*3ac0a46fSAndroid Build Coastguard Worker m_pFocusWidget = pNewFocus;
358*3ac0a46fSAndroid Build Coastguard Worker } else {
359*3ac0a46fSAndroid Build Coastguard Worker m_pFocusNode.Clear();
360*3ac0a46fSAndroid Build Coastguard Worker m_pFocusWidget.Clear();
361*3ac0a46fSAndroid Build Coastguard Worker }
362*3ac0a46fSAndroid Build Coastguard Worker return true;
363*3ac0a46fSAndroid Build Coastguard Worker }
364*3ac0a46fSAndroid Build Coastguard Worker
SetFocusNode(CXFA_Node * node)365*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::SetFocusNode(CXFA_Node* node) {
366*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pNewFocus = node ? GetWidgetForNode(node) : nullptr;
367*3ac0a46fSAndroid Build Coastguard Worker if (!SetFocus(pNewFocus))
368*3ac0a46fSAndroid Build Coastguard Worker return;
369*3ac0a46fSAndroid Build Coastguard Worker
370*3ac0a46fSAndroid Build Coastguard Worker m_pFocusNode = node;
371*3ac0a46fSAndroid Build Coastguard Worker if (m_iStatus != LayoutStatus::kEnd)
372*3ac0a46fSAndroid Build Coastguard Worker return;
373*3ac0a46fSAndroid Build Coastguard Worker
374*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->SetFocusWidget(m_pFocusWidget);
375*3ac0a46fSAndroid Build Coastguard Worker }
376*3ac0a46fSAndroid Build Coastguard Worker
DeleteLayoutItem(CXFA_FFWidget * pWidget)377*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
378*3ac0a46fSAndroid Build Coastguard Worker if (m_pFocusNode != pWidget->GetNode())
379*3ac0a46fSAndroid Build Coastguard Worker return;
380*3ac0a46fSAndroid Build Coastguard Worker
381*3ac0a46fSAndroid Build Coastguard Worker m_pFocusNode.Clear();
382*3ac0a46fSAndroid Build Coastguard Worker m_pFocusWidget.Clear();
383*3ac0a46fSAndroid Build Coastguard Worker }
384*3ac0a46fSAndroid Build Coastguard Worker
XFA_ProcessEvent(CXFA_FFDocView * pDocView,CXFA_Node * pNode,CXFA_EventParam * pParam)385*3ac0a46fSAndroid Build Coastguard Worker static XFA_EventError XFA_ProcessEvent(CXFA_FFDocView* pDocView,
386*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode,
387*3ac0a46fSAndroid Build Coastguard Worker CXFA_EventParam* pParam) {
388*3ac0a46fSAndroid Build Coastguard Worker if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
389*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
390*3ac0a46fSAndroid Build Coastguard Worker if (pNode && pNode->GetElementType() == XFA_Element::Draw)
391*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
392*3ac0a46fSAndroid Build Coastguard Worker
393*3ac0a46fSAndroid Build Coastguard Worker switch (pParam->m_eType) {
394*3ac0a46fSAndroid Build Coastguard Worker case XFA_EVENT_Calculate:
395*3ac0a46fSAndroid Build Coastguard Worker return pNode->ProcessCalculate(pDocView);
396*3ac0a46fSAndroid Build Coastguard Worker case XFA_EVENT_Validate:
397*3ac0a46fSAndroid Build Coastguard Worker if (pDocView->GetDoc()->IsValidationsEnabled())
398*3ac0a46fSAndroid Build Coastguard Worker return pNode->ProcessValidate(pDocView, 0x01);
399*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kDisabled;
400*3ac0a46fSAndroid Build Coastguard Worker case XFA_EVENT_InitCalculate: {
401*3ac0a46fSAndroid Build Coastguard Worker CXFA_Calculate* calc = pNode->GetCalculateIfExists();
402*3ac0a46fSAndroid Build Coastguard Worker if (!calc)
403*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
404*3ac0a46fSAndroid Build Coastguard Worker if (pNode->IsUserInteractive())
405*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kDisabled;
406*3ac0a46fSAndroid Build Coastguard Worker return pNode->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam);
407*3ac0a46fSAndroid Build Coastguard Worker }
408*3ac0a46fSAndroid Build Coastguard Worker default:
409*3ac0a46fSAndroid Build Coastguard Worker return pNode->ProcessEvent(pDocView, kXFAEventActivity[pParam->m_eType],
410*3ac0a46fSAndroid Build Coastguard Worker pParam);
411*3ac0a46fSAndroid Build Coastguard Worker }
412*3ac0a46fSAndroid Build Coastguard Worker }
413*3ac0a46fSAndroid Build Coastguard Worker
ExecEventActivityByDeepFirst(CXFA_Node * pFormNode,XFA_EVENTTYPE eEventType,bool bIsFormReady,bool bRecursive)414*3ac0a46fSAndroid Build Coastguard Worker XFA_EventError CXFA_FFDocView::ExecEventActivityByDeepFirst(
415*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormNode,
416*3ac0a46fSAndroid Build Coastguard Worker XFA_EVENTTYPE eEventType,
417*3ac0a46fSAndroid Build Coastguard Worker bool bIsFormReady,
418*3ac0a46fSAndroid Build Coastguard Worker bool bRecursive) {
419*3ac0a46fSAndroid Build Coastguard Worker if (!pFormNode)
420*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
421*3ac0a46fSAndroid Build Coastguard Worker
422*3ac0a46fSAndroid Build Coastguard Worker XFA_Element elementType = pFormNode->GetElementType();
423*3ac0a46fSAndroid Build Coastguard Worker if (elementType == XFA_Element::Field) {
424*3ac0a46fSAndroid Build Coastguard Worker if (eEventType == XFA_EVENT_IndexChange)
425*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
426*3ac0a46fSAndroid Build Coastguard Worker
427*3ac0a46fSAndroid Build Coastguard Worker if (!pFormNode->IsWidgetReady())
428*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kNotExist;
429*3ac0a46fSAndroid Build Coastguard Worker
430*3ac0a46fSAndroid Build Coastguard Worker CXFA_EventParam eParam;
431*3ac0a46fSAndroid Build Coastguard Worker eParam.m_eType = eEventType;
432*3ac0a46fSAndroid Build Coastguard Worker eParam.m_bIsFormReady = bIsFormReady;
433*3ac0a46fSAndroid Build Coastguard Worker return XFA_ProcessEvent(this, pFormNode, &eParam);
434*3ac0a46fSAndroid Build Coastguard Worker }
435*3ac0a46fSAndroid Build Coastguard Worker
436*3ac0a46fSAndroid Build Coastguard Worker XFA_EventError iRet = XFA_EventError::kNotExist;
437*3ac0a46fSAndroid Build Coastguard Worker if (bRecursive) {
438*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode;
439*3ac0a46fSAndroid Build Coastguard Worker pNode = pNode->GetNextContainerSibling()) {
440*3ac0a46fSAndroid Build Coastguard Worker elementType = pNode->GetElementType();
441*3ac0a46fSAndroid Build Coastguard Worker if (elementType != XFA_Element::Variables &&
442*3ac0a46fSAndroid Build Coastguard Worker elementType != XFA_Element::Draw) {
443*3ac0a46fSAndroid Build Coastguard Worker XFA_EventErrorAccumulate(
444*3ac0a46fSAndroid Build Coastguard Worker &iRet, ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
445*3ac0a46fSAndroid Build Coastguard Worker bRecursive));
446*3ac0a46fSAndroid Build Coastguard Worker }
447*3ac0a46fSAndroid Build Coastguard Worker }
448*3ac0a46fSAndroid Build Coastguard Worker }
449*3ac0a46fSAndroid Build Coastguard Worker if (!pFormNode->IsWidgetReady())
450*3ac0a46fSAndroid Build Coastguard Worker return iRet;
451*3ac0a46fSAndroid Build Coastguard Worker
452*3ac0a46fSAndroid Build Coastguard Worker CXFA_EventParam eParam;
453*3ac0a46fSAndroid Build Coastguard Worker eParam.m_eType = eEventType;
454*3ac0a46fSAndroid Build Coastguard Worker eParam.m_bIsFormReady = bIsFormReady;
455*3ac0a46fSAndroid Build Coastguard Worker
456*3ac0a46fSAndroid Build Coastguard Worker XFA_EventErrorAccumulate(&iRet, XFA_ProcessEvent(this, pFormNode, &eParam));
457*3ac0a46fSAndroid Build Coastguard Worker return iRet;
458*3ac0a46fSAndroid Build Coastguard Worker }
459*3ac0a46fSAndroid Build Coastguard Worker
GetWidgetByName(const WideString & wsName,CXFA_FFWidget * pRefWidget)460*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName,
461*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFWidget* pRefWidget) {
462*3ac0a46fSAndroid Build Coastguard Worker if (!IsValidXMLNameString(wsName)) {
463*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
464*3ac0a46fSAndroid Build Coastguard Worker }
465*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
466*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRefNode = nullptr;
467*3ac0a46fSAndroid Build Coastguard Worker if (pRefWidget) {
468*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* node = pRefWidget->GetNode();
469*3ac0a46fSAndroid Build Coastguard Worker pRefNode = node->IsWidgetReady() ? node : nullptr;
470*3ac0a46fSAndroid Build Coastguard Worker }
471*3ac0a46fSAndroid Build Coastguard Worker WideString wsExpression = (!pRefNode ? L"$form." : L"") + wsName;
472*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
473*3ac0a46fSAndroid Build Coastguard Worker pScriptContext->ResolveObjects(
474*3ac0a46fSAndroid Build Coastguard Worker pRefNode, wsExpression.AsStringView(),
475*3ac0a46fSAndroid Build Coastguard Worker Mask<XFA_ResolveFlag>{
476*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
477*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kSiblings, XFA_ResolveFlag::kParent});
478*3ac0a46fSAndroid Build Coastguard Worker if (!maybeResult.has_value())
479*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
480*3ac0a46fSAndroid Build Coastguard Worker
481*3ac0a46fSAndroid Build Coastguard Worker if (maybeResult.value().type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
482*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pNode = maybeResult.value().objects.front()->AsNode();
483*3ac0a46fSAndroid Build Coastguard Worker if (pNode && pNode->IsWidgetReady())
484*3ac0a46fSAndroid Build Coastguard Worker return GetWidgetForNode(pNode);
485*3ac0a46fSAndroid Build Coastguard Worker }
486*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
487*3ac0a46fSAndroid Build Coastguard Worker }
488*3ac0a46fSAndroid Build Coastguard Worker
OnPageViewEvent(CXFA_ViewLayoutItem * pSender,CXFA_FFDoc::PageViewEvent eEvent)489*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::OnPageViewEvent(CXFA_ViewLayoutItem* pSender,
490*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFDoc::PageViewEvent eEvent) {
491*3ac0a46fSAndroid Build Coastguard Worker CXFA_FFPageView* pFFPageView = pSender ? pSender->GetPageView() : nullptr;
492*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->OnPageViewEvent(pFFPageView, eEvent);
493*3ac0a46fSAndroid Build Coastguard Worker }
494*3ac0a46fSAndroid Build Coastguard Worker
InvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rtInvalidate)495*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::InvalidateRect(CXFA_FFPageView* pPageView,
496*3ac0a46fSAndroid Build Coastguard Worker const CFX_RectF& rtInvalidate) {
497*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->InvalidateRect(pPageView, rtInvalidate);
498*3ac0a46fSAndroid Build Coastguard Worker }
499*3ac0a46fSAndroid Build Coastguard Worker
RunLayout()500*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::RunLayout() {
501*3ac0a46fSAndroid Build Coastguard Worker LockUpdate();
502*3ac0a46fSAndroid Build Coastguard Worker m_bInLayoutStatus = true;
503*3ac0a46fSAndroid Build Coastguard Worker
504*3ac0a46fSAndroid Build Coastguard Worker CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor();
505*3ac0a46fSAndroid Build Coastguard Worker if (!pProcessor->IncrementLayout() && pProcessor->StartLayout() < 100) {
506*3ac0a46fSAndroid Build Coastguard Worker pProcessor->DoLayout();
507*3ac0a46fSAndroid Build Coastguard Worker UnlockUpdate();
508*3ac0a46fSAndroid Build Coastguard Worker m_bInLayoutStatus = false;
509*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->OnPageViewEvent(nullptr, CXFA_FFDoc::PageViewEvent::kStopLayout);
510*3ac0a46fSAndroid Build Coastguard Worker return true;
511*3ac0a46fSAndroid Build Coastguard Worker }
512*3ac0a46fSAndroid Build Coastguard Worker
513*3ac0a46fSAndroid Build Coastguard Worker m_bInLayoutStatus = false;
514*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->OnPageViewEvent(nullptr, CXFA_FFDoc::PageViewEvent::kStopLayout);
515*3ac0a46fSAndroid Build Coastguard Worker UnlockUpdate();
516*3ac0a46fSAndroid Build Coastguard Worker return false;
517*3ac0a46fSAndroid Build Coastguard Worker }
518*3ac0a46fSAndroid Build Coastguard Worker
RunSubformIndexChange()519*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::RunSubformIndexChange() {
520*3ac0a46fSAndroid Build Coastguard Worker std::set<CXFA_Node*> seen;
521*3ac0a46fSAndroid Build Coastguard Worker while (!m_IndexChangedSubforms.empty()) {
522*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pSubformNode = m_IndexChangedSubforms.front();
523*3ac0a46fSAndroid Build Coastguard Worker m_IndexChangedSubforms.pop_front();
524*3ac0a46fSAndroid Build Coastguard Worker bool bInserted = seen.insert(pSubformNode).second;
525*3ac0a46fSAndroid Build Coastguard Worker if (!bInserted || !pSubformNode->IsWidgetReady())
526*3ac0a46fSAndroid Build Coastguard Worker continue;
527*3ac0a46fSAndroid Build Coastguard Worker
528*3ac0a46fSAndroid Build Coastguard Worker CXFA_EventParam eParam;
529*3ac0a46fSAndroid Build Coastguard Worker eParam.m_eType = XFA_EVENT_IndexChange;
530*3ac0a46fSAndroid Build Coastguard Worker pSubformNode->ProcessEvent(this, XFA_AttributeValue::IndexChange, &eParam);
531*3ac0a46fSAndroid Build Coastguard Worker }
532*3ac0a46fSAndroid Build Coastguard Worker }
533*3ac0a46fSAndroid Build Coastguard Worker
AddNewFormNode(CXFA_Node * pNode)534*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
535*3ac0a46fSAndroid Build Coastguard Worker m_NewAddedNodes.push_back(pNode);
536*3ac0a46fSAndroid Build Coastguard Worker InitLayout(pNode);
537*3ac0a46fSAndroid Build Coastguard Worker }
538*3ac0a46fSAndroid Build Coastguard Worker
AddIndexChangedSubform(CXFA_Subform * pNode)539*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Subform* pNode) {
540*3ac0a46fSAndroid Build Coastguard Worker if (!pdfium::Contains(m_IndexChangedSubforms, pNode))
541*3ac0a46fSAndroid Build Coastguard Worker m_IndexChangedSubforms.push_back(pNode);
542*3ac0a46fSAndroid Build Coastguard Worker }
543*3ac0a46fSAndroid Build Coastguard Worker
RunDocClose()544*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::RunDocClose() {
545*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRootItem =
546*3ac0a46fSAndroid Build Coastguard Worker ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
547*3ac0a46fSAndroid Build Coastguard Worker if (!pRootItem)
548*3ac0a46fSAndroid Build Coastguard Worker return;
549*3ac0a46fSAndroid Build Coastguard Worker
550*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true);
551*3ac0a46fSAndroid Build Coastguard Worker }
552*3ac0a46fSAndroid Build Coastguard Worker
AddCalculateNode(CXFA_Node * node)553*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddCalculateNode(CXFA_Node* node) {
554*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pCurrentNode =
555*3ac0a46fSAndroid Build Coastguard Worker !m_CalculateNodes.empty() ? m_CalculateNodes.back() : nullptr;
556*3ac0a46fSAndroid Build Coastguard Worker if (pCurrentNode != node)
557*3ac0a46fSAndroid Build Coastguard Worker m_CalculateNodes.push_back(node);
558*3ac0a46fSAndroid Build Coastguard Worker }
559*3ac0a46fSAndroid Build Coastguard Worker
AddCalculateNodeNotify(CXFA_Node * pNodeChange)560*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
561*3ac0a46fSAndroid Build Coastguard Worker CJX_Object::CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData();
562*3ac0a46fSAndroid Build Coastguard Worker if (!pGlobalData)
563*3ac0a46fSAndroid Build Coastguard Worker return;
564*3ac0a46fSAndroid Build Coastguard Worker
565*3ac0a46fSAndroid Build Coastguard Worker for (auto& pResult : pGlobalData->m_Globals) {
566*3ac0a46fSAndroid Build Coastguard Worker if (!pResult->HasRemovedChildren() && pResult->IsWidgetReady())
567*3ac0a46fSAndroid Build Coastguard Worker AddCalculateNode(pResult);
568*3ac0a46fSAndroid Build Coastguard Worker }
569*3ac0a46fSAndroid Build Coastguard Worker }
570*3ac0a46fSAndroid Build Coastguard Worker
RunCalculateRecursive(size_t index)571*3ac0a46fSAndroid Build Coastguard Worker size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) {
572*3ac0a46fSAndroid Build Coastguard Worker while (index < m_CalculateNodes.size()) {
573*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* node = m_CalculateNodes[index];
574*3ac0a46fSAndroid Build Coastguard Worker
575*3ac0a46fSAndroid Build Coastguard Worker AddCalculateNodeNotify(node);
576*3ac0a46fSAndroid Build Coastguard Worker size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1;
577*3ac0a46fSAndroid Build Coastguard Worker node->JSObject()->SetCalcRecursionCount(recurse);
578*3ac0a46fSAndroid Build Coastguard Worker if (recurse > 11)
579*3ac0a46fSAndroid Build Coastguard Worker break;
580*3ac0a46fSAndroid Build Coastguard Worker if (node->ProcessCalculate(this) == XFA_EventError::kSuccess &&
581*3ac0a46fSAndroid Build Coastguard Worker node->IsWidgetReady()) {
582*3ac0a46fSAndroid Build Coastguard Worker AddValidateNode(node);
583*3ac0a46fSAndroid Build Coastguard Worker }
584*3ac0a46fSAndroid Build Coastguard Worker
585*3ac0a46fSAndroid Build Coastguard Worker index = RunCalculateRecursive(++index);
586*3ac0a46fSAndroid Build Coastguard Worker }
587*3ac0a46fSAndroid Build Coastguard Worker return index;
588*3ac0a46fSAndroid Build Coastguard Worker }
589*3ac0a46fSAndroid Build Coastguard Worker
RunCalculateWidgets()590*3ac0a46fSAndroid Build Coastguard Worker XFA_EventError CXFA_FFDocView::RunCalculateWidgets() {
591*3ac0a46fSAndroid Build Coastguard Worker if (!m_pDoc->IsCalculationsEnabled())
592*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kDisabled;
593*3ac0a46fSAndroid Build Coastguard Worker
594*3ac0a46fSAndroid Build Coastguard Worker if (!m_CalculateNodes.empty())
595*3ac0a46fSAndroid Build Coastguard Worker RunCalculateRecursive(0);
596*3ac0a46fSAndroid Build Coastguard Worker
597*3ac0a46fSAndroid Build Coastguard Worker for (CXFA_Node* node : m_CalculateNodes)
598*3ac0a46fSAndroid Build Coastguard Worker node->JSObject()->SetCalcRecursionCount(0);
599*3ac0a46fSAndroid Build Coastguard Worker
600*3ac0a46fSAndroid Build Coastguard Worker m_CalculateNodes.clear();
601*3ac0a46fSAndroid Build Coastguard Worker return XFA_EventError::kSuccess;
602*3ac0a46fSAndroid Build Coastguard Worker }
603*3ac0a46fSAndroid Build Coastguard Worker
AddValidateNode(CXFA_Node * node)604*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::AddValidateNode(CXFA_Node* node) {
605*3ac0a46fSAndroid Build Coastguard Worker if (!pdfium::Contains(m_ValidateNodes, node))
606*3ac0a46fSAndroid Build Coastguard Worker m_ValidateNodes.push_back(node);
607*3ac0a46fSAndroid Build Coastguard Worker }
608*3ac0a46fSAndroid Build Coastguard Worker
InitCalculate(CXFA_Node * pNode)609*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
610*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true);
611*3ac0a46fSAndroid Build Coastguard Worker }
612*3ac0a46fSAndroid Build Coastguard Worker
ProcessValueChanged(CXFA_Node * node)613*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::ProcessValueChanged(CXFA_Node* node) {
614*3ac0a46fSAndroid Build Coastguard Worker AddValidateNode(node);
615*3ac0a46fSAndroid Build Coastguard Worker AddCalculateNode(node);
616*3ac0a46fSAndroid Build Coastguard Worker RunCalculateWidgets();
617*3ac0a46fSAndroid Build Coastguard Worker RunValidate();
618*3ac0a46fSAndroid Build Coastguard Worker }
619*3ac0a46fSAndroid Build Coastguard Worker
InitValidate(CXFA_Node * pNode)620*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
621*3ac0a46fSAndroid Build Coastguard Worker if (!m_pDoc->IsValidationsEnabled())
622*3ac0a46fSAndroid Build Coastguard Worker return false;
623*3ac0a46fSAndroid Build Coastguard Worker
624*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true);
625*3ac0a46fSAndroid Build Coastguard Worker m_ValidateNodes.clear();
626*3ac0a46fSAndroid Build Coastguard Worker return true;
627*3ac0a46fSAndroid Build Coastguard Worker }
628*3ac0a46fSAndroid Build Coastguard Worker
RunValidate()629*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::RunValidate() {
630*3ac0a46fSAndroid Build Coastguard Worker if (!m_pDoc->IsValidationsEnabled())
631*3ac0a46fSAndroid Build Coastguard Worker return false;
632*3ac0a46fSAndroid Build Coastguard Worker
633*3ac0a46fSAndroid Build Coastguard Worker while (!m_ValidateNodes.empty()) {
634*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* node = m_ValidateNodes.front();
635*3ac0a46fSAndroid Build Coastguard Worker m_ValidateNodes.pop_front();
636*3ac0a46fSAndroid Build Coastguard Worker if (!node->HasRemovedChildren())
637*3ac0a46fSAndroid Build Coastguard Worker node->ProcessValidate(this, 0);
638*3ac0a46fSAndroid Build Coastguard Worker }
639*3ac0a46fSAndroid Build Coastguard Worker return true;
640*3ac0a46fSAndroid Build Coastguard Worker }
641*3ac0a46fSAndroid Build Coastguard Worker
RunEventLayoutReady()642*3ac0a46fSAndroid Build Coastguard Worker bool CXFA_FFDocView::RunEventLayoutReady() {
643*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pRootItem =
644*3ac0a46fSAndroid Build Coastguard Worker ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
645*3ac0a46fSAndroid Build Coastguard Worker if (!pRootItem)
646*3ac0a46fSAndroid Build Coastguard Worker return false;
647*3ac0a46fSAndroid Build Coastguard Worker
648*3ac0a46fSAndroid Build Coastguard Worker ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true);
649*3ac0a46fSAndroid Build Coastguard Worker RunLayout();
650*3ac0a46fSAndroid Build Coastguard Worker return true;
651*3ac0a46fSAndroid Build Coastguard Worker }
652*3ac0a46fSAndroid Build Coastguard Worker
RunBindItems()653*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::RunBindItems() {
654*3ac0a46fSAndroid Build Coastguard Worker while (!m_BindItems.empty()) {
655*3ac0a46fSAndroid Build Coastguard Worker CXFA_BindItems* item = m_BindItems.front();
656*3ac0a46fSAndroid Build Coastguard Worker m_BindItems.pop_front();
657*3ac0a46fSAndroid Build Coastguard Worker if (item->HasRemovedChildren())
658*3ac0a46fSAndroid Build Coastguard Worker continue;
659*3ac0a46fSAndroid Build Coastguard Worker
660*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pWidgetNode = item->GetParent();
661*3ac0a46fSAndroid Build Coastguard Worker if (!pWidgetNode || !pWidgetNode->IsWidgetReady())
662*3ac0a46fSAndroid Build Coastguard Worker continue;
663*3ac0a46fSAndroid Build Coastguard Worker
664*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine* pScriptContext =
665*3ac0a46fSAndroid Build Coastguard Worker pWidgetNode->GetDocument()->GetScriptContext();
666*3ac0a46fSAndroid Build Coastguard Worker WideString wsRef = item->GetRef();
667*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> maybeRS =
668*3ac0a46fSAndroid Build Coastguard Worker pScriptContext->ResolveObjects(
669*3ac0a46fSAndroid Build Coastguard Worker pWidgetNode, wsRef.AsStringView(),
670*3ac0a46fSAndroid Build Coastguard Worker Mask<XFA_ResolveFlag>{
671*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
672*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kSiblings, XFA_ResolveFlag::kParent,
673*3ac0a46fSAndroid Build Coastguard Worker XFA_ResolveFlag::kALL});
674*3ac0a46fSAndroid Build Coastguard Worker pWidgetNode->DeleteItem(-1, false, false);
675*3ac0a46fSAndroid Build Coastguard Worker if (!maybeRS.has_value() ||
676*3ac0a46fSAndroid Build Coastguard Worker maybeRS.value().type != CFXJSE_Engine::ResolveResult::Type::kNodes ||
677*3ac0a46fSAndroid Build Coastguard Worker maybeRS.value().objects.empty()) {
678*3ac0a46fSAndroid Build Coastguard Worker continue;
679*3ac0a46fSAndroid Build Coastguard Worker }
680*3ac0a46fSAndroid Build Coastguard Worker WideString wsValueRef = item->GetValueRef();
681*3ac0a46fSAndroid Build Coastguard Worker WideString wsLabelRef = item->GetLabelRef();
682*3ac0a46fSAndroid Build Coastguard Worker const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
683*3ac0a46fSAndroid Build Coastguard Worker const bool bLabelUseContent =
684*3ac0a46fSAndroid Build Coastguard Worker wsLabelRef.IsEmpty() || wsLabelRef.EqualsASCII("$");
685*3ac0a46fSAndroid Build Coastguard Worker const bool bValueUseContent =
686*3ac0a46fSAndroid Build Coastguard Worker wsValueRef.IsEmpty() || wsValueRef.EqualsASCII("$");
687*3ac0a46fSAndroid Build Coastguard Worker WideString wsValue;
688*3ac0a46fSAndroid Build Coastguard Worker WideString wsLabel;
689*3ac0a46fSAndroid Build Coastguard Worker uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView());
690*3ac0a46fSAndroid Build Coastguard Worker for (auto& refObject : maybeRS.value().objects) {
691*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* refNode = refObject->AsNode();
692*3ac0a46fSAndroid Build Coastguard Worker if (!refNode)
693*3ac0a46fSAndroid Build Coastguard Worker continue;
694*3ac0a46fSAndroid Build Coastguard Worker
695*3ac0a46fSAndroid Build Coastguard Worker if (bValueUseContent) {
696*3ac0a46fSAndroid Build Coastguard Worker wsValue = refNode->JSObject()->GetContent(false);
697*3ac0a46fSAndroid Build Coastguard Worker } else {
698*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
699*3ac0a46fSAndroid Build Coastguard Worker wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false)
700*3ac0a46fSAndroid Build Coastguard Worker : refNode->JSObject()->GetContent(false);
701*3ac0a46fSAndroid Build Coastguard Worker }
702*3ac0a46fSAndroid Build Coastguard Worker
703*3ac0a46fSAndroid Build Coastguard Worker if (!bUseValue) {
704*3ac0a46fSAndroid Build Coastguard Worker if (bLabelUseContent) {
705*3ac0a46fSAndroid Build Coastguard Worker wsLabel = refNode->JSObject()->GetContent(false);
706*3ac0a46fSAndroid Build Coastguard Worker } else {
707*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* nodeLabel =
708*3ac0a46fSAndroid Build Coastguard Worker refNode->GetFirstChildByName(wsLabelRef.AsStringView());
709*3ac0a46fSAndroid Build Coastguard Worker if (nodeLabel)
710*3ac0a46fSAndroid Build Coastguard Worker wsLabel = nodeLabel->JSObject()->GetContent(false);
711*3ac0a46fSAndroid Build Coastguard Worker }
712*3ac0a46fSAndroid Build Coastguard Worker } else {
713*3ac0a46fSAndroid Build Coastguard Worker wsLabel = wsValue;
714*3ac0a46fSAndroid Build Coastguard Worker }
715*3ac0a46fSAndroid Build Coastguard Worker pWidgetNode->InsertItem(wsLabel, wsValue, false);
716*3ac0a46fSAndroid Build Coastguard Worker }
717*3ac0a46fSAndroid Build Coastguard Worker }
718*3ac0a46fSAndroid Build Coastguard Worker }
719*3ac0a46fSAndroid Build Coastguard Worker
SetChangeMark()720*3ac0a46fSAndroid Build Coastguard Worker void CXFA_FFDocView::SetChangeMark() {
721*3ac0a46fSAndroid Build Coastguard Worker if (m_iStatus != LayoutStatus::kEnd)
722*3ac0a46fSAndroid Build Coastguard Worker return;
723*3ac0a46fSAndroid Build Coastguard Worker
724*3ac0a46fSAndroid Build Coastguard Worker m_pDoc->SetChangeMark();
725*3ac0a46fSAndroid Build Coastguard Worker }
726*3ac0a46fSAndroid Build Coastguard Worker
GetRootSubform()727*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CXFA_FFDocView::GetRootSubform() {
728*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* pFormPacketNode =
729*3ac0a46fSAndroid Build Coastguard Worker ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
730*3ac0a46fSAndroid Build Coastguard Worker if (!pFormPacketNode)
731*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
732*3ac0a46fSAndroid Build Coastguard Worker
733*3ac0a46fSAndroid Build Coastguard Worker return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(
734*3ac0a46fSAndroid Build Coastguard Worker XFA_Element::Subform);
735*3ac0a46fSAndroid Build Coastguard Worker }
736