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/cxfa_ffdocview.h"
8
9 #include "core/fxcrt/fx_extension.h"
10 #include "fxjs/cfxjse_engine.h"
11 #include "fxjs/xfa/cjx_object.h"
12 #include "third_party/base/ptr_util.h"
13 #include "third_party/base/stl_util.h"
14 #include "xfa/fxfa/cxfa_ffapp.h"
15 #include "xfa/fxfa/cxfa_ffbarcode.h"
16 #include "xfa/fxfa/cxfa_ffcheckbutton.h"
17 #include "xfa/fxfa/cxfa_ffdoc.h"
18 #include "xfa/fxfa/cxfa_ffdraw.h"
19 #include "xfa/fxfa/cxfa_ffexclgroup.h"
20 #include "xfa/fxfa/cxfa_fffield.h"
21 #include "xfa/fxfa/cxfa_ffimage.h"
22 #include "xfa/fxfa/cxfa_ffimageedit.h"
23 #include "xfa/fxfa/cxfa_ffpageview.h"
24 #include "xfa/fxfa/cxfa_ffpushbutton.h"
25 #include "xfa/fxfa/cxfa_ffsignature.h"
26 #include "xfa/fxfa/cxfa_ffsubform.h"
27 #include "xfa/fxfa/cxfa_fftext.h"
28 #include "xfa/fxfa/cxfa_ffwidget.h"
29 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
30 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
31 #include "xfa/fxfa/cxfa_textprovider.h"
32 #include "xfa/fxfa/cxfa_widgetacciterator.h"
33 #include "xfa/fxfa/parser/cxfa_acrobat.h"
34 #include "xfa/fxfa/parser/cxfa_binditems.h"
35 #include "xfa/fxfa/parser/cxfa_calculate.h"
36 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
37 #include "xfa/fxfa/parser/cxfa_pageset.h"
38 #include "xfa/fxfa/parser/cxfa_present.h"
39 #include "xfa/fxfa/parser/cxfa_subform.h"
40 #include "xfa/fxfa/parser/cxfa_validate.h"
41 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
42
43 const XFA_AttributeEnum gs_EventActivity[] = {
44 XFA_AttributeEnum::Click, XFA_AttributeEnum::Change,
45 XFA_AttributeEnum::DocClose, XFA_AttributeEnum::DocReady,
46 XFA_AttributeEnum::Enter, XFA_AttributeEnum::Exit,
47 XFA_AttributeEnum::Full, XFA_AttributeEnum::IndexChange,
48 XFA_AttributeEnum::Initialize, XFA_AttributeEnum::MouseDown,
49 XFA_AttributeEnum::MouseEnter, XFA_AttributeEnum::MouseExit,
50 XFA_AttributeEnum::MouseUp, XFA_AttributeEnum::PostExecute,
51 XFA_AttributeEnum::PostOpen, XFA_AttributeEnum::PostPrint,
52 XFA_AttributeEnum::PostSave, XFA_AttributeEnum::PostSign,
53 XFA_AttributeEnum::PostSubmit, XFA_AttributeEnum::PreExecute,
54 XFA_AttributeEnum::PreOpen, XFA_AttributeEnum::PrePrint,
55 XFA_AttributeEnum::PreSave, XFA_AttributeEnum::PreSign,
56 XFA_AttributeEnum::PreSubmit, XFA_AttributeEnum::Ready,
57 XFA_AttributeEnum::Unknown,
58 };
59
CXFA_FFDocView(CXFA_FFDoc * pDoc)60 CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc)
61 : m_bLayoutEvent(false),
62 m_pListFocusWidget(nullptr),
63 m_bInLayoutStatus(false),
64 m_pDoc(pDoc),
65 m_pXFADocLayout(nullptr),
66 m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None),
67 m_iLock(0) {}
68
~CXFA_FFDocView()69 CXFA_FFDocView::~CXFA_FFDocView() {
70 DestroyDocView();
71 }
72
InitLayout(CXFA_Node * pNode)73 void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) {
74 RunBindItems();
75 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true,
76 nullptr);
77 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true,
78 nullptr);
79 }
80
StartLayout(int32_t iStartPage)81 int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) {
82 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
83 m_pDoc->GetXFADoc()->DoProtoMerge();
84 m_pDoc->GetXFADoc()->DoDataMerge();
85 m_pXFADocLayout = GetXFALayout();
86
87 int32_t iStatus = m_pXFADocLayout->StartLayout();
88 if (iStatus < 0)
89 return iStatus;
90
91 CXFA_Node* pRootItem =
92 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
93 if (!pRootItem)
94 return iStatus;
95
96 InitLayout(pRootItem);
97 InitCalculate(pRootItem);
98 InitValidate(pRootItem);
99
100 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr);
101 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start;
102 return iStatus;
103 }
104
DoLayout()105 int32_t CXFA_FFDocView::DoLayout() {
106 int32_t iStatus = 100;
107 iStatus = m_pXFADocLayout->DoLayout();
108 if (iStatus != 100)
109 return iStatus;
110
111 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing;
112 return iStatus;
113 }
114
StopLayout()115 void CXFA_FFDocView::StopLayout() {
116 CXFA_Node* pRootItem =
117 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
118 if (!pRootItem)
119 return;
120
121 CXFA_Subform* pSubformNode =
122 pRootItem->GetChild<CXFA_Subform>(0, XFA_Element::Subform, false);
123 if (!pSubformNode)
124 return;
125
126 CXFA_PageSet* pPageSetNode =
127 pSubformNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
128 if (!pPageSetNode)
129 return;
130
131 RunCalculateWidgets();
132 RunValidate();
133
134 InitLayout(pPageSetNode);
135 InitCalculate(pPageSetNode);
136 InitValidate(pPageSetNode);
137
138 ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true,
139 nullptr);
140 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
141 nullptr);
142 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true,
143 nullptr);
144
145 RunCalculateWidgets();
146 RunValidate();
147
148 if (RunLayout()) {
149 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true,
150 nullptr);
151 }
152
153 m_CalculateAccs.clear();
154 if (m_pFocusAcc && !m_pFocusWidget)
155 SetFocusWidgetAcc(m_pFocusAcc.Get());
156
157 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End;
158 }
159
ShowNullTestMsg()160 void CXFA_FFDocView::ShowNullTestMsg() {
161 int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg);
162 CXFA_FFApp* pApp = m_pDoc->GetApp();
163 IXFA_AppProvider* pAppProvider = pApp->GetAppProvider();
164 if (pAppProvider && iCount) {
165 int32_t iRemain = iCount > 7 ? iCount - 7 : 0;
166 iCount -= iRemain;
167 WideString wsMsg;
168 for (int32_t i = 0; i < iCount; i++)
169 wsMsg += m_arrNullTestMsg[i] + L"\n";
170
171 if (iRemain > 0) {
172 wsMsg += L"\n" + WideString::Format(
173 L"Message limit exceeded. Remaining %d "
174 L"validation errors not reported.",
175 iRemain);
176 }
177 pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status,
178 XFA_MB_OK);
179 }
180 m_arrNullTestMsg.clear();
181 }
182
UpdateDocView()183 void CXFA_FFDocView::UpdateDocView() {
184 if (IsUpdateLocked())
185 return;
186
187 LockUpdate();
188 for (CXFA_Node* pNode : m_NewAddedNodes) {
189 InitCalculate(pNode);
190 InitValidate(pNode);
191 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr);
192 }
193 m_NewAddedNodes.clear();
194
195 RunSubformIndexChange();
196 RunCalculateWidgets();
197 RunValidate();
198
199 ShowNullTestMsg();
200
201 if (RunLayout() && m_bLayoutEvent)
202 RunEventLayoutReady();
203
204 m_bLayoutEvent = false;
205 m_CalculateAccs.clear();
206 RunInvalidate();
207 UnlockUpdate();
208 }
209
CountPageViews() const210 int32_t CXFA_FFDocView::CountPageViews() const {
211 return m_pXFADocLayout ? m_pXFADocLayout->CountPages() : 0;
212 }
213
GetPageView(int32_t nIndex) const214 CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const {
215 if (!m_pXFADocLayout)
216 return nullptr;
217 return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex));
218 }
219
GetXFALayout() const220 CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const {
221 return m_pDoc->GetXFADoc()->GetDocLayout();
222 }
223
ResetSingleWidgetAccData(CXFA_WidgetAcc * pWidgetAcc)224 bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) {
225 CXFA_Node* pNode = pWidgetAcc->GetNode();
226 XFA_Element eType = pNode->GetElementType();
227 if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
228 return false;
229
230 pWidgetAcc->ResetData();
231 pWidgetAcc->UpdateUIDisplay(this, nullptr);
232 CXFA_Validate* validate = pNode->GetValidateIfExists();
233 if (!validate)
234 return true;
235
236 AddValidateWidget(pWidgetAcc);
237 validate->SetFlag(XFA_NodeFlag_NeedsInitApp, false);
238 return true;
239 }
240
ResetWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)241 void CXFA_FFDocView::ResetWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
242 m_bLayoutEvent = true;
243 bool bChanged = false;
244 CXFA_Node* pFormNode = nullptr;
245 if (pWidgetAcc) {
246 bChanged = ResetSingleWidgetAccData(pWidgetAcc);
247 pFormNode = pWidgetAcc->GetNode();
248 } else {
249 pFormNode = GetRootSubform();
250 }
251 if (!pFormNode)
252 return;
253
254 if (pFormNode->GetElementType() != XFA_Element::Field &&
255 pFormNode->GetElementType() != XFA_Element::ExclGroup) {
256 CXFA_WidgetAccIterator Iterator(pFormNode);
257 while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) {
258 bChanged |= ResetSingleWidgetAccData(pAcc);
259 if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup)
260 Iterator.SkipTree();
261 }
262 }
263 if (bChanged)
264 m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
265 }
266
ProcessWidgetEvent(CXFA_EventParam * pParam,CXFA_WidgetAcc * pWidgetAcc)267 int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam,
268 CXFA_WidgetAcc* pWidgetAcc) {
269 if (!pParam)
270 return XFA_EVENTERROR_Error;
271
272 if (pParam->m_eType == XFA_EVENT_Validate) {
273 WideString wsValidateStr(L"preSubmit");
274 CXFA_Node* pConfigItem =
275 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config));
276 if (pConfigItem) {
277 CXFA_Acrobat* pAcrobatNode =
278 pConfigItem->GetChild<CXFA_Acrobat>(0, XFA_Element::Acrobat, false);
279 CXFA_Validate* pValidateNode =
280 pAcrobatNode ? pAcrobatNode->GetChild<CXFA_Validate>(
281 0, XFA_Element::Validate, false)
282 : nullptr;
283 if (!pValidateNode) {
284 CXFA_Present* pPresentNode =
285 pConfigItem->GetChild<CXFA_Present>(0, XFA_Element::Present, false);
286 pValidateNode = pPresentNode ? pPresentNode->GetChild<CXFA_Validate>(
287 0, XFA_Element::Validate, false)
288 : nullptr;
289 }
290 if (pValidateNode)
291 wsValidateStr = pValidateNode->JSObject()->GetContent(false);
292 }
293
294 if (!wsValidateStr.Contains(L"preSubmit"))
295 return XFA_EVENTERROR_Success;
296 }
297
298 CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr;
299 if (!pNode) {
300 CXFA_Node* pRootItem =
301 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
302 if (!pRootItem)
303 return XFA_EVENTERROR_Error;
304
305 pNode = pRootItem->GetChild<CXFA_Node>(0, XFA_Element::Subform, false);
306 }
307
308 ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady,
309 true, nullptr);
310 return XFA_EVENTERROR_Success;
311 }
312
GetWidgetForNode(CXFA_Node * node)313 CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) {
314 return static_cast<CXFA_FFWidget*>(GetXFALayout()->GetLayoutItem(node));
315 }
316
GetWidgetHandler()317 CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() {
318 if (!m_pWidgetHandler)
319 m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this);
320 return m_pWidgetHandler.get();
321 }
322
323 std::unique_ptr<CXFA_WidgetAccIterator>
CreateWidgetAccIterator()324 CXFA_FFDocView::CreateWidgetAccIterator() {
325 CXFA_Subform* pFormRoot = GetRootSubform();
326 return pFormRoot ? pdfium::MakeUnique<CXFA_WidgetAccIterator>(pFormRoot)
327 : nullptr;
328 }
329
KillFocus()330 void CXFA_FFDocView::KillFocus() {
331 if (m_pFocusWidget &&
332 (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) {
333 m_pFocusWidget->OnKillFocus(nullptr);
334 }
335 m_pFocusAcc = nullptr;
336 m_pFocusWidget = nullptr;
337 m_pOldFocusWidget = nullptr;
338 }
339
SetFocus(CXFA_FFWidget * hWidget)340 bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) {
341 CXFA_FFWidget* pNewFocus = hWidget;
342 if (m_pOldFocusWidget == pNewFocus)
343 return false;
344
345 CXFA_FFWidget* pOldFocus = m_pOldFocusWidget.Get();
346 m_pOldFocusWidget = pNewFocus;
347 if (pOldFocus) {
348 if (m_pFocusWidget != m_pOldFocusWidget &&
349 (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) {
350 m_pFocusWidget = pOldFocus;
351 pOldFocus->OnKillFocus(pNewFocus);
352 } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
353 if (!pOldFocus->IsLoaded())
354 pOldFocus->LoadWidget();
355
356 pOldFocus->OnSetFocus(m_pFocusWidget.Get());
357 m_pFocusWidget = pOldFocus;
358 pOldFocus->OnKillFocus(pNewFocus);
359 }
360 }
361 if (m_pFocusWidget == m_pOldFocusWidget)
362 return false;
363
364 pNewFocus = m_pOldFocusWidget.Get();
365 if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) {
366 m_pFocusAcc = nullptr;
367 m_pFocusWidget = nullptr;
368 m_pListFocusWidget = nullptr;
369 m_pOldFocusWidget = nullptr;
370 return false;
371 }
372 if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) {
373 if (!pNewFocus->IsLoaded())
374 pNewFocus->LoadWidget();
375 pNewFocus->OnSetFocus(m_pFocusWidget.Get());
376 }
377 m_pFocusAcc = pNewFocus ? pNewFocus->GetNode()->GetWidgetAcc() : nullptr;
378 m_pFocusWidget = pNewFocus;
379 m_pOldFocusWidget = m_pFocusWidget;
380 return true;
381 }
382
SetFocusWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)383 void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
384 CXFA_FFWidget* pNewFocus = nullptr;
385 if (pWidgetAcc)
386 pNewFocus = GetWidgetForNode(pWidgetAcc->GetNode());
387 if (!SetFocus(pNewFocus))
388 return;
389
390 m_pFocusAcc = pWidgetAcc;
391 if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End)
392 return;
393
394 m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc.Get(),
395 m_pFocusWidget.Get());
396 }
397
DeleteLayoutItem(CXFA_FFWidget * pWidget)398 void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) {
399 if (m_pFocusAcc && m_pFocusAcc->GetNode() != pWidget->GetNode())
400 return;
401
402 m_pFocusAcc = nullptr;
403 m_pFocusWidget = nullptr;
404 m_pOldFocusWidget = nullptr;
405 }
406
XFA_ProcessEvent(CXFA_FFDocView * pDocView,CXFA_WidgetAcc * pWidgetAcc,CXFA_EventParam * pParam)407 static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView,
408 CXFA_WidgetAcc* pWidgetAcc,
409 CXFA_EventParam* pParam) {
410 if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
411 return XFA_EVENTERROR_NotExist;
412 if (!pWidgetAcc)
413 return XFA_EVENTERROR_NotExist;
414
415 CXFA_Node* node = pWidgetAcc->GetNode();
416 if (node && node->GetElementType() == XFA_Element::Draw)
417 return XFA_EVENTERROR_NotExist;
418
419 switch (pParam->m_eType) {
420 case XFA_EVENT_Calculate:
421 return node->ProcessCalculate(pDocView);
422 case XFA_EVENT_Validate:
423 if (pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
424 pDocView->GetDoc())) {
425 return node->ProcessValidate(pDocView, 0x01);
426 }
427 return XFA_EVENTERROR_Disabled;
428 case XFA_EVENT_InitCalculate: {
429 CXFA_Calculate* calc = node->GetCalculateIfExists();
430 if (!calc)
431 return XFA_EVENTERROR_NotExist;
432 if (node->IsUserInteractive())
433 return XFA_EVENTERROR_Disabled;
434
435 return node->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam);
436 }
437 default:
438 break;
439 }
440
441 return node->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType],
442 pParam);
443 }
444
ExecEventActivityByDeepFirst(CXFA_Node * pFormNode,XFA_EVENTTYPE eEventType,bool bIsFormReady,bool bRecursive,CXFA_Node * pExclude)445 int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
446 XFA_EVENTTYPE eEventType,
447 bool bIsFormReady,
448 bool bRecursive,
449 CXFA_Node* pExclude) {
450 if (pFormNode == pExclude)
451 return XFA_EVENTERROR_NotExist;
452
453 XFA_Element elementType = pFormNode->GetElementType();
454 if (elementType == XFA_Element::Field) {
455 if (eEventType == XFA_EVENT_IndexChange)
456 return XFA_EVENTERROR_NotExist;
457
458 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
459 if (!pWidgetAcc)
460 return XFA_EVENTERROR_NotExist;
461
462 CXFA_EventParam eParam;
463 eParam.m_eType = eEventType;
464 eParam.m_pTarget = pWidgetAcc;
465 eParam.m_bIsFormReady = bIsFormReady;
466 return XFA_ProcessEvent(this, pWidgetAcc, &eParam);
467 }
468
469 int32_t iRet = XFA_EVENTERROR_NotExist;
470 if (bRecursive) {
471 for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode;
472 pNode = pNode->GetNextContainerSibling()) {
473 elementType = pNode->GetElementType();
474 if (elementType != XFA_Element::Variables &&
475 elementType != XFA_Element::Draw) {
476 iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady,
477 bRecursive, pExclude);
478 }
479 }
480 }
481 CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
482 if (!pWidgetAcc)
483 return iRet;
484
485 CXFA_EventParam eParam;
486 eParam.m_eType = eEventType;
487 eParam.m_pTarget = pWidgetAcc;
488 eParam.m_bIsFormReady = bIsFormReady;
489 iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam);
490
491 return iRet;
492 }
493
GetWidgetByName(const WideString & wsName,CXFA_FFWidget * pRefWidget)494 CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName,
495 CXFA_FFWidget* pRefWidget) {
496 CXFA_WidgetAcc* pRefAcc =
497 pRefWidget ? pRefWidget->GetNode()->GetWidgetAcc() : nullptr;
498 CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc);
499 if (!pAcc)
500 return nullptr;
501 return GetWidgetForNode(pAcc->GetNode());
502 }
503
GetWidgetAccByName(const WideString & wsName,CXFA_WidgetAcc * pRefWidgetAcc)504 CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName(
505 const WideString& wsName,
506 CXFA_WidgetAcc* pRefWidgetAcc) {
507 WideString wsExpression;
508 uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
509 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
510 CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext();
511 if (!pScriptContext)
512 return nullptr;
513
514 CXFA_Node* refNode = nullptr;
515 if (pRefWidgetAcc) {
516 refNode = pRefWidgetAcc->GetNode();
517 wsExpression = wsName;
518 } else {
519 wsExpression = L"$form." + wsName;
520 }
521
522 XFA_RESOLVENODE_RS resolveNodeRS;
523 if (!pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
524 &resolveNodeRS, dwStyle, nullptr)) {
525 return nullptr;
526 }
527
528 if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
529 CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode();
530 if (pNode)
531 return pNode->GetWidgetAcc();
532 }
533 return nullptr;
534 }
535
OnPageEvent(CXFA_ContainerLayoutItem * pSender,uint32_t dwEvent)536 void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender,
537 uint32_t dwEvent) {
538 CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender);
539 m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent);
540 }
541
542
AddInvalidateRect(CXFA_FFWidget * pWidget,const CFX_RectF & rtInvalidate)543 void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget,
544 const CFX_RectF& rtInvalidate) {
545 AddInvalidateRect(pWidget->GetPageView(), rtInvalidate);
546 }
547
AddInvalidateRect(CXFA_FFPageView * pPageView,const CFX_RectF & rtInvalidate)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
555 m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate);
556 }
557
RunInvalidate()558 void CXFA_FFDocView::RunInvalidate() {
559 for (const auto& pair : m_mapPageInvalidate)
560 m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second);
561
562 m_mapPageInvalidate.clear();
563 }
564
RunLayout()565 bool CXFA_FFDocView::RunLayout() {
566 LockUpdate();
567 m_bInLayoutStatus = true;
568 if (!m_pXFADocLayout->IncrementLayout() &&
569 m_pXFADocLayout->StartLayout() < 100) {
570 m_pXFADocLayout->DoLayout();
571 UnlockUpdate();
572 m_bInLayoutStatus = false;
573 m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
574 XFA_PAGEVIEWEVENT_StopLayout);
575 return true;
576 }
577
578 m_bInLayoutStatus = false;
579 m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr,
580 XFA_PAGEVIEWEVENT_StopLayout);
581 UnlockUpdate();
582 return false;
583 }
584
RunSubformIndexChange()585 void CXFA_FFDocView::RunSubformIndexChange() {
586 for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) {
587 if (!pSubformNode->GetWidgetAcc())
588 continue;
589
590 CXFA_EventParam eParam;
591 eParam.m_eType = XFA_EVENT_IndexChange;
592 eParam.m_pTarget = pSubformNode->GetWidgetAcc();
593 pSubformNode->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam);
594 }
595 m_IndexChangedSubforms.clear();
596 }
597
AddNewFormNode(CXFA_Node * pNode)598 void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) {
599 m_NewAddedNodes.push_back(pNode);
600 InitLayout(pNode);
601 }
602
AddIndexChangedSubform(CXFA_Node * pNode)603 void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) {
604 ASSERT(pNode->GetElementType() == XFA_Element::Subform);
605 m_IndexChangedSubforms.push_back(pNode);
606 }
607
RunDocClose()608 void CXFA_FFDocView::RunDocClose() {
609 CXFA_Node* pRootItem =
610 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
611 if (!pRootItem)
612 return;
613
614 ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true,
615 nullptr);
616 }
617
DestroyDocView()618 void CXFA_FFDocView::DestroyDocView() {
619 ClearInvalidateList();
620 m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None;
621 m_iLock = 0;
622 m_ValidateAccs.clear();
623 m_BindItems.clear();
624 m_CalculateAccs.clear();
625 }
626
AddCalculateWidgetAcc(CXFA_WidgetAcc * pWidgetAcc)627 void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) {
628 CXFA_WidgetAcc* pCurrentAcc =
629 !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr;
630 if (pCurrentAcc != pWidgetAcc)
631 m_CalculateAccs.push_back(pWidgetAcc);
632 }
633
AddCalculateNodeNotify(CXFA_Node * pNodeChange)634 void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) {
635 CXFA_CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData();
636 if (!pGlobalData)
637 return;
638
639 for (auto* pResult : pGlobalData->m_Globals) {
640 if (!pResult->HasRemovedChildren())
641 AddCalculateWidgetAcc(pResult->GetWidgetAcc());
642 }
643 }
644
RunCalculateRecursive(size_t index)645 size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) {
646 while (index < m_CalculateAccs.size()) {
647 CXFA_Node* node = m_CalculateAccs[index]->GetNode();
648
649 AddCalculateNodeNotify(node);
650 size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1;
651 node->JSObject()->SetCalcRecursionCount(recurse);
652 if (recurse > 11)
653 break;
654 if (node->ProcessCalculate(this) == XFA_EVENTERROR_Success)
655 AddValidateWidget(node->GetWidgetAcc());
656
657 index = RunCalculateRecursive(++index);
658 }
659 return index;
660 }
661
RunCalculateWidgets()662 int32_t CXFA_FFDocView::RunCalculateWidgets() {
663 if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc.Get()))
664 return XFA_EVENTERROR_Disabled;
665 if (!m_CalculateAccs.empty())
666 RunCalculateRecursive(0);
667
668 for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs)
669 pCurAcc->GetNode()->JSObject()->SetCalcRecursionCount(0);
670
671 m_CalculateAccs.clear();
672 return XFA_EVENTERROR_Success;
673 }
674
AddValidateWidget(CXFA_WidgetAcc * pWidget)675 void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) {
676 if (!pdfium::ContainsValue(m_ValidateAccs, pWidget))
677 m_ValidateAccs.push_back(pWidget);
678 }
679
InitCalculate(CXFA_Node * pNode)680 void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) {
681 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true,
682 nullptr);
683 }
684
ProcessValueChanged(CXFA_WidgetAcc * widgetAcc)685 void CXFA_FFDocView::ProcessValueChanged(CXFA_WidgetAcc* widgetAcc) {
686 AddValidateWidget(widgetAcc);
687 AddCalculateWidgetAcc(widgetAcc);
688 RunCalculateWidgets();
689 RunValidate();
690 }
691
InitValidate(CXFA_Node * pNode)692 bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) {
693 if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get()))
694 return false;
695
696 ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr);
697 m_ValidateAccs.clear();
698 return true;
699 }
700
RunValidate()701 bool CXFA_FFDocView::RunValidate() {
702 if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc.Get()))
703 return false;
704
705 for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) {
706 CXFA_Node* node = pAcc->GetNode();
707 if (!node->HasRemovedChildren())
708 node->ProcessValidate(this, 0);
709 }
710 m_ValidateAccs.clear();
711 return true;
712 }
713
RunEventLayoutReady()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
RunBindItems()726 void CXFA_FFDocView::RunBindItems() {
727 for (auto* item : m_BindItems) {
728 if (item->HasRemovedChildren())
729 continue;
730
731 CXFA_Node* pWidgetNode = item->GetParent();
732 CXFA_WidgetAcc* pAcc = pWidgetNode->GetWidgetAcc();
733 if (!pAcc)
734 continue;
735
736 CFXJSE_Engine* pScriptContext =
737 pWidgetNode->GetDocument()->GetScriptContext();
738 WideString wsRef = item->GetRef();
739 uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
740 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent |
741 XFA_RESOLVENODE_ALL;
742 XFA_RESOLVENODE_RS rs;
743 pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs,
744 dwStyle, nullptr);
745 pAcc->DeleteItem(-1, false, false);
746 if (rs.dwFlags != XFA_ResolveNode_RSType_Nodes || rs.objects.empty())
747 continue;
748
749 WideString wsValueRef = item->GetValueRef();
750 WideString wsLabelRef = item->GetLabelRef();
751 const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
752 const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$";
753 const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$";
754 WideString wsValue;
755 WideString wsLabel;
756 uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false);
757 for (CXFA_Object* refObject : rs.objects) {
758 CXFA_Node* refNode = refObject->AsNode();
759 if (!refNode)
760 continue;
761
762 if (bValueUseContent) {
763 wsValue = refNode->JSObject()->GetContent(false);
764 } else {
765 CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash);
766 wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false)
767 : refNode->JSObject()->GetContent(false);
768 }
769
770 if (!bUseValue) {
771 if (bLabelUseContent) {
772 wsLabel = refNode->JSObject()->GetContent(false);
773 } else {
774 CXFA_Node* nodeLabel =
775 refNode->GetFirstChildByName(wsLabelRef.AsStringView());
776 if (nodeLabel)
777 wsLabel = nodeLabel->JSObject()->GetContent(false);
778 }
779 } else {
780 wsLabel = wsValue;
781 }
782 pAcc->InsertItem(wsLabel, wsValue, false);
783 }
784 }
785 m_BindItems.clear();
786 }
787
SetChangeMark()788 void CXFA_FFDocView::SetChangeMark() {
789 if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End)
790 return;
791
792 m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc.Get());
793 }
794
GetRootSubform()795 CXFA_Subform* CXFA_FFDocView::GetRootSubform() {
796 CXFA_Node* pFormPacketNode =
797 ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form));
798 if (!pFormPacketNode)
799 return nullptr;
800
801 return pFormPacketNode->GetFirstChildByClass<CXFA_Subform>(
802 XFA_Element::Subform);
803 }
804