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