// 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 #include #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/xml/cfx_xmlparser.h" #include "fxjs/gc/container_trace.h" #include "fxjs/xfa/cfxjse_engine.h" #include "fxjs/xfa/cjx_object.h" #include "third_party/base/stl_util.h" #include "xfa/fxfa/cxfa_ffapp.h" #include "xfa/fxfa/cxfa_ffbarcode.h" #include "xfa/fxfa/cxfa_ffcheckbutton.h" #include "xfa/fxfa/cxfa_ffdoc.h" #include "xfa/fxfa/cxfa_ffexclgroup.h" #include "xfa/fxfa/cxfa_fffield.h" #include "xfa/fxfa/cxfa_ffimage.h" #include "xfa/fxfa/cxfa_ffimageedit.h" #include "xfa/fxfa/cxfa_ffpageview.h" #include "xfa/fxfa/cxfa_ffpushbutton.h" #include "xfa/fxfa/cxfa_ffsignature.h" #include "xfa/fxfa/cxfa_fftext.h" #include "xfa/fxfa/cxfa_ffwidget.h" #include "xfa/fxfa/cxfa_ffwidgethandler.h" #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h" #include "xfa/fxfa/cxfa_readynodeiterator.h" #include "xfa/fxfa/cxfa_textprovider.h" #include "xfa/fxfa/layout/cxfa_layoutprocessor.h" #include "xfa/fxfa/parser/cxfa_acrobat.h" #include "xfa/fxfa/parser/cxfa_binditems.h" #include "xfa/fxfa/parser/cxfa_calculate.h" #include "xfa/fxfa/parser/cxfa_pageset.h" #include "xfa/fxfa/parser/cxfa_present.h" #include "xfa/fxfa/parser/cxfa_subform.h" #include "xfa/fxfa/parser/cxfa_validate.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" #include "xfa/fxfa/parser/xfa_utils.h" namespace { bool IsValidXMLNameString(const WideString& str) { bool first = true; for (const auto ch : str) { if (!CFX_XMLParser::IsXMLNameChar(ch, first)) { return false; } first = false; } return true; } } // namespace const XFA_AttributeValue gs_EventActivity[] = { XFA_AttributeValue::Click, XFA_AttributeValue::Change, XFA_AttributeValue::DocClose, XFA_AttributeValue::DocReady, XFA_AttributeValue::Enter, XFA_AttributeValue::Exit, XFA_AttributeValue::Full, XFA_AttributeValue::IndexChange, XFA_AttributeValue::Initialize, XFA_AttributeValue::MouseDown, XFA_AttributeValue::MouseEnter, XFA_AttributeValue::MouseExit, XFA_AttributeValue::MouseUp, XFA_AttributeValue::PostExecute, XFA_AttributeValue::PostOpen, XFA_AttributeValue::PostPrint, XFA_AttributeValue::PostSave, XFA_AttributeValue::PostSign, XFA_AttributeValue::PostSubmit, XFA_AttributeValue::PreExecute, XFA_AttributeValue::PreOpen, XFA_AttributeValue::PrePrint, XFA_AttributeValue::PreSave, XFA_AttributeValue::PreSign, XFA_AttributeValue::PreSubmit, XFA_AttributeValue::Ready, XFA_AttributeValue::Unknown, }; CXFA_FFDocView::CXFA_FFDocView(CXFA_FFDoc* pDoc) : m_pDoc(pDoc) {} CXFA_FFDocView::~CXFA_FFDocView() = default; void CXFA_FFDocView::Trace(cppgc::Visitor* visitor) const { visitor->Trace(m_pDoc); visitor->Trace(m_pWidgetHandler); visitor->Trace(m_pFocusNode); visitor->Trace(m_pFocusWidget); ContainerTrace(visitor, m_ValidateNodes); ContainerTrace(visitor, m_CalculateNodes); ContainerTrace(visitor, m_NewAddedNodes); ContainerTrace(visitor, m_BindItems); ContainerTrace(visitor, m_IndexChangedSubforms); } void CXFA_FFDocView::InitLayout(CXFA_Node* pNode) { RunBindItems(); ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Initialize, false, true); ExecEventActivityByDeepFirst(pNode, XFA_EVENT_IndexChange, false, true); } int32_t CXFA_FFDocView::StartLayout() { m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; m_pDoc->GetXFADoc()->DoProtoMerge(); m_pDoc->GetXFADoc()->DoDataMerge(); int32_t iStatus = GetLayoutProcessor()->StartLayout(false); 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); m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_Start; return iStatus; } int32_t CXFA_FFDocView::DoLayout() { int32_t iStatus = GetLayoutProcessor()->DoLayout(); 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_Subform* pSubformNode = pRootItem->GetChild(0, XFA_Element::Subform, false); if (!pSubformNode) return; CXFA_PageSet* pPageSetNode = pSubformNode->GetFirstChildByClass(XFA_Element::PageSet); if (!pPageSetNode) return; RunCalculateWidgets(); RunValidate(); InitLayout(pPageSetNode); InitCalculate(pPageSetNode); InitValidate(pPageSetNode); ExecEventActivityByDeepFirst(pPageSetNode, XFA_EVENT_Ready, true, true); ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true); ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_DocReady, false, true); RunCalculateWidgets(); RunValidate(); if (RunLayout()) ExecEventActivityByDeepFirst(pRootItem, XFA_EVENT_Ready, false, true); m_CalculateNodes.clear(); if (m_pFocusNode && !m_pFocusWidget) SetFocusNode(m_pFocusNode); m_iStatus = XFA_DOCVIEW_LAYOUTSTATUS_End; } void CXFA_FFDocView::ShowNullTestMsg() { int32_t iCount = pdfium::CollectionSize(m_NullTestMsgArray); CXFA_FFApp* pApp = m_pDoc->GetApp(); IXFA_AppProvider* pAppProvider = pApp->GetAppProvider(); if (pAppProvider && iCount) { int32_t iRemain = iCount > 7 ? iCount - 7 : 0; iCount -= iRemain; WideString wsMsg; for (int32_t i = 0; i < iCount; i++) wsMsg += m_NullTestMsgArray[i] + L"\n"; if (iRemain > 0) { wsMsg += L"\n" + WideString::Format( L"Message limit exceeded. Remaining %d " L"validation errors not reported.", iRemain); } pAppProvider->MsgBox(wsMsg, pAppProvider->GetAppTitle(), static_cast(AlertIcon::kStatus), static_cast(AlertButton::kOK)); } m_NullTestMsgArray.clear(); } void CXFA_FFDocView::UpdateDocView() { if (IsUpdateLocked()) return; LockUpdate(); while (!m_NewAddedNodes.empty()) { CXFA_Node* pNode = m_NewAddedNodes.front(); m_NewAddedNodes.pop_front(); InitCalculate(pNode); InitValidate(pNode); ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true); } RunSubformIndexChange(); RunCalculateWidgets(); RunValidate(); ShowNullTestMsg(); if (RunLayout() && m_bLayoutEvent) RunEventLayoutReady(); m_bLayoutEvent = false; m_CalculateNodes.clear(); UnlockUpdate(); } void CXFA_FFDocView::UpdateUIDisplay(CXFA_Node* pNode, CXFA_FFWidget* pExcept) { CXFA_FFWidget* pWidget = GetWidgetForNode(pNode); CXFA_FFWidget* pNext = nullptr; for (; pWidget; pWidget = pNext) { pNext = pWidget->GetNextFFWidget(); if (pWidget == pExcept || !pWidget->IsLoaded() || (pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton && pWidget->IsFocused())) { continue; } pWidget->UpdateFWLData(); pWidget->InvalidateRect(); } } int32_t CXFA_FFDocView::CountPageViews() const { CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor(); return pProcessor ? pProcessor->CountPages() : 0; } CXFA_FFPageView* CXFA_FFDocView::GetPageView(int32_t nIndex) const { CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor(); if (!pProcessor) return nullptr; auto* pPage = pProcessor->GetPage(nIndex); return pPage ? pPage->GetPageView() : nullptr; } CXFA_LayoutProcessor* CXFA_FFDocView::GetLayoutProcessor() const { return CXFA_LayoutProcessor::FromDocument(m_pDoc->GetXFADoc()); } bool CXFA_FFDocView::ResetSingleNodeData(CXFA_Node* pNode) { XFA_Element eType = pNode->GetElementType(); if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup) return false; pNode->ResetData(); UpdateUIDisplay(pNode, nullptr); CXFA_Validate* validate = pNode->GetValidateIfExists(); if (!validate) return true; AddValidateNode(pNode); validate->SetFlag(XFA_NodeFlag_NeedsInitApp); return true; } void CXFA_FFDocView::ResetNode(CXFA_Node* pNode) { m_bLayoutEvent = true; bool bChanged = false; CXFA_Node* pFormNode = nullptr; if (pNode) { bChanged = ResetSingleNodeData(pNode); pFormNode = pNode; } else { pFormNode = GetRootSubform(); } if (!pFormNode) return; if (pFormNode->GetElementType() != XFA_Element::Field && pFormNode->GetElementType() != XFA_Element::ExclGroup) { CXFA_ReadyNodeIterator it(pFormNode); while (CXFA_Node* next_node = it.MoveToNext()) { bChanged |= ResetSingleNodeData(next_node); if (next_node->GetElementType() == XFA_Element::ExclGroup) it.SkipTree(); } } if (bChanged) m_pDoc->SetChangeMark(); } CXFA_FFWidget* CXFA_FFDocView::GetWidgetForNode(CXFA_Node* node) { return GetFFWidget( ToContentLayoutItem(GetLayoutProcessor()->GetLayoutItem(node))); } CXFA_FFWidgetHandler* CXFA_FFDocView::GetWidgetHandler() { if (!m_pWidgetHandler) { m_pWidgetHandler = cppgc::MakeGarbageCollected( m_pDoc->GetHeap()->GetAllocationHandle(), this); } return m_pWidgetHandler; } bool CXFA_FFDocView::SetFocus(CXFA_FFWidget* pNewFocus) { if (pNewFocus == m_pFocusWidget) return false; if (m_pFocusWidget) { CXFA_ContentLayoutItem* pItem = m_pFocusWidget->GetLayoutItem(); if (pItem->TestStatusBits(XFA_WidgetStatus_Visible) && !pItem->TestStatusBits(XFA_WidgetStatus_Focused)) { if (!m_pFocusWidget->IsLoaded()) m_pFocusWidget->LoadWidget(); if (!m_pFocusWidget->OnSetFocus(m_pFocusWidget)) m_pFocusWidget.Clear(); } } if (m_pFocusWidget) { if (!m_pFocusWidget->OnKillFocus(pNewFocus)) return false; } if (pNewFocus) { if (pNewFocus->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible)) { if (!pNewFocus->IsLoaded()) pNewFocus->LoadWidget(); if (!pNewFocus->OnSetFocus(m_pFocusWidget)) pNewFocus = nullptr; } } if (pNewFocus) { CXFA_Node* node = pNewFocus->GetNode(); m_pFocusNode = node->IsWidgetReady() ? node : nullptr; m_pFocusWidget = pNewFocus; } else { m_pFocusNode.Clear(); m_pFocusWidget.Clear(); } return true; } void CXFA_FFDocView::SetFocusNode(CXFA_Node* node) { CXFA_FFWidget* pNewFocus = node ? GetWidgetForNode(node) : nullptr; if (!SetFocus(pNewFocus)) return; m_pFocusNode = node; if (m_iStatus != XFA_DOCVIEW_LAYOUTSTATUS_End) return; m_pDoc->SetFocusWidget(m_pFocusWidget); } void CXFA_FFDocView::DeleteLayoutItem(CXFA_FFWidget* pWidget) { if (m_pFocusNode != pWidget->GetNode()) return; m_pFocusNode.Clear(); m_pFocusWidget.Clear(); } static XFA_EventError XFA_ProcessEvent(CXFA_FFDocView* pDocView, CXFA_Node* pNode, CXFA_EventParam* pParam) { if (!pParam || pParam->m_eType == XFA_EVENT_Unknown) return XFA_EventError::kNotExist; if (pNode && pNode->GetElementType() == XFA_Element::Draw) return XFA_EventError::kNotExist; switch (pParam->m_eType) { case XFA_EVENT_Calculate: return pNode->ProcessCalculate(pDocView); case XFA_EVENT_Validate: if (pDocView->GetDoc()->IsValidationsEnabled()) return pNode->ProcessValidate(pDocView, 0x01); return XFA_EventError::kDisabled; case XFA_EVENT_InitCalculate: { CXFA_Calculate* calc = pNode->GetCalculateIfExists(); if (!calc) return XFA_EventError::kNotExist; if (pNode->IsUserInteractive()) return XFA_EventError::kDisabled; return pNode->ExecuteScript(pDocView, calc->GetScriptIfExists(), pParam); } default: return pNode->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType], pParam); } } XFA_EventError CXFA_FFDocView::ExecEventActivityByDeepFirst( CXFA_Node* pFormNode, XFA_EVENTTYPE eEventType, bool bIsFormReady, bool bRecursive) { if (!pFormNode) return XFA_EventError::kNotExist; XFA_Element elementType = pFormNode->GetElementType(); if (elementType == XFA_Element::Field) { if (eEventType == XFA_EVENT_IndexChange) return XFA_EventError::kNotExist; if (!pFormNode->IsWidgetReady()) return XFA_EventError::kNotExist; CXFA_EventParam eParam; eParam.m_eType = eEventType; eParam.m_pTarget = pFormNode; eParam.m_bIsFormReady = bIsFormReady; return XFA_ProcessEvent(this, pFormNode, &eParam); } XFA_EventError iRet = XFA_EventError::kNotExist; if (bRecursive) { for (CXFA_Node* pNode = pFormNode->GetFirstContainerChild(); pNode; pNode = pNode->GetNextContainerSibling()) { elementType = pNode->GetElementType(); if (elementType != XFA_Element::Variables && elementType != XFA_Element::Draw) { XFA_EventErrorAccumulate( &iRet, ExecEventActivityByDeepFirst(pNode, eEventType, bIsFormReady, bRecursive)); } } } if (!pFormNode->IsWidgetReady()) return iRet; CXFA_EventParam eParam; eParam.m_eType = eEventType; eParam.m_pTarget = pFormNode; eParam.m_bIsFormReady = bIsFormReady; XFA_EventErrorAccumulate(&iRet, XFA_ProcessEvent(this, pFormNode, &eParam)); return iRet; } CXFA_FFWidget* CXFA_FFDocView::GetWidgetByName(const WideString& wsName, CXFA_FFWidget* pRefWidget) { if (!IsValidXMLNameString(wsName)) { return nullptr; } CFXJSE_Engine* pScriptContext = m_pDoc->GetXFADoc()->GetScriptContext(); CXFA_Node* pRefNode = nullptr; if (pRefWidget) { CXFA_Node* node = pRefWidget->GetNode(); pRefNode = node->IsWidgetReady() ? node : nullptr; } WideString wsExpression = (!pRefNode ? L"$form." : L"") + wsName; XFA_ResolveNodeRS resolveNodeRS; constexpr uint32_t kStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent; if (!pScriptContext->ResolveObjects(pRefNode, wsExpression.AsStringView(), &resolveNodeRS, kStyle, nullptr)) { return nullptr; } if (resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) { CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode(); if (pNode && pNode->IsWidgetReady()) return GetWidgetForNode(pNode); } return nullptr; } void CXFA_FFDocView::OnPageEvent(CXFA_ViewLayoutItem* pSender, uint32_t dwEvent) { CXFA_FFPageView* pFFPageView = pSender ? pSender->GetPageView() : nullptr; m_pDoc->PageViewEvent(pFFPageView, dwEvent); } void CXFA_FFDocView::InvalidateRect(CXFA_FFPageView* pPageView, const CFX_RectF& rtInvalidate) { m_pDoc->InvalidateRect(pPageView, rtInvalidate); } bool CXFA_FFDocView::RunLayout() { LockUpdate(); m_bInLayoutStatus = true; CXFA_LayoutProcessor* pProcessor = GetLayoutProcessor(); if (!pProcessor->IncrementLayout() && pProcessor->StartLayout(false) < 100) { pProcessor->DoLayout(); UnlockUpdate(); m_bInLayoutStatus = false; m_pDoc->PageViewEvent(nullptr, XFA_PAGEVIEWEVENT_StopLayout); return true; } m_bInLayoutStatus = false; m_pDoc->PageViewEvent(nullptr, XFA_PAGEVIEWEVENT_StopLayout); UnlockUpdate(); return false; } void CXFA_FFDocView::RunSubformIndexChange() { std::set seen; while (!m_IndexChangedSubforms.empty()) { CXFA_Node* pSubformNode = m_IndexChangedSubforms.front(); m_IndexChangedSubforms.pop_front(); bool bInserted = seen.insert(pSubformNode).second; if (!bInserted || !pSubformNode->IsWidgetReady()) continue; CXFA_EventParam eParam; eParam.m_eType = XFA_EVENT_IndexChange; eParam.m_pTarget = pSubformNode; pSubformNode->ProcessEvent(this, XFA_AttributeValue::IndexChange, &eParam); } } 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); if (!pdfium::Contains(m_IndexChangedSubforms, pNode)) 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); } void CXFA_FFDocView::AddCalculateNode(CXFA_Node* node) { CXFA_Node* pCurrentNode = !m_CalculateNodes.empty() ? m_CalculateNodes.back() : nullptr; if (pCurrentNode != node) m_CalculateNodes.push_back(node); } void CXFA_FFDocView::AddCalculateNodeNotify(CXFA_Node* pNodeChange) { CJX_Object::CalcData* pGlobalData = pNodeChange->JSObject()->GetCalcData(); if (!pGlobalData) return; for (auto pResult : pGlobalData->m_Globals) { if (!pResult->HasRemovedChildren() && pResult->IsWidgetReady()) AddCalculateNode(pResult); } } size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) { while (index < m_CalculateNodes.size()) { CXFA_Node* node = m_CalculateNodes[index]; AddCalculateNodeNotify(node); size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1; node->JSObject()->SetCalcRecursionCount(recurse); if (recurse > 11) break; if (node->ProcessCalculate(this) == XFA_EventError::kSuccess && node->IsWidgetReady()) { AddValidateNode(node); } index = RunCalculateRecursive(++index); } return index; } XFA_EventError CXFA_FFDocView::RunCalculateWidgets() { if (!m_pDoc->IsCalculationsEnabled()) return XFA_EventError::kDisabled; if (!m_CalculateNodes.empty()) RunCalculateRecursive(0); for (CXFA_Node* node : m_CalculateNodes) node->JSObject()->SetCalcRecursionCount(0); m_CalculateNodes.clear(); return XFA_EventError::kSuccess; } void CXFA_FFDocView::AddValidateNode(CXFA_Node* node) { if (!pdfium::Contains(m_ValidateNodes, node)) m_ValidateNodes.push_back(node); } void CXFA_FFDocView::InitCalculate(CXFA_Node* pNode) { ExecEventActivityByDeepFirst(pNode, XFA_EVENT_InitCalculate, false, true); } void CXFA_FFDocView::ProcessValueChanged(CXFA_Node* node) { AddValidateNode(node); AddCalculateNode(node); RunCalculateWidgets(); RunValidate(); } bool CXFA_FFDocView::InitValidate(CXFA_Node* pNode) { if (!m_pDoc->IsValidationsEnabled()) return false; ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Validate, false, true); m_ValidateNodes.clear(); return true; } bool CXFA_FFDocView::RunValidate() { if (!m_pDoc->IsValidationsEnabled()) return false; while (!m_ValidateNodes.empty()) { CXFA_Node* node = m_ValidateNodes.front(); m_ValidateNodes.pop_front(); if (!node->HasRemovedChildren()) node->ProcessValidate(this, 0); } 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); RunLayout(); return true; } void CXFA_FFDocView::RunBindItems() { while (!m_BindItems.empty()) { CXFA_BindItems* item = m_BindItems.front(); m_BindItems.pop_front(); if (item->HasRemovedChildren()) continue; CXFA_Node* pWidgetNode = item->GetParent(); if (!pWidgetNode || !pWidgetNode->IsWidgetReady()) continue; CFXJSE_Engine* pScriptContext = pWidgetNode->GetDocument()->GetScriptContext(); WideString wsRef = item->GetRef(); constexpr uint32_t kStyle = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_ALL; XFA_ResolveNodeRS rs; pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs, kStyle, nullptr); pWidgetNode->DeleteItem(-1, false, false); if (rs.dwFlags != XFA_ResolveNodeRS::Type::kNodes || rs.objects.empty()) continue; WideString wsValueRef = item->GetValueRef(); WideString wsLabelRef = item->GetLabelRef(); const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef; const bool bLabelUseContent = wsLabelRef.IsEmpty() || wsLabelRef.EqualsASCII("$"); const bool bValueUseContent = wsValueRef.IsEmpty() || wsValueRef.EqualsASCII("$"); WideString wsValue; WideString wsLabel; uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false); for (auto& refObject : rs.objects) { CXFA_Node* refNode = refObject->AsNode(); if (!refNode) continue; if (bValueUseContent) { wsValue = refNode->JSObject()->GetContent(false); } else { CXFA_Node* nodeValue = refNode->GetFirstChildByName(uValueHash); wsValue = nodeValue ? nodeValue->JSObject()->GetContent(false) : refNode->JSObject()->GetContent(false); } if (!bUseValue) { if (bLabelUseContent) { wsLabel = refNode->JSObject()->GetContent(false); } else { CXFA_Node* nodeLabel = refNode->GetFirstChildByName(wsLabelRef.AsStringView()); if (nodeLabel) wsLabel = nodeLabel->JSObject()->GetContent(false); } } else { wsLabel = wsValue; } pWidgetNode->InsertItem(wsLabel, wsValue, false); } } } void CXFA_FFDocView::SetChangeMark() { if (m_iStatus < XFA_DOCVIEW_LAYOUTSTATUS_End) return; m_pDoc->SetChangeMark(); } 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); }