OLD | NEW |
| (Empty) |
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_script_nodehelper.h" | |
8 | |
9 #include "core/fxcrt/include/fx_ext.h" | |
10 #include "xfa/fxfa/parser/xfa_doclayout.h" | |
11 #include "xfa/fxfa/parser/xfa_document.h" | |
12 #include "xfa/fxfa/parser/xfa_localemgr.h" | |
13 #include "xfa/fxfa/parser/xfa_object.h" | |
14 #include "xfa/fxfa/parser/xfa_script.h" | |
15 #include "xfa/fxfa/parser/xfa_script_imp.h" | |
16 #include "xfa/fxfa/parser/xfa_utils.h" | |
17 | |
18 CXFA_NodeHelper::CXFA_NodeHelper() | |
19 : m_eLastCreateType(XFA_Element::DataValue), | |
20 m_pCreateParent(nullptr), | |
21 m_iCreateCount(0), | |
22 m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne), | |
23 m_iCurAllStart(-1), | |
24 m_pAllStartParent(nullptr) {} | |
25 | |
26 CXFA_NodeHelper::~CXFA_NodeHelper() {} | |
27 | |
28 CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetOneChild(CXFA_Node* parent, | |
29 const FX_WCHAR* pwsName, | |
30 FX_BOOL bIsClassName) { | |
31 if (!parent) { | |
32 return nullptr; | |
33 } | |
34 CXFA_NodeArray siblings; | |
35 uint32_t uNameHash = FX_HashCode_GetW(CFX_WideStringC(pwsName), false); | |
36 NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName); | |
37 if (siblings.GetSize() == 0) { | |
38 return nullptr; | |
39 } | |
40 return siblings[0]; | |
41 } | |
42 | |
43 int32_t CXFA_NodeHelper::CountSiblings(CXFA_Node* pNode, | |
44 XFA_LOGIC_TYPE eLogicType, | |
45 CXFA_NodeArray* pSiblings, | |
46 FX_BOOL bIsClassName) { | |
47 if (!pNode) | |
48 return 0; | |
49 CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
50 if (!parent) | |
51 return 0; | |
52 const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( | |
53 parent->GetElementType(), pNode->GetElementType(), XFA_XDPPACKET_UNKNOWN); | |
54 if (!pProperty && eLogicType == XFA_LOGIC_Transparent) { | |
55 parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
56 if (!parent) { | |
57 return 0; | |
58 } | |
59 } | |
60 if (bIsClassName) { | |
61 return NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(), | |
62 pSiblings, eLogicType, bIsClassName); | |
63 } else { | |
64 return NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings, | |
65 eLogicType, bIsClassName); | |
66 } | |
67 } | |
68 | |
69 int32_t CXFA_NodeHelper::NodeAcc_TraverseAnySiblings(CXFA_Node* parent, | |
70 uint32_t dNameHash, | |
71 CXFA_NodeArray* pSiblings, | |
72 FX_BOOL bIsClassName) { | |
73 if (!parent || !pSiblings) { | |
74 return 0; | |
75 } | |
76 int32_t nCount = 0; | |
77 int32_t i = 0; | |
78 CXFA_NodeArray properties; | |
79 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
80 int32_t nProperties = properties.GetSize(); | |
81 for (i = 0; i < nProperties; ++i) { | |
82 CXFA_Node* child = properties[i]; | |
83 if (bIsClassName) { | |
84 if (child->GetClassHashCode() == dNameHash) { | |
85 pSiblings->Add(child); | |
86 nCount++; | |
87 } | |
88 } else { | |
89 if (child->GetNameHash() == dNameHash) { | |
90 pSiblings->Add(child); | |
91 nCount++; | |
92 } | |
93 } | |
94 if (nCount > 0) { | |
95 return nCount; | |
96 } | |
97 nCount += | |
98 NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); | |
99 } | |
100 CXFA_NodeArray children; | |
101 parent->GetNodeList(children, XFA_NODEFILTER_Children); | |
102 int32_t nChildren = children.GetSize(); | |
103 for (i = 0; i < nChildren; i++) { | |
104 CXFA_Node* child = children[i]; | |
105 if (bIsClassName) { | |
106 if (child->GetClassHashCode() == dNameHash) { | |
107 if (pSiblings) { | |
108 pSiblings->Add(child); | |
109 } | |
110 nCount++; | |
111 } | |
112 } else { | |
113 if (child->GetNameHash() == dNameHash) { | |
114 if (pSiblings) { | |
115 pSiblings->Add(child); | |
116 } | |
117 nCount++; | |
118 } | |
119 } | |
120 if (nCount > 0) { | |
121 return nCount; | |
122 } | |
123 nCount += | |
124 NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName); | |
125 } | |
126 return nCount; | |
127 } | |
128 | |
129 int32_t CXFA_NodeHelper::NodeAcc_TraverseSiblings(CXFA_Node* parent, | |
130 uint32_t dNameHash, | |
131 CXFA_NodeArray* pSiblings, | |
132 XFA_LOGIC_TYPE eLogicType, | |
133 FX_BOOL bIsClassName, | |
134 FX_BOOL bIsFindProperty) { | |
135 if (!parent || !pSiblings) { | |
136 return 0; | |
137 } | |
138 int32_t nCount = 0; | |
139 int32_t i = 0; | |
140 if (bIsFindProperty) { | |
141 CXFA_NodeArray properties; | |
142 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
143 int32_t nProperties = properties.GetSize(); | |
144 for (i = 0; i < nProperties; ++i) { | |
145 CXFA_Node* child = properties[i]; | |
146 if (bIsClassName) { | |
147 if (child->GetClassHashCode() == dNameHash) { | |
148 pSiblings->Add(child); | |
149 nCount++; | |
150 } | |
151 } else { | |
152 if (child->GetNameHash() == dNameHash) { | |
153 if (child->GetElementType() != XFA_Element::PageSet && | |
154 child->GetElementType() != XFA_Element::Extras && | |
155 child->GetElementType() != XFA_Element::Items) { | |
156 pSiblings->Add(child); | |
157 nCount++; | |
158 } | |
159 } | |
160 } | |
161 if (child->IsUnnamed() && | |
162 child->GetElementType() == XFA_Element::PageSet) { | |
163 nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings, | |
164 eLogicType, bIsClassName, FALSE); | |
165 } | |
166 } | |
167 if (nCount > 0) { | |
168 return nCount; | |
169 } | |
170 } | |
171 CXFA_NodeArray children; | |
172 parent->GetNodeList(children, XFA_NODEFILTER_Children); | |
173 int32_t nChildren = children.GetSize(); | |
174 for (i = 0; i < nChildren; i++) { | |
175 CXFA_Node* child = children[i]; | |
176 if (child->GetElementType() == XFA_Element::Variables) { | |
177 continue; | |
178 } | |
179 if (bIsClassName) { | |
180 if (child->GetClassHashCode() == dNameHash) { | |
181 if (pSiblings) { | |
182 pSiblings->Add(child); | |
183 } | |
184 nCount++; | |
185 } | |
186 } else { | |
187 if (child->GetNameHash() == dNameHash) { | |
188 if (pSiblings) { | |
189 pSiblings->Add(child); | |
190 } | |
191 nCount++; | |
192 } | |
193 } | |
194 if (eLogicType == XFA_LOGIC_NoTransparent) { | |
195 continue; | |
196 } | |
197 if (NodeIsTransparent(child) && | |
198 child->GetElementType() != XFA_Element::PageSet) { | |
199 nCount += NodeAcc_TraverseSiblings(child, dNameHash, pSiblings, | |
200 eLogicType, bIsClassName, FALSE); | |
201 } | |
202 } | |
203 return nCount; | |
204 } | |
205 | |
206 CXFA_Node* CXFA_NodeHelper::ResolveNodes_GetParent(CXFA_Node* pNode, | |
207 XFA_LOGIC_TYPE eLogicType) { | |
208 if (!pNode) { | |
209 return nullptr; | |
210 } | |
211 if (eLogicType == XFA_LOGIC_NoTransparent) { | |
212 return pNode->GetNodeItem(XFA_NODEITEM_Parent); | |
213 } | |
214 CXFA_Node* parent; | |
215 CXFA_Node* node = pNode; | |
216 while (TRUE) { | |
217 parent = ResolveNodes_GetParent(node); | |
218 if (!parent) { | |
219 break; | |
220 } | |
221 XFA_Element parentType = parent->GetElementType(); | |
222 if ((!parent->IsUnnamed() && parentType != XFA_Element::SubformSet) || | |
223 parentType == XFA_Element::Variables) { | |
224 break; | |
225 } | |
226 node = parent; | |
227 } | |
228 return parent; | |
229 } | |
230 | |
231 int32_t CXFA_NodeHelper::GetIndex(CXFA_Node* pNode, | |
232 XFA_LOGIC_TYPE eLogicType, | |
233 FX_BOOL bIsProperty, | |
234 FX_BOOL bIsClassIndex) { | |
235 CXFA_Node* parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
236 if (!parent) { | |
237 return 0; | |
238 } | |
239 if (!bIsProperty && eLogicType == XFA_LOGIC_Transparent) { | |
240 parent = ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
241 if (!parent) { | |
242 return 0; | |
243 } | |
244 } | |
245 uint32_t dwHashName = pNode->GetNameHash(); | |
246 if (bIsClassIndex) { | |
247 dwHashName = pNode->GetClassHashCode(); | |
248 } | |
249 CXFA_NodeArray siblings; | |
250 int32_t iSize = NodeAcc_TraverseSiblings(parent, dwHashName, &siblings, | |
251 eLogicType, bIsClassIndex); | |
252 for (int32_t i = 0; i < iSize; ++i) { | |
253 CXFA_Node* child = siblings[i]; | |
254 if (child == pNode) { | |
255 return i; | |
256 } | |
257 } | |
258 return 0; | |
259 } | |
260 | |
261 void CXFA_NodeHelper::GetNameExpression(CXFA_Node* refNode, | |
262 CFX_WideString& wsName, | |
263 FX_BOOL bIsAllPath, | |
264 XFA_LOGIC_TYPE eLogicType) { | |
265 wsName.clear(); | |
266 if (bIsAllPath) { | |
267 GetNameExpression(refNode, wsName, FALSE, eLogicType); | |
268 CFX_WideString wsParent; | |
269 CXFA_Node* parent = | |
270 ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
271 while (parent) { | |
272 GetNameExpression(parent, wsParent, FALSE, eLogicType); | |
273 wsParent += L"."; | |
274 wsParent += wsName; | |
275 wsName = wsParent; | |
276 parent = ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent); | |
277 } | |
278 return; | |
279 } | |
280 | |
281 CFX_WideString ws; | |
282 FX_BOOL bIsProperty = NodeIsProperty(refNode); | |
283 if (refNode->IsUnnamed() || | |
284 (bIsProperty && refNode->GetElementType() != XFA_Element::PageSet)) { | |
285 ws = refNode->GetClassName(); | |
286 wsName.Format(L"#%s[%d]", ws.c_str(), | |
287 GetIndex(refNode, eLogicType, bIsProperty, TRUE)); | |
288 return; | |
289 } | |
290 ws = refNode->GetCData(XFA_ATTRIBUTE_Name); | |
291 ws.Replace(L".", L"\\."); | |
292 wsName.Format(L"%s[%d]", ws.c_str(), | |
293 GetIndex(refNode, eLogicType, bIsProperty, FALSE)); | |
294 } | |
295 | |
296 FX_BOOL CXFA_NodeHelper::NodeIsTransparent(CXFA_Node* refNode) { | |
297 if (!refNode) { | |
298 return FALSE; | |
299 } | |
300 XFA_Element refNodeType = refNode->GetElementType(); | |
301 if ((refNode->IsUnnamed() && refNode->IsContainerNode()) || | |
302 refNodeType == XFA_Element::SubformSet || | |
303 refNodeType == XFA_Element::Area || refNodeType == XFA_Element::Proto) { | |
304 return TRUE; | |
305 } | |
306 return FALSE; | |
307 } | |
308 | |
309 FX_BOOL CXFA_NodeHelper::CreateNode_ForCondition(CFX_WideString& wsCondition) { | |
310 int32_t iLen = wsCondition.GetLength(); | |
311 CFX_WideString wsIndex(L"0"); | |
312 FX_BOOL bAll = FALSE; | |
313 if (iLen == 0) { | |
314 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
315 return FALSE; | |
316 } | |
317 if (wsCondition.GetAt(0) == '[') { | |
318 int32_t i = 1; | |
319 for (; i < iLen; ++i) { | |
320 FX_WCHAR ch = wsCondition[i]; | |
321 if (ch == ' ') { | |
322 continue; | |
323 } | |
324 if (ch == '+' || ch == '-') { | |
325 break; | |
326 } else if (ch == '*') { | |
327 bAll = TRUE; | |
328 break; | |
329 } else { | |
330 break; | |
331 } | |
332 } | |
333 if (bAll) { | |
334 wsIndex = FX_WSTRC(L"1"); | |
335 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll; | |
336 } else { | |
337 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
338 wsIndex = wsCondition.Mid(i, iLen - 1 - i); | |
339 } | |
340 int32_t iIndex = wsIndex.GetInteger(); | |
341 m_iCreateCount = iIndex; | |
342 return TRUE; | |
343 } | |
344 return FALSE; | |
345 } | |
346 | |
347 FX_BOOL CXFA_NodeHelper::ResolveNodes_CreateNode( | |
348 CFX_WideString wsName, | |
349 CFX_WideString wsCondition, | |
350 FX_BOOL bLastNode, | |
351 CXFA_ScriptContext* pScriptContext) { | |
352 if (!m_pCreateParent) { | |
353 return FALSE; | |
354 } | |
355 FX_BOOL bIsClassName = FALSE; | |
356 FX_BOOL bResult = FALSE; | |
357 if (wsName.GetAt(0) == '!') { | |
358 wsName = wsName.Right(wsName.GetLength() - 1); | |
359 m_pCreateParent = ToNode( | |
360 pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); | |
361 } | |
362 if (wsName.GetAt(0) == '#') { | |
363 bIsClassName = TRUE; | |
364 wsName = wsName.Right(wsName.GetLength() - 1); | |
365 } | |
366 if (m_iCreateCount == 0) { | |
367 CreateNode_ForCondition(wsCondition); | |
368 } | |
369 if (bIsClassName) { | |
370 XFA_Element eType = XFA_GetElementTypeForName(wsName.AsStringC()); | |
371 if (eType == XFA_Element::Unknown) | |
372 return FALSE; | |
373 | |
374 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
375 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eType); | |
376 if (pNewNode) { | |
377 m_pCreateParent->InsertChild(pNewNode); | |
378 if (iIndex == m_iCreateCount - 1) { | |
379 m_pCreateParent = pNewNode; | |
380 } | |
381 bResult = TRUE; | |
382 } | |
383 } | |
384 } else { | |
385 XFA_Element eClassType = XFA_Element::DataGroup; | |
386 if (bLastNode) { | |
387 eClassType = m_eLastCreateType; | |
388 } | |
389 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
390 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType); | |
391 if (pNewNode) { | |
392 pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName.AsStringC()); | |
393 pNewNode->CreateXMLMappingNode(); | |
394 m_pCreateParent->InsertChild(pNewNode); | |
395 if (iIndex == m_iCreateCount - 1) { | |
396 m_pCreateParent = pNewNode; | |
397 } | |
398 bResult = TRUE; | |
399 } | |
400 } | |
401 } | |
402 if (!bResult) { | |
403 m_pCreateParent = nullptr; | |
404 } | |
405 return bResult; | |
406 } | |
407 | |
408 void CXFA_NodeHelper::SetCreateNodeType(CXFA_Node* refNode) { | |
409 if (!refNode) { | |
410 return; | |
411 } | |
412 if (refNode->GetElementType() == XFA_Element::Subform) { | |
413 m_eLastCreateType = XFA_Element::DataGroup; | |
414 } else if (refNode->GetElementType() == XFA_Element::Field) { | |
415 m_eLastCreateType = XFA_FieldIsMultiListBox(refNode) | |
416 ? XFA_Element::DataGroup | |
417 : XFA_Element::DataValue; | |
418 } else if (refNode->GetElementType() == XFA_Element::ExclGroup) { | |
419 m_eLastCreateType = XFA_Element::DataValue; | |
420 } | |
421 } | |
422 | |
423 FX_BOOL CXFA_NodeHelper::NodeIsProperty(CXFA_Node* refNode) { | |
424 CXFA_Node* parent = ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
425 return parent && refNode && | |
426 XFA_GetPropertyOfElement(parent->GetElementType(), | |
427 refNode->GetElementType(), | |
428 XFA_XDPPACKET_UNKNOWN); | |
429 } | |
OLD | NEW |