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/src/fxfa/parser/xfa_script_nodehelper.h" | |
8 | |
9 #include "core/include/fxcrt/fx_ext.h" | |
10 #include "xfa/src/fxfa/fm2js/xfa_fm2jsapi.h" | |
11 #include "xfa/src/fxfa/parser/xfa_docdata.h" | |
12 #include "xfa/src/fxfa/parser/xfa_doclayout.h" | |
13 #include "xfa/src/fxfa/parser/xfa_document.h" | |
14 #include "xfa/src/fxfa/parser/xfa_localemgr.h" | |
15 #include "xfa/src/fxfa/parser/xfa_script_imp.h" | |
16 #include "xfa/src/fxfa/parser/xfa_object.h" | |
17 #include "xfa/src/fxfa/parser/xfa_parser.h" | |
18 #include "xfa/src/fxfa/parser/xfa_script.h" | |
19 #include "xfa/src/fxfa/parser/xfa_utils.h" | |
20 | |
21 CXFA_NodeHelper::CXFA_NodeHelper(void) | |
22 : m_eLastCreateType(XFA_ELEMENT_DataValue), | |
23 m_pCreateParent(NULL), | |
24 m_iCreateCount(0), | |
25 m_iCreateFlag(XFA_RESOLVENODE_RSTYPE_CreateNodeOne), | |
26 m_iCurAllStart(-1), | |
27 m_pAllStartParent(NULL) {} | |
28 CXFA_NodeHelper::~CXFA_NodeHelper(void) {} | |
29 CXFA_Node* CXFA_NodeHelper::XFA_ResolveNodes_GetOneChild( | |
30 CXFA_Node* parent, | |
31 const FX_WCHAR* pwsName, | |
32 FX_BOOL bIsClassName) { | |
33 if (parent == NULL) { | |
34 return NULL; | |
35 } | |
36 CXFA_NodeArray siblings; | |
37 uint32_t uNameHash = FX_HashCode_String_GetW(pwsName, FXSYS_wcslen(pwsName)); | |
38 XFA_NodeAcc_TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName); | |
39 if (siblings.GetSize() == 0) { | |
40 return NULL; | |
41 } | |
42 return siblings[0]; | |
43 } | |
44 int32_t CXFA_NodeHelper::XFA_CountSiblings(CXFA_Node* pNode, | |
45 XFA_LOGIC_TYPE eLogicType, | |
46 CXFA_NodeArray* pSiblings, | |
47 FX_BOOL bIsClassName) { | |
48 if (!pNode) | |
49 return 0; | |
50 CXFA_Node* parent = | |
51 XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
52 if (!parent) | |
53 return 0; | |
54 const XFA_PROPERTY* pProperty = XFA_GetPropertyOfElement( | |
55 parent->GetClassID(), pNode->GetClassID(), XFA_XDPPACKET_UNKNOWN); | |
56 if (!pProperty && eLogicType == XFA_LOGIC_Transparent) { | |
57 parent = XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
58 if (parent == NULL) { | |
59 return 0; | |
60 } | |
61 } | |
62 if (bIsClassName) { | |
63 return XFA_NodeAcc_TraverseSiblings(parent, pNode->GetClassHashCode(), | |
64 pSiblings, eLogicType, bIsClassName); | |
65 } else { | |
66 return XFA_NodeAcc_TraverseSiblings(parent, pNode->GetNameHash(), pSiblings, | |
67 eLogicType, bIsClassName); | |
68 } | |
69 } | |
70 int32_t CXFA_NodeHelper::XFA_NodeAcc_TraverseAnySiblings( | |
71 CXFA_Node* parent, | |
72 FX_DWORD dNameHash, | |
73 CXFA_NodeArray* pSiblings, | |
74 FX_BOOL bIsClassName) { | |
75 if (parent == NULL || pSiblings == NULL) { | |
76 return 0; | |
77 } | |
78 int32_t nCount = 0; | |
79 int32_t i = 0; | |
80 CXFA_NodeArray properties; | |
81 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
82 int32_t nProperties = properties.GetSize(); | |
83 for (i = 0; i < nProperties; ++i) { | |
84 CXFA_Node* child = properties[i]; | |
85 if (bIsClassName) { | |
86 if (child->GetClassHashCode() == dNameHash) { | |
87 pSiblings->Add(child); | |
88 nCount++; | |
89 } | |
90 } else { | |
91 if (child->GetNameHash() == dNameHash) { | |
92 pSiblings->Add(child); | |
93 nCount++; | |
94 } | |
95 } | |
96 if (nCount > 0) { | |
97 return nCount; | |
98 } | |
99 nCount += XFA_NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, | |
100 bIsClassName); | |
101 } | |
102 CXFA_NodeArray children; | |
103 parent->GetNodeList(children, XFA_NODEFILTER_Children); | |
104 int32_t nChildren = children.GetSize(); | |
105 for (i = 0; i < nChildren; i++) { | |
106 CXFA_Node* child = children[i]; | |
107 if (bIsClassName) { | |
108 if (child->GetClassHashCode() == dNameHash) { | |
109 if (pSiblings) { | |
110 pSiblings->Add(child); | |
111 } | |
112 nCount++; | |
113 } | |
114 } else { | |
115 if (child->GetNameHash() == dNameHash) { | |
116 if (pSiblings) { | |
117 pSiblings->Add(child); | |
118 } | |
119 nCount++; | |
120 } | |
121 } | |
122 if (nCount > 0) { | |
123 return nCount; | |
124 } | |
125 nCount += XFA_NodeAcc_TraverseAnySiblings(child, dNameHash, pSiblings, | |
126 bIsClassName); | |
127 } | |
128 return nCount; | |
129 } | |
130 int32_t CXFA_NodeHelper::XFA_NodeAcc_TraverseSiblings(CXFA_Node* parent, | |
131 FX_DWORD dNameHash, | |
132 CXFA_NodeArray* pSiblings, | |
133 XFA_LOGIC_TYPE eLogicType, | |
134 FX_BOOL bIsClassName, | |
135 FX_BOOL bIsFindProperty) { | |
136 if (parent == NULL || pSiblings == NULL) { | |
137 return 0; | |
138 } | |
139 int32_t nCount = 0; | |
140 int32_t i = 0; | |
141 if (bIsFindProperty) { | |
142 CXFA_NodeArray properties; | |
143 parent->GetNodeList(properties, XFA_NODEFILTER_Properties); | |
144 int32_t nProperties = properties.GetSize(); | |
145 for (i = 0; i < nProperties; ++i) { | |
146 CXFA_Node* child = properties[i]; | |
147 if (bIsClassName) { | |
148 if (child->GetClassHashCode() == dNameHash) { | |
149 pSiblings->Add(child); | |
150 nCount++; | |
151 } | |
152 } else { | |
153 if (child->GetNameHash() == dNameHash) { | |
154 if (child->GetClassID() != XFA_ELEMENT_PageSet && | |
155 child->GetClassID() != XFA_ELEMENT_Extras && | |
156 child->GetClassID() != XFA_ELEMENT_Items) { | |
157 pSiblings->Add(child); | |
158 nCount++; | |
159 } | |
160 } | |
161 } | |
162 if (child->IsUnnamed() && child->GetClassID() == XFA_ELEMENT_PageSet) { | |
163 nCount += XFA_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->GetClassID() == 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 (XFA_NodeIsTransparent(child) && | |
198 child->GetClassID() != XFA_ELEMENT_PageSet) { | |
199 nCount += XFA_NodeAcc_TraverseSiblings(child, dNameHash, pSiblings, | |
200 eLogicType, bIsClassName, FALSE); | |
201 } | |
202 } | |
203 return nCount; | |
204 } | |
205 CXFA_Node* CXFA_NodeHelper::XFA_ResolveNodes_GetParent( | |
206 CXFA_Node* pNode, | |
207 XFA_LOGIC_TYPE eLogicType) { | |
208 if (!pNode) { | |
209 return NULL; | |
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 = XFA_ResolveNodes_GetParent(node); | |
218 if (parent == NULL) { | |
219 break; | |
220 } | |
221 XFA_ELEMENT parentElement = parent->GetClassID(); | |
222 if ((!parent->IsUnnamed() && parentElement != XFA_ELEMENT_SubformSet) || | |
223 parentElement == XFA_ELEMENT_Variables) { | |
224 break; | |
225 } | |
226 node = parent; | |
227 } | |
228 return parent; | |
229 } | |
230 int32_t CXFA_NodeHelper::XFA_GetIndex(CXFA_Node* pNode, | |
231 XFA_LOGIC_TYPE eLogicType, | |
232 FX_BOOL bIsProperty, | |
233 FX_BOOL bIsClassIndex) { | |
234 CXFA_Node* parent = | |
235 XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_NoTransparent); | |
236 if (parent == NULL) { | |
237 return 0; | |
238 } | |
239 if (!bIsProperty && eLogicType == XFA_LOGIC_Transparent) { | |
240 parent = XFA_ResolveNodes_GetParent(pNode, XFA_LOGIC_Transparent); | |
241 if (parent == NULL) { | |
242 return 0; | |
243 } | |
244 } | |
245 FX_DWORD dwHashName = pNode->GetNameHash(); | |
246 if (bIsClassIndex) { | |
247 dwHashName = pNode->GetClassHashCode(); | |
248 } | |
249 CXFA_NodeArray siblings; | |
250 int32_t iSize = XFA_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 void CXFA_NodeHelper::XFA_GetNameExpression(CXFA_Node* refNode, | |
261 CFX_WideString& wsName, | |
262 FX_BOOL bIsAllPath, | |
263 XFA_LOGIC_TYPE eLogicType) { | |
264 wsName.Empty(); | |
265 if (bIsAllPath) { | |
266 XFA_GetNameExpression(refNode, wsName, FALSE, eLogicType); | |
267 CFX_WideString wsParent; | |
268 CXFA_Node* parent = | |
269 XFA_ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
270 while (parent) { | |
271 XFA_GetNameExpression(parent, wsParent, FALSE, eLogicType); | |
272 wsParent += L"."; | |
273 wsParent += wsName; | |
274 wsName = wsParent; | |
275 parent = XFA_ResolveNodes_GetParent(parent, XFA_LOGIC_NoTransparent); | |
276 } | |
277 return; | |
278 } | |
279 | |
280 CFX_WideStringC wsTagName; | |
281 CFX_WideString ws; | |
282 FX_BOOL bIsProperty = XFA_NodeIsProperty(refNode); | |
283 if (refNode->IsUnnamed() || | |
284 (bIsProperty && refNode->GetClassID() != XFA_ELEMENT_PageSet)) { | |
285 refNode->GetClassName(wsTagName); | |
286 ws = wsTagName; | |
287 wsName.Format(L"#%s[%d]", (const FX_WCHAR*)ws, | |
288 XFA_GetIndex(refNode, eLogicType, bIsProperty, TRUE)); | |
289 return; | |
290 } | |
291 ws = refNode->GetCData(XFA_ATTRIBUTE_Name); | |
292 ws.Replace(L".", L"\\."); | |
293 wsName.Format(L"%s[%d]", (const FX_WCHAR*)ws, | |
294 XFA_GetIndex(refNode, eLogicType, bIsProperty, FALSE)); | |
295 } | |
296 | |
297 FX_BOOL CXFA_NodeHelper::XFA_NodeIsTransparent(CXFA_Node* refNode) { | |
298 if (refNode == NULL) { | |
299 return FALSE; | |
300 } | |
301 XFA_ELEMENT eRefNode = refNode->GetClassID(); | |
302 if ((refNode->IsUnnamed() && refNode->IsContainerNode()) || | |
303 eRefNode == XFA_ELEMENT_SubformSet || eRefNode == XFA_ELEMENT_Area || | |
304 eRefNode == XFA_ELEMENT_Proto) { | |
305 return TRUE; | |
306 } | |
307 return FALSE; | |
308 } | |
309 FX_BOOL CXFA_NodeHelper::XFA_CreateNode_ForCondition( | |
310 CFX_WideString& wsCondition) { | |
311 int32_t iLen = wsCondition.GetLength(); | |
312 CFX_WideString wsIndex = FX_WSTRC(L"0"); | |
313 FX_BOOL bAll = FALSE; | |
314 | |
315 if (iLen == 0) { | |
316 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
317 return FALSE; | |
318 } | |
319 if (wsCondition.GetAt(0) == '[') { | |
320 int32_t i = 1; | |
321 for (; i < iLen; ++i) { | |
322 FX_WCHAR ch = wsCondition[i]; | |
323 if (ch == ' ') { | |
324 continue; | |
325 } | |
326 if (ch == '+' || ch == '-') { | |
327 break; | |
328 } else if (ch == '*') { | |
329 bAll = TRUE; | |
330 break; | |
331 } else { | |
332 break; | |
333 } | |
334 } | |
335 if (bAll) { | |
336 wsIndex = FX_WSTRC(L"1"); | |
337 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeAll; | |
338 } else { | |
339 m_iCreateFlag = XFA_RESOLVENODE_RSTYPE_CreateNodeOne; | |
340 wsIndex = wsCondition.Mid(i, iLen - 1 - i); | |
341 } | |
342 int32_t iIndex = wsIndex.GetInteger(); | |
343 m_iCreateCount = iIndex; | |
344 return TRUE; | |
345 } | |
346 return FALSE; | |
347 } | |
348 FX_BOOL CXFA_NodeHelper::XFA_ResolveNodes_CreateNode( | |
349 CFX_WideString wsName, | |
350 CFX_WideString wsCondition, | |
351 FX_BOOL bLastNode, | |
352 CXFA_ScriptContext* pScriptContext) { | |
353 if (m_pCreateParent == NULL) { | |
354 return FALSE; | |
355 } | |
356 FX_BOOL bIsClassName = FALSE; | |
357 FX_BOOL bResult = FALSE; | |
358 if (wsName.GetAt(0) == '!') { | |
359 wsName = wsName.Right(wsName.GetLength() - 1); | |
360 m_pCreateParent = ToNode( | |
361 pScriptContext->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets)); | |
362 } | |
363 if (wsName.GetAt(0) == '#') { | |
364 bIsClassName = TRUE; | |
365 wsName = wsName.Right(wsName.GetLength() - 1); | |
366 } | |
367 if (m_iCreateCount == 0) { | |
368 XFA_CreateNode_ForCondition(wsCondition); | |
369 } | |
370 if (bIsClassName) { | |
371 const XFA_ELEMENTINFO* lpElement = XFA_GetElementByName(wsName); | |
372 if (lpElement == NULL) { | |
373 return FALSE; | |
374 } | |
375 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
376 CXFA_Node* pNewNode = | |
377 m_pCreateParent->CreateSamePacketNode(lpElement->eName); | |
378 if (pNewNode) { | |
379 m_pCreateParent->InsertChild(pNewNode); | |
380 if (iIndex == m_iCreateCount - 1) { | |
381 m_pCreateParent = pNewNode; | |
382 } | |
383 bResult = TRUE; | |
384 } | |
385 } | |
386 } else { | |
387 XFA_ELEMENT eClassType = XFA_ELEMENT_DataGroup; | |
388 if (bLastNode) { | |
389 eClassType = m_eLastCreateType; | |
390 } | |
391 for (int32_t iIndex = 0; iIndex < m_iCreateCount; iIndex++) { | |
392 CXFA_Node* pNewNode = m_pCreateParent->CreateSamePacketNode(eClassType); | |
393 if (pNewNode) { | |
394 pNewNode->SetAttribute(XFA_ATTRIBUTE_Name, wsName); | |
395 pNewNode->CreateXMLMappingNode(); | |
396 m_pCreateParent->InsertChild(pNewNode); | |
397 if (iIndex == m_iCreateCount - 1) { | |
398 m_pCreateParent = pNewNode; | |
399 } | |
400 bResult = TRUE; | |
401 } | |
402 } | |
403 } | |
404 if (!bResult) { | |
405 m_pCreateParent = NULL; | |
406 } | |
407 return bResult; | |
408 } | |
409 void CXFA_NodeHelper::XFA_SetCreateNodeType(CXFA_Node* refNode) { | |
410 if (refNode == NULL) { | |
411 return; | |
412 } | |
413 if (refNode->GetClassID() == XFA_ELEMENT_Subform) { | |
414 m_eLastCreateType = XFA_ELEMENT_DataGroup; | |
415 } else if (refNode->GetClassID() == XFA_ELEMENT_Field) { | |
416 m_eLastCreateType = XFA_FieldIsMultiListBox(refNode) | |
417 ? XFA_ELEMENT_DataGroup | |
418 : XFA_ELEMENT_DataValue; | |
419 } else if (refNode->GetClassID() == XFA_ELEMENT_ExclGroup) { | |
420 m_eLastCreateType = XFA_ELEMENT_DataValue; | |
421 } | |
422 } | |
423 FX_BOOL CXFA_NodeHelper::XFA_NodeIsProperty(CXFA_Node* refNode) { | |
424 CXFA_Node* parent = | |
425 XFA_ResolveNodes_GetParent(refNode, XFA_LOGIC_NoTransparent); | |
426 return parent && refNode && | |
427 XFA_GetPropertyOfElement(parent->GetClassID(), refNode->GetClassID(), | |
428 XFA_XDPPACKET_UNKNOWN); | |
429 } | |
OLD | NEW |