diff options
Diffstat (limited to 'xfa/fxfa/cxfa_ffdocview.cpp')
-rw-r--r-- | xfa/fxfa/cxfa_ffdocview.cpp | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp new file mode 100644 index 0000000000..9708e34562 --- /dev/null +++ b/xfa/fxfa/cxfa_ffdocview.cpp @@ -0,0 +1,790 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "xfa/fxfa/cxfa_ffdocview.h" + +#include "core/fxcrt/fx_ext.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" +#include "xfa/fxfa/app/xfa_ffbarcode.h" +#include "xfa/fxfa/app/xfa_ffcheckbutton.h" +#include "xfa/fxfa/app/xfa_ffchoicelist.h" +#include "xfa/fxfa/app/xfa_ffdraw.h" +#include "xfa/fxfa/app/xfa_ffexclgroup.h" +#include "xfa/fxfa/app/xfa_fffield.h" +#include "xfa/fxfa/app/xfa_ffimage.h" +#include "xfa/fxfa/app/xfa_ffimageedit.h" +#include "xfa/fxfa/app/xfa_ffpath.h" +#include "xfa/fxfa/app/xfa_ffpushbutton.h" +#include "xfa/fxfa/app/xfa_ffsignature.h" +#include "xfa/fxfa/app/xfa_ffsubform.h" +#include "xfa/fxfa/app/xfa_fftext.h" +#include "xfa/fxfa/app/xfa_fftextedit.h" +#include "xfa/fxfa/app/xfa_ffwidgetacc.h" +#include "xfa/fxfa/app/xfa_fwladapter.h" +#include "xfa/fxfa/cxfa_ffapp.h" +#include "xfa/fxfa/cxfa_ffdoc.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" +#include "xfa/fxfa/cxfa_ffwidgethandler.h" +#include "xfa/fxfa/cxfa_widgetacciterator.h" +#include "xfa/fxfa/parser/cxfa_binditems.h" +#include "xfa/fxfa/parser/cxfa_layoutprocessor.h" +#include "xfa/fxfa/parser/cxfa_scriptcontext.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +const XFA_ATTRIBUTEENUM gs_EventActivity[] = { + XFA_ATTRIBUTEENUM_Click, XFA_ATTRIBUTEENUM_Change, + XFA_ATTRIBUTEENUM_DocClose, XFA_ATTRIBUTEENUM_DocReady, + XFA_ATTRIBUTEENUM_Enter, XFA_ATTRIBUTEENUM_Exit, + XFA_ATTRIBUTEENUM_Full, XFA_ATTRIBUTEENUM_IndexChange, + XFA_ATTRIBUTEENUM_Initialize, XFA_ATTRIBUTEENUM_MouseDown, + XFA_ATTRIBUTEENUM_MouseEnter, XFA_ATTRIBUTEENUM_MouseExit, + XFA_ATTRIBUTEENUM_MouseUp, XFA_ATTRIBUTEENUM_PostExecute, + XFA_ATTRIBUTEENUM_PostOpen, XFA_ATTRIBUTEENUM_PostPrint, + XFA_ATTRIBUTEENUM_PostSave, XFA_ATTRIBUTEENUM_PostSign, + XFA_ATTRIBUTEENUM_PostSubmit, XFA_ATTRIBUTEENUM_PreExecute, + XFA_ATTRIBUTEENUM_PreOpen, XFA_ATTRIBUTEENUM_PrePrint, + XFA_ATTRIBUTEENUM_PreSave, XFA_ATTRIBUTEENUM_PreSign, + XFA_ATTRIBUTEENUM_PreSubmit, XFA_ATTRIBUTEENUM_Ready, + XFA_ATTRIBUTEENUM_Unknown, +}; + +CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) + : m_bLayoutEvent(false), + m_pListFocusWidget(nullptr), + m_bInLayoutStatus(false), + m_pDoc(pDoc), + m_pXFADocLayout(nullptr), + m_pFocusAcc(nullptr), + m_pFocusWidget(nullptr), + m_pOldFocusWidget(nullptr), + m_iStatus(XFA_DOCVIEW_LAYOUTSTATUS_None), + m_iLock(0) {} + +CXFA_FFDocView::~CXFA_FFDocView() { + DestroyDocView(); +} + +void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) { + RunBindItems(); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true, + nullptr); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true, + nullptr); +} +int32_t CXFA_FFDocView::StartLayout(int32_t iStartPage) { + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; + m_pDoc->GetXFADoc()->DoProtoMerge(); + m_pDoc->GetXFADoc()->DoDataMerge(); + m_pXFADocLayout = GetXFALayout(); + int32_t iStatus = m_pXFADocLayout->StartLayout(); + if (iStatus < 0) { + return iStatus; + } + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) { + return iStatus; + } + InitLayout(pRootItem); + InitCalculate(pRootItem); + InitValidate(pRootItem); + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, true, true, nullptr); + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; + return iStatus; +} +int32_t CXFA_FFDocView::DoLayout(IFX_Pause* pPause) { + int32_t iStatus = 100; + iStatus = m_pXFADocLayout->DoLayout(pPause); + if (iStatus != 100) { + return iStatus; + } + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Doing; + return iStatus; +} +void CXFA_FFDocView::StopLayout() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) { + return; + } + CXFA_Node* pSubformNode = pRootItem->GetChild(0, XFA_Element::Subform); + if (!pSubformNode) { + return; + } + CXFA_Node* pPageSetNode = + pSubformNode->GetFirstChildByClass(XFA_Element::PageSet); + if (!pPageSetNode) { + return; + } + RunCalculateWidgets(); + RunValidate(); + InitLayout(pPageSetNode); + InitCalculate(pPageSetNode); + InitValidate(pPageSetNode); + ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true, + nullptr); + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true, + nullptr); + RunCalculateWidgets(); + RunValidate(); + if (RunLayout()) { + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + } + m_CalculateAccs.clear(); + if (m_pFocusAcc && !m_pFocusWidget) { + SetFocusWidgetAcc(m_pFocusAcc); + } + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End; +} +int32_t CXFA_FFDocView::GetLayoutStatus() { + return m_iStatus; +} +void CXFA_FFDocView::ShowNullTestMsg() { + int32_t iCount = pdfium::CollectionSize<int32_t>(m_arrNullTestMsg); + CXFA_FFApp* pApp = m_pDoc->GetApp(); + IXFA_AppProvider* pAppProvider = pApp->GetAppProvider(); + if (pAppProvider && iCount) { + int32_t iRemain = iCount > 7 ? iCount - 7 : 0; + iCount -= iRemain; + CFX_WideString wsMsg; + for (int32_t i = 0; i < iCount; i++) { + wsMsg += m_arrNullTestMsg[i] + L"\n"; + } + if (iRemain > 0) { + CFX_WideString wsTemp; + wsTemp.Format( + L"Message limit exceeded. Remaining %d " + L"validation errors not reported.", + iRemain); + wsMsg += L"\n" + wsTemp; + } + pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), XFA_MBICON_Status, + XFA_MB_OK); + } + m_arrNullTestMsg.clear(); +} + +void CXFA_FFDocView::UpdateDocView() { + if (IsUpdateLocked()) + return; + + LockUpdate(); + for (CXFA_Node* pNode : m_NewAddedNodes) { + InitCalculate(pNode); + InitValidate(pNode); + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true, nullptr); + } + m_NewAddedNodes.clear(); + RunSubformIndexChange(); + RunCalculateWidgets(); + RunValidate(); + ShowNullTestMsg(); + if (RunLayout() && m_bLayoutEvent) + RunEventLayoutReady(); + + m_bLayoutEvent = false; + m_CalculateAccs.clear(); + RunInvalidate(); + UnlockUpdate(); +} + +int32_t CXFA_FFDocView::CountPageViews() { + if (!m_pXFADocLayout) { + return 0; + } + return m_pXFADocLayout->CountPages(); +} +CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) { + if (!m_pXFADocLayout) { + return nullptr; + } + return static_cast<CXFA_FFPageView*>(m_pXFADocLayout->GetPage(nIndex)); +} + +CXFA_LayoutProcessor* CXFA_FFDocView::GetXFALayout() const { + return m_pDoc->GetXFADoc()->GetDocLayout(); +} +bool CXFA_FFDocView::ResetSingleWidgetAccData(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_Node* pNode = pWidgetAcc->GetNode(); + XFA_Element eType = pNode->GetElementType(); + if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) { + return false; + } + pWidgetAcc->ResetData(); + pWidgetAcc->UpdateUIDisplay(); + if (CXFA_Validate validate = pWidgetAcc->GetValidate()) { + AddValidateWidget(pWidgetAcc); + validate.GetNode()->SetFlag(XFA_NodeFlag_NeedsInitApp, false); + } + return true; +} +void CXFA_FFDocView::ResetWidgetData(CXFA_WidgetAcc* pWidgetAcc) { + m_bLayoutEvent = true; + bool bChanged = false; + CXFA_Node* pFormNode = nullptr; + if (pWidgetAcc) { + bChanged = ResetSingleWidgetAccData(pWidgetAcc); + pFormNode = pWidgetAcc->GetNode(); + } else { + pFormNode = GetRootSubform(); + } + if (!pFormNode) { + return; + } + if (pFormNode->GetElementType() != XFA_Element::Field && + pFormNode->GetElementType() != XFA_Element::ExclGroup) { + CXFA_WidgetAccIterator Iterator(pFormNode); + while (CXFA_WidgetAcc* pAcc = Iterator.MoveToNext()) { + bChanged |= ResetSingleWidgetAccData(pAcc); + if (pAcc->GetNode()->GetElementType() == XFA_Element::ExclGroup) { + Iterator.SkipTree(); + } + } + } + if (bChanged) { + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); + } +} +int32_t CXFA_FFDocView::ProcessWidgetEvent(CXFA_EventParam* pParam, + CXFA_WidgetAcc* pWidgetAcc) { + if (!pParam) + return XFA_EVENTERROR_Error; + + if (pParam->m_eType == XFA_EVENT_Validate) { + CFX_WideString wsValidateStr(L"preSubmit"); + CXFA_Node* pConfigItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Config)); + if (pConfigItem) { + CXFA_Node* pValidateNode = nullptr; + CXFA_Node* pAcrobatNode = pConfigItem->GetChild(0, XFA_Element::Acrobat); + pValidateNode = pAcrobatNode + ? pAcrobatNode->GetChild(0, XFA_Element::Validate) + : nullptr; + if (!pValidateNode) { + CXFA_Node* pPresentNode = + pConfigItem->GetChild(0, XFA_Element::Present); + pValidateNode = pPresentNode + ? pPresentNode->GetChild(0, XFA_Element::Validate) + : nullptr; + } + if (pValidateNode) + wsValidateStr = pValidateNode->GetContent(); + } + + if (wsValidateStr.Find(L"preSubmit") == -1) + return XFA_EVENTERROR_Success; + } + + CXFA_Node* pNode = pWidgetAcc ? pWidgetAcc->GetNode() : nullptr; + if (!pNode) { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) + return XFA_EVENTERROR_Error; + + pNode = pRootItem->GetChild(0, XFA_Element::Subform); + } + ExecEventActivityByDeepFirst(pNode, pParam->m_eType, pParam->m_bIsFormReady, + true, nullptr); + return XFA_EVENTERROR_Success; +} + +CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() { + if (!m_pWidgetHandler) + m_pWidgetHandler = pdfium::MakeUnique<CXFA_FFWidgetHandler>(this); + + return m_pWidgetHandler.get(); +} + +CXFA_WidgetAccIterator* CXFA_FFDocView::CreateWidgetAccIterator( + XFA_WIDGETORDER eOrder) { + CXFA_Node* pFormRoot = GetRootSubform(); + return pFormRoot ? new CXFA_WidgetAccIterator(pFormRoot) : nullptr; +} + +CXFA_FFWidget* CXFA_FFDocView::GetFocusWidget() { + return m_pFocusWidget; +} + +void CXFA_FFDocView::KillFocus() { + if (m_pFocusWidget && + (m_pFocusWidget->GetStatus() & XFA_WidgetStatus_Focused)) { + (m_pFocusWidget)->OnKillFocus(nullptr); + } + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; +} +bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* hWidget) { + CXFA_FFWidget* pNewFocus = hWidget; + if (m_pOldFocusWidget == pNewFocus) { + return false; + } + CXFA_FFWidget* pOldFocus = m_pOldFocusWidget; + m_pOldFocusWidget = pNewFocus; + if (pOldFocus) { + if (m_pFocusWidget != m_pOldFocusWidget && + (pOldFocus->GetStatus() & XFA_WidgetStatus_Focused)) { + m_pFocusWidget = pOldFocus; + pOldFocus->OnKillFocus(pNewFocus); + } else if ((pOldFocus->GetStatus() & XFA_WidgetStatus_Visible)) { + if (!pOldFocus->IsLoaded()) { + pOldFocus->LoadWidget(); + } + pOldFocus->OnSetFocus(m_pFocusWidget); + m_pFocusWidget = pOldFocus; + pOldFocus->OnKillFocus(pNewFocus); + } + } + if (m_pFocusWidget == m_pOldFocusWidget) { + return false; + } + pNewFocus = m_pOldFocusWidget; + if (m_pListFocusWidget && pNewFocus == m_pListFocusWidget) { + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pListFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; + return false; + } + if (pNewFocus && (pNewFocus->GetStatus() & XFA_WidgetStatus_Visible)) { + if (!pNewFocus->IsLoaded()) { + pNewFocus->LoadWidget(); + } + pNewFocus->OnSetFocus(m_pFocusWidget); + } + m_pFocusAcc = pNewFocus ? pNewFocus->GetDataAcc() : nullptr; + m_pFocusWidget = pNewFocus; + m_pOldFocusWidget = m_pFocusWidget; + return true; +} +CXFA_WidgetAcc* CXFA_FFDocView::GetFocusWidgetAcc() { + return m_pFocusAcc; +} +void CXFA_FFDocView::SetFocusWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_FFWidget* pNewFocus = + pWidgetAcc ? pWidgetAcc->GetNextWidget(nullptr) : nullptr; + if (SetFocus(pNewFocus)) { + m_pFocusAcc = pWidgetAcc; + if (m_iStatus == XFA_DOCVIEW_LAYOUTSTATUS_End) { + m_pDoc->GetDocEnvironment()->SetFocusWidget(m_pDoc, m_pFocusWidget); + } + } +} +void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) { + if (m_pFocusAcc == pWidget->GetDataAcc()) { + m_pFocusAcc = nullptr; + m_pFocusWidget = nullptr; + m_pOldFocusWidget = nullptr; + } +} +static int32_t XFA_ProcessEvent(CXFA_FFDocView* pDocView, + CXFA_WidgetAcc* pWidgetAcc, + CXFA_EventParam* pParam) { + if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) { + return XFA_EVENTERROR_NotExist; + } + if (!pWidgetAcc || pWidgetAcc->GetElementType() == XFA_Element::Draw) { + return XFA_EVENTERROR_NotExist; + } + switch (pParam->m_eType) { + case XFA_EVENT_Calculate: + return pWidgetAcc->ProcessCalculate(); + case XFA_EVENT_Validate: + if (((CXFA_FFDoc*)pDocView->GetDoc()) + ->GetDocEnvironment() + ->IsValidationsEnabled(pDocView->GetDoc())) { + return pWidgetAcc->ProcessValidate(0x01); + } + return XFA_EVENTERROR_Disabled; + case XFA_EVENT_InitCalculate: { + CXFA_Calculate calc = pWidgetAcc->GetCalculate(); + if (!calc) { + return XFA_EVENTERROR_NotExist; + } + if (pWidgetAcc->GetNode()->IsUserInteractive()) + return XFA_EVENTERROR_Disabled; + + CXFA_Script script = calc.GetScript(); + return pWidgetAcc->ExecuteScript(script, pParam); + } + default: + break; + } + int32_t iRet = + pWidgetAcc->ProcessEvent(gs_EventActivity[pParam->m_eType], pParam); + return iRet; +} +int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode, + XFA_EVENTTYPE eEventType, + bool bIsFormReady, + bool bRecursive, + CXFA_Node* pExclude) { + int32_t iRet = XFA_EVENTERROR_NotExist; + if (pFormNode == pExclude) { + return iRet; + } + XFA_Element elementType = pFormNode->GetElementType(); + if (elementType == XFA_Element::Field) { + if (eEventType == XFA_EVENT_IndexChange) { + return iRet; + } + CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData(); + if (!pWidgetAcc) { + return iRet; + } + CXFA_EventParam eParam; + eParam.m_eType = eEventType; + eParam.m_pTarget = pWidgetAcc; + eParam.m_bIsFormReady = bIsFormReady; + return XFA_ProcessEvent(this, pWidgetAcc, &eParam); + } + if (bRecursive) { + for (CXFA_Node* pNode = pFormNode->GetNodeItem( + XFA_NODEITEM_FirstChild, XFA_ObjectType::ContainerNode); + pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling, + XFA_ObjectType::ContainerNode)) { + elementType = pNode->GetElementType(); + if (elementType != XFA_Element::Variables && + elementType != XFA_Element::Draw) { + iRet |= ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady, + bRecursive, pExclude); + } + } + } + CXFA_WidgetAcc* pWidgetAcc = (CXFA_WidgetAcc*)pFormNode->GetWidgetData(); + if (!pWidgetAcc) { + return iRet; + } + CXFA_EventParam eParam; + eParam.m_eType = eEventType; + eParam.m_pTarget = pWidgetAcc; + eParam.m_bIsFormReady = bIsFormReady; + iRet |= XFA_ProcessEvent(this, pWidgetAcc, &eParam); + return iRet; +} + +CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const CFX_WideString& wsName, + CXFA_FFWidget* pRefWidget) { + CXFA_WidgetAcc* pRefAcc = pRefWidget ? pRefWidget->GetDataAcc() : nullptr; + CXFA_WidgetAcc* pAcc = GetWidgetAccByName(wsName, pRefAcc); + return pAcc ? pAcc->GetNextWidget(nullptr) : nullptr; +} + +CXFA_WidgetAcc* CXFA_FFDocView::GetWidgetAccByName( + const CFX_WideString& wsName, + CXFA_WidgetAcc* pRefWidgetAcc) { + CFX_WideString wsExpression; + uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; + CXFA_ScriptContext* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext(); + if (!pScriptContext) { + return nullptr; + } + CXFA_Node* refNode = nullptr; + if (pRefWidgetAcc) { + refNode = pRefWidgetAcc->GetNode(); + wsExpression = wsName; + } else { + wsExpression = L"$form." + wsName; + } + XFA_RESOLVENODE_RS resoveNodeRS; + int32_t iRet = pScriptContext->ResolveObjects( + refNode, wsExpression.AsStringC(), resoveNodeRS, dwStyle); + if (iRet < 1) { + return nullptr; + } + if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { + CXFA_Node* pNode = resoveNodeRS.objects.front()->AsNode(); + if (pNode) + return static_cast<CXFA_WidgetAcc*>(pNode->GetWidgetData()); + } + return nullptr; +} + +void CXFA_FFDocView::OnPageEvent(CXFA_ContainerLayoutItem* pSender, + uint32_t dwEvent) { + CXFA_FFPageView* pFFPageView = static_cast<CXFA_FFPageView*>(pSender); + m_pDoc->GetDocEnvironment()->PageViewEvent(pFFPageView, dwEvent); +} + +void CXFA_FFDocView::LockUpdate() { + m_iLock++; +} +void CXFA_FFDocView::UnlockUpdate() { + m_iLock--; +} +bool CXFA_FFDocView::IsUpdateLocked() { + return m_iLock > 0; +} +void CXFA_FFDocView::ClearInvalidateList() { + m_mapPageInvalidate.clear(); +} +void CXFA_FFDocView::AddInvalidateRect(CXFA_FFWidget* pWidget, + const CFX_RectF& rtInvalidate) { + AddInvalidateRect(pWidget->GetPageView(), rtInvalidate); +} + +void CXFA_FFDocView::AddInvalidateRect(CXFA_FFPageView* pPageView, + const CFX_RectF& rtInvalidate) { + if (m_mapPageInvalidate[pPageView]) { + m_mapPageInvalidate[pPageView]->Union(rtInvalidate); + return; + } + m_mapPageInvalidate[pPageView] = pdfium::MakeUnique<CFX_RectF>(rtInvalidate); +} + +void CXFA_FFDocView::RunInvalidate() { + for (const auto& pair : m_mapPageInvalidate) + m_pDoc->GetDocEnvironment()->InvalidateRect(pair.first, *pair.second); + m_mapPageInvalidate.clear(); +} + +bool CXFA_FFDocView::RunLayout() { + LockUpdate(); + m_bInLayoutStatus = true; + if (!m_pXFADocLayout->IncrementLayout() && + m_pXFADocLayout->StartLayout() < 100) { + m_pXFADocLayout->DoLayout(); + UnlockUpdate(); + m_bInLayoutStatus = false; + m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, + XFA_PAGEVIEWEVENT_StopLayout); + return true; + } + m_bInLayoutStatus = false; + m_pDoc->GetDocEnvironment()->PageViewEvent(nullptr, + XFA_PAGEVIEWEVENT_StopLayout); + UnlockUpdate(); + return false; +} + +void CXFA_FFDocView::RunSubformIndexChange() { + for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) { + CXFA_WidgetAcc* pWidgetAcc = + static_cast<CXFA_WidgetAcc*>(pSubformNode->GetWidgetData()); + if (!pWidgetAcc) + continue; + + CXFA_EventParam eParam; + eParam.m_eType = XFA_EVENT_IndexChange; + eParam.m_pTarget = pWidgetAcc; + pWidgetAcc->ProcessEvent(XFA_ATTRIBUTEENUM_IndexChange, &eParam); + } + m_IndexChangedSubforms.clear(); +} + +void CXFA_FFDocView::AddNewFormNode(CXFA_Node* pNode) { + m_NewAddedNodes.push_back(pNode); + InitLayout(pNode); +} + +void CXFA_FFDocView::AddIndexChangedSubform(CXFA_Node* pNode) { + ASSERT(pNode->GetElementType() == XFA_Element::Subform); + m_IndexChangedSubforms.push_back(pNode); +} + +void CXFA_FFDocView::RunDocClose() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) { + return; + } + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocClose, false, true, + nullptr); +} + +void CXFA_FFDocView::DestroyDocView() { + ClearInvalidateList(); + m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_None; + m_iLock = 0; + m_ValidateAccs.clear(); + m_BindItems.clear(); + m_CalculateAccs.clear(); +} + +bool CXFA_FFDocView::IsStaticNotify() { + return m_pDoc->GetDocType() == XFA_DocType::Static; +} + +void CXFA_FFDocView::AddCalculateWidgetAcc(CXFA_WidgetAcc* pWidgetAcc) { + CXFA_WidgetAcc* pCurrentAcc = + !m_CalculateAccs.empty() ? m_CalculateAccs.back() : nullptr; + if (pCurrentAcc != pWidgetAcc) + m_CalculateAccs.push_back(pWidgetAcc); +} + +void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) { + auto* pGlobalData = + static_cast<CXFA_CalcData*>(pNodeChange->GetUserData(XFA_CalcData)); + if (!pGlobalData) + return; + + for (auto* pResultAcc : pGlobalData->m_Globals) { + if (!pResultAcc->GetNode()->HasRemovedChildren()) + AddCalculateWidgetAcc(pResultAcc); + } +} + +void CXFA_FFDocView::RunCalculateRecursive(int32_t& iIndex) { + while (iIndex < pdfium::CollectionSize<int32_t>(m_CalculateAccs)) { + CXFA_WidgetAcc* pCurAcc = m_CalculateAccs[iIndex]; + AddCalculateNodeNotify(pCurAcc->GetNode()); + int32_t iRefCount = + (int32_t)(uintptr_t)pCurAcc->GetNode()->GetUserData(XFA_CalcRefCount); + iRefCount++; + pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, + (void*)(uintptr_t)iRefCount); + if (iRefCount > 11) { + break; + } + if ((pCurAcc->ProcessCalculate()) == XFA_EVENTERROR_Success) { + AddValidateWidget(pCurAcc); + } + iIndex++; + RunCalculateRecursive(iIndex); + } +} + +int32_t CXFA_FFDocView::RunCalculateWidgets() { + if (!m_pDoc->GetDocEnvironment()->IsCalculationsEnabled(m_pDoc)) { + return XFA_EVENTERROR_Disabled; + } + int32_t iCounts = pdfium::CollectionSize<int32_t>(m_CalculateAccs); + int32_t iIndex = 0; + if (iCounts > 0) + RunCalculateRecursive(iIndex); + + for (CXFA_WidgetAcc* pCurAcc : m_CalculateAccs) + pCurAcc->GetNode()->SetUserData(XFA_CalcRefCount, (void*)(uintptr_t)0); + + m_CalculateAccs.clear(); + return XFA_EVENTERROR_Success; +} + +void CXFA_FFDocView::AddValidateWidget(CXFA_WidgetAcc* pWidget) { + if (!pdfium::ContainsValue(m_ValidateAccs, pWidget)) + m_ValidateAccs.push_back(pWidget); +} + +bool CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) { + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true, + nullptr); + return true; +} + +bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) { + if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc)) + return false; + + ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true, nullptr); + m_ValidateAccs.clear(); + return true; +} + +bool CXFA_FFDocView::RunValidate() { + if (!m_pDoc->GetDocEnvironment()->IsValidationsEnabled(m_pDoc)) + return false; + + for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) { + if (!pAcc->GetNode()->HasRemovedChildren()) + pAcc->ProcessValidate(); + } + m_ValidateAccs.clear(); + return true; +} +bool CXFA_FFDocView::RunEventLayoutReady() { + CXFA_Node* pRootItem = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pRootItem) { + return false; + } + ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true, + nullptr); + RunLayout(); + return true; +} + +void CXFA_FFDocView::RunBindItems() { + for (auto* item : m_BindItems) { + if (item->HasRemovedChildren()) + continue; + + CXFA_Node* pWidgetNode = item->GetNodeItem(XFA_NODEITEM_Parent); + CXFA_WidgetAcc* pAcc = + static_cast<CXFA_WidgetAcc*>(pWidgetNode->GetWidgetData()); + if (!pAcc) + continue; + + CXFA_BindItems binditems(item); + CXFA_ScriptContext* pScriptContext = + pWidgetNode->GetDocument()->GetScriptContext(); + CFX_WideStringC wsRef; + binditems.GetRef(wsRef); + uint32_t dwStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_ALL; + XFA_RESOLVENODE_RS rs; + pScriptContext->ResolveObjects(pWidgetNode, wsRef, rs, dwStyle); + pAcc->DeleteItem(-1); + if (rs.dwFlags != XFA_RESOVENODE_RSTYPE_Nodes || rs.objects.empty()) + continue; + + CFX_WideStringC wsValueRef, wsLabelRef; + binditems.GetValueRef(wsValueRef); + binditems.GetLabelRef(wsLabelRef); + const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef; + const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef == L"$"; + const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef == L"$"; + CFX_WideString wsValue; + CFX_WideString wsLabel; + uint32_t uValueHash = FX_HashCode_GetW(wsValueRef, false); + for (CXFA_Object* refObject : rs.objects) { + CXFA_Node* refNode = refObject->AsNode(); + if (!refNode) + continue; + if (bValueUseContent) { + wsValue = refNode->GetContent(); + } else { + CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash); + wsValue = nodeValue ? nodeValue->GetContent() : refNode->GetContent(); + } + if (!bUseValue) { + if (bLabelUseContent) { + wsLabel = refNode->GetContent(); + } else { + CXFA_Node* nodeLabel = refNode->GetFirstChildByName(wsLabelRef); + if (nodeLabel) + wsLabel = nodeLabel->GetContent(); + } + } else { + wsLabel = wsValue; + } + pAcc->InsertItem(wsLabel, wsValue); + } + } + m_BindItems.clear(); +} + +void CXFA_FFDocView::SetChangeMark() { + if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) { + return; + } + m_pDoc->GetDocEnvironment()->SetChangeMark(m_pDoc); +} +CXFA_Node* CXFA_FFDocView::GetRootSubform() { + CXFA_Node* pFormPacketNode = + ToNode(m_pDoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)); + if (!pFormPacketNode) { + return nullptr; + } + return pFormPacketNode->GetFirstChildByClass(XFA_Element::Subform); +} |