| // Copyright 2014 The PDFium Authors |
| // 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/parser/xfa_document_datamerger_imp.h" |
| |
| #include "xfa/fxfa/parser/cxfa_document.h" |
| #include "xfa/fxfa/parser/cxfa_node.h" |
| |
| bool XFA_DataMerge_NeedGenerateForm(CXFA_Node* pTemplateChild, |
| bool bUseInstanceManager) { |
| XFA_Element eType = pTemplateChild->GetElementType(); |
| if (eType == XFA_Element::Variables) |
| return true; |
| if (pTemplateChild->IsContainerNode()) |
| return false; |
| if (eType == XFA_Element::Proto || |
| (bUseInstanceManager && eType == XFA_Element::Occur)) { |
| return false; |
| } |
| return true; |
| } |
| |
| CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument, |
| XFA_Element eType, |
| uint32_t dwNameHash, |
| CXFA_Node* pFormParent) { |
| CXFA_Node* pFormChild = pFormParent->GetFirstChild(); |
| for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) { |
| if (pFormChild->GetElementType() == eType && |
| pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) { |
| return pFormChild; |
| } |
| } |
| return nullptr; |
| } |
| |
| CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer( |
| CXFA_Document* pDocument, |
| CXFA_Node* pFormParent, |
| CXFA_Node* pTemplateNode, |
| bool bRecursive, |
| std::vector<CXFA_Node*>* pSubformArray) { |
| CXFA_Node* pExistingNode = nullptr; |
| if (!pSubformArray) { |
| pExistingNode = XFA_DataMerge_FindFormDOMInstance( |
| pDocument, pTemplateNode->GetElementType(), |
| pTemplateNode->GetNameHash(), pFormParent); |
| } else if (!pSubformArray->empty()) { |
| pExistingNode = pSubformArray->front(); |
| pSubformArray->erase(pSubformArray->begin()); |
| } |
| if (pExistingNode) { |
| if (pSubformArray) { |
| pFormParent->InsertChildAndNotify(pExistingNode, nullptr); |
| } else if (pExistingNode->IsContainerNode()) { |
| pFormParent->RemoveChildAndNotify(pExistingNode, true); |
| pFormParent->InsertChildAndNotify(pExistingNode, nullptr); |
| } |
| pExistingNode->ClearFlag(XFA_NodeFlag::kUnusedNode); |
| pExistingNode->SetTemplateNode(pTemplateNode); |
| if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) { |
| for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); |
| pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { |
| if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) { |
| XFA_NodeMerge_CloneOrMergeContainer( |
| pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr); |
| } |
| } |
| } |
| pExistingNode->SetInitializedFlagAndNotify(); |
| return pExistingNode; |
| } |
| |
| CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false); |
| pFormParent->InsertChildAndNotify(pNewNode, nullptr); |
| if (bRecursive) { |
| for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild(); |
| pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) { |
| if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) { |
| CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true); |
| pNewNode->InsertChildAndNotify(pNewChild, nullptr); |
| } |
| } |
| } |
| return pNewNode; |
| } |
| |
| CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) { |
| if (!pParentFormNode) |
| return nullptr; |
| |
| for (CXFA_Node* pRootBoundNode = pParentFormNode; |
| pRootBoundNode && pRootBoundNode->IsContainerNode(); |
| pRootBoundNode = pRootBoundNode->GetParent()) { |
| CXFA_Node* pDataScope = pRootBoundNode->GetBindData(); |
| if (pDataScope) |
| return pDataScope; |
| } |
| return ToNode( |
| pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data)); |
| } |