• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/parser/xfa_document_datamerger_imp.h"
8 
9 #include "xfa/fxfa/parser/cxfa_document.h"
10 #include "xfa/fxfa/parser/cxfa_node.h"
11 
XFA_DataMerge_NeedGenerateForm(CXFA_Node * pTemplateChild,bool bUseInstanceManager)12 bool XFA_DataMerge_NeedGenerateForm(CXFA_Node* pTemplateChild,
13                                     bool bUseInstanceManager) {
14   XFA_Element eType = pTemplateChild->GetElementType();
15   if (eType == XFA_Element::Variables)
16     return true;
17   if (pTemplateChild->IsContainerNode())
18     return false;
19   if (eType == XFA_Element::Proto ||
20       (bUseInstanceManager && eType == XFA_Element::Occur)) {
21     return false;
22   }
23   return true;
24 }
25 
26 
XFA_DataMerge_FindFormDOMInstance(CXFA_Document * pDocument,XFA_Element eType,uint32_t dwNameHash,CXFA_Node * pFormParent)27 CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument,
28                                              XFA_Element eType,
29                                              uint32_t dwNameHash,
30                                              CXFA_Node* pFormParent) {
31   CXFA_Node* pFormChild = pFormParent->GetFirstChild();
32   for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) {
33     if (pFormChild->GetElementType() == eType &&
34         pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) {
35       return pFormChild;
36     }
37   }
38   return nullptr;
39 }
40 
XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,bool bRecursive,std::vector<CXFA_Node * > * pSubformArray)41 CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(
42     CXFA_Document* pDocument,
43     CXFA_Node* pFormParent,
44     CXFA_Node* pTemplateNode,
45     bool bRecursive,
46     std::vector<CXFA_Node*>* pSubformArray) {
47   CXFA_Node* pExistingNode = nullptr;
48   if (!pSubformArray) {
49     pExistingNode = XFA_DataMerge_FindFormDOMInstance(
50         pDocument, pTemplateNode->GetElementType(),
51         pTemplateNode->GetNameHash(), pFormParent);
52   } else if (!pSubformArray->empty()) {
53     pExistingNode = pSubformArray->front();
54     pSubformArray->erase(pSubformArray->begin());
55   }
56   if (pExistingNode) {
57     if (pSubformArray) {
58       pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
59     } else if (pExistingNode->IsContainerNode()) {
60       pFormParent->RemoveChildAndNotify(pExistingNode, true);
61       pFormParent->InsertChildAndNotify(pExistingNode, nullptr);
62     }
63     pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
64     pExistingNode->SetTemplateNode(pTemplateNode);
65     if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) {
66       for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
67            pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
68         if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
69           XFA_NodeMerge_CloneOrMergeContainer(
70               pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr);
71         }
72       }
73     }
74     pExistingNode->SetFlagAndNotify(XFA_NodeFlag_Initialized);
75     return pExistingNode;
76   }
77 
78   CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false);
79   pFormParent->InsertChildAndNotify(pNewNode, nullptr);
80   if (bRecursive) {
81     for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
82          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
83       if (XFA_DataMerge_NeedGenerateForm(pTemplateChild, true)) {
84         CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true);
85         pNewNode->InsertChildAndNotify(pNewChild, nullptr);
86       }
87     }
88   }
89   return pNewNode;
90 }
91 
XFA_DataMerge_FindDataScope(CXFA_Node * pParentFormNode)92 CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) {
93   if (!pParentFormNode)
94     return nullptr;
95 
96   for (CXFA_Node* pRootBoundNode = pParentFormNode;
97        pRootBoundNode && pRootBoundNode->IsContainerNode();
98        pRootBoundNode = pRootBoundNode->GetParent()) {
99     CXFA_Node* pDataScope = pRootBoundNode->GetBindData();
100     if (pDataScope)
101       return pDataScope;
102   }
103   return ToNode(
104       pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data));
105 }
106 
107