Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxfa / src / parser / xfa_utils_imp.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../foxitlib.h"\r
8 #include "../common/xfa_utils.h"\r
9 #include "../common/xfa_object.h"\r
10 #include "../common/xfa_document.h"\r
11 #include "../common/xfa_parser.h"\r
12 #include "../common/xfa_script.h"\r
13 #include "../common/xfa_docdata.h"\r
14 #include "../common/xfa_doclayout.h"\r
15 #include "../common/xfa_debug.h"\r
16 #include "../common/xfa_localemgr.h"\r
17 #include "../common/xfa_fm2jsapi.h"\r
18 #include "xfa_debug_parser.h"\r
19 CXFA_Node* XFA_CreateUIChild(CXFA_Node* pNode, XFA_ELEMENT& eWidgetType)\r
20 {\r
21     XFA_ELEMENT eType = pNode->GetClassID();\r
22     eWidgetType = eType;\r
23     if (eType != XFA_ELEMENT_Field && eType != XFA_ELEMENT_Draw) {\r
24         return NULL;\r
25     }\r
26     eWidgetType = XFA_ELEMENT_UNKNOWN;\r
27     XFA_ELEMENT eUIType = XFA_ELEMENT_UNKNOWN;\r
28     CXFA_Value defValue = pNode->GetProperty(0, XFA_ELEMENT_Value, TRUE);\r
29     XFA_ELEMENT eValueType = (XFA_ELEMENT)defValue.GetChildValueClassID();\r
30     switch (eValueType) {\r
31         case XFA_ELEMENT_Boolean:\r
32             eUIType = XFA_ELEMENT_CheckButton;\r
33             break;\r
34         case XFA_ELEMENT_Integer:\r
35         case XFA_ELEMENT_Decimal:\r
36         case XFA_ELEMENT_Float:\r
37             eUIType = XFA_ELEMENT_NumericEdit;\r
38             break;\r
39         case XFA_ELEMENT_ExData:\r
40         case XFA_ELEMENT_Text:\r
41             eUIType = XFA_ELEMENT_TextEdit;\r
42             eWidgetType = XFA_ELEMENT_Text;\r
43             break;\r
44         case XFA_ELEMENT_Date:\r
45         case XFA_ELEMENT_Time:\r
46         case XFA_ELEMENT_DateTime:\r
47             eUIType = XFA_ELEMENT_DateTimeEdit;\r
48             break;\r
49         case XFA_ELEMENT_Image:\r
50             eUIType = XFA_ELEMENT_ImageEdit;\r
51             eWidgetType = XFA_ELEMENT_Image;\r
52             break;;\r
53         case XFA_ELEMENT_Arc:\r
54         case XFA_ELEMENT_Line:\r
55         case XFA_ELEMENT_Rectangle:\r
56             eUIType = XFA_ELEMENT_DefaultUi;\r
57             eWidgetType = eValueType;\r
58             break;\r
59         default:\r
60             break;\r
61     }\r
62     CXFA_Node* pUIChild = NULL;\r
63     CXFA_Node* pUI = pNode->GetProperty(0, XFA_ELEMENT_Ui, TRUE);\r
64     CXFA_Node *pChild = pUI->GetNodeItem(XFA_NODEITEM_FirstChild);\r
65     for ( ; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {\r
66         XFA_ELEMENT eChild = pChild->GetClassID();\r
67         if (eChild == XFA_ELEMENT_Extras || eChild == XFA_ELEMENT_Picture) {\r
68             continue;\r
69         }\r
70         XFA_LPCPROPERTY pProterty = XFA_GetPropertyOfElement(XFA_ELEMENT_Ui, eChild, XFA_XDPPACKET_Form);\r
71         if (pProterty && (pProterty->uFlags & XFA_PROPERTYFLAG_OneOf)) {\r
72             pUIChild = pChild;\r
73             break;\r
74         }\r
75     }\r
76     if(eType == XFA_ELEMENT_Draw) {\r
77         XFA_ELEMENT eDraw = pUIChild ? pUIChild->GetClassID() : XFA_ELEMENT_UNKNOWN;\r
78         switch (eDraw) {\r
79             case XFA_ELEMENT_TextEdit:\r
80                 eWidgetType = XFA_ELEMENT_Text;\r
81                 break;\r
82             case XFA_ELEMENT_ImageEdit:\r
83                 eWidgetType = XFA_ELEMENT_Image;\r
84                 break;\r
85             default:\r
86                 eWidgetType = eWidgetType == XFA_ELEMENT_UNKNOWN ? XFA_ELEMENT_Text : eWidgetType;\r
87                 break;\r
88         }\r
89     } else {\r
90         if (pUIChild && pUIChild->GetClassID() == XFA_ELEMENT_DefaultUi) {\r
91             eWidgetType = XFA_ELEMENT_TextEdit;\r
92         } else {\r
93             eWidgetType = pUIChild ? pUIChild->GetClassID() : (eUIType == XFA_ELEMENT_UNKNOWN ? XFA_ELEMENT_TextEdit : eUIType);\r
94         }\r
95     }\r
96     if (!pUIChild) {\r
97         if (eUIType == XFA_ELEMENT_UNKNOWN) {\r
98             eUIType = XFA_ELEMENT_TextEdit;\r
99             ((CXFA_Node*)defValue)->GetProperty(0, XFA_ELEMENT_Text, TRUE);\r
100         }\r
101         pUIChild = pUI->GetProperty(0, eUIType, TRUE);\r
102     } else if (eUIType == XFA_ELEMENT_UNKNOWN) {\r
103         switch (pUIChild->GetClassID()) {\r
104             case XFA_ELEMENT_CheckButton: {\r
105                     eValueType = XFA_ELEMENT_Text;\r
106                     if (CXFA_Node* pItems = pNode->GetChild(0, XFA_ELEMENT_Items)) {\r
107                         if (CXFA_Node* pItem = pItems->GetChild(0, XFA_ELEMENT_UNKNOWN)) {\r
108                             eValueType = pItem->GetClassID();\r
109                         }\r
110                     }\r
111                 }\r
112                 break;\r
113             case XFA_ELEMENT_DateTimeEdit:\r
114                 eValueType = XFA_ELEMENT_DateTime;\r
115                 break;\r
116             case XFA_ELEMENT_ImageEdit:\r
117                 eValueType = XFA_ELEMENT_Image;\r
118                 break;\r
119             case XFA_ELEMENT_NumericEdit:\r
120                 eValueType = XFA_ELEMENT_Float;\r
121                 break;\r
122             case XFA_ELEMENT_ChoiceList: {\r
123                     eValueType = (pUIChild->GetEnum(XFA_ATTRIBUTE_Open) == XFA_ATTRIBUTEENUM_MultiSelect) ? XFA_ELEMENT_ExData : XFA_ELEMENT_Text;\r
124                 }\r
125                 break;\r
126             case XFA_ELEMENT_Barcode:\r
127             case XFA_ELEMENT_Button:\r
128             case XFA_ELEMENT_PasswordEdit:\r
129             case XFA_ELEMENT_Signature:\r
130             case XFA_ELEMENT_TextEdit:\r
131             default:\r
132                 eValueType = XFA_ELEMENT_Text;\r
133                 break;\r
134         }\r
135         ((CXFA_Node*)defValue)->GetProperty(0, eValueType, TRUE);\r
136     }\r
137     return pUIChild;\r
138 }\r
139 CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData)\r
140 {\r
141     CXFA_Node* pNodeValue = pWidgetData->GetNode()->GetChild(0, XFA_ELEMENT_Value);\r
142     if (!pNodeValue) {\r
143         return CXFA_LocaleValue();\r
144     }\r
145     CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild);\r
146     if (!pValueChild) {\r
147         return CXFA_LocaleValue();\r
148     }\r
149     int32_t iVTType = XFA_VT_NULL;\r
150     XFA_ELEMENT eType = pValueChild->GetClassID();\r
151     switch (eType) {\r
152         case XFA_ELEMENT_Decimal:\r
153             iVTType = XFA_VT_DECIMAL;\r
154             break;\r
155         case XFA_ELEMENT_Float:\r
156             iVTType = XFA_VT_FLOAT;\r
157             break;\r
158         case XFA_ELEMENT_Date:\r
159             iVTType = XFA_VT_DATE;\r
160             break;\r
161         case XFA_ELEMENT_Time:\r
162             iVTType = XFA_VT_TIME;\r
163             break;\r
164         case XFA_ELEMENT_DateTime:\r
165             iVTType = XFA_VT_DATETIME;\r
166             break;\r
167         case XFA_ELEMENT_Boolean:\r
168             iVTType = XFA_VT_BOOLEAN;\r
169             break;\r
170         case XFA_ELEMENT_Integer:\r
171             iVTType = XFA_VT_INTEGER;\r
172             break;\r
173         case XFA_ELEMENT_Text:\r
174             iVTType = XFA_VT_TEXT;\r
175             break;\r
176         default:\r
177             iVTType = XFA_VT_NULL;\r
178             break;\r
179     }\r
180     return CXFA_LocaleValue(iVTType, pWidgetData->GetRawValue(), pWidgetData->GetNode()->GetDocument()->GetLocalMgr());\r
181 }\r
182 void    XFA_GetPlainTextFromRichText(IFDE_XMLNode *pXMLNode, CFX_WideString &wsPlainText)\r
183 {\r
184     if (pXMLNode == NULL) {\r
185         return;\r
186     }\r
187     switch(pXMLNode->GetType()) {\r
188         case FDE_XMLNODE_Element: {\r
189                 IFDE_XMLElement *pXMLElement = (IFDE_XMLElement*)pXMLNode;\r
190                 CFX_WideString wsTag;\r
191                 pXMLElement->GetLocalTagName(wsTag);\r
192                 uint32_t uTag = FX_HashCode_String_GetW(wsTag, wsTag.GetLength(), TRUE);\r
193                 if (uTag == 0x0001f714) {\r
194                     wsPlainText += L"\n";\r
195                 } else if (uTag == 0x00000070) {\r
196                     if (!wsPlainText.IsEmpty()) {\r
197                         wsPlainText += L"\n";\r
198                     }\r
199                 } else if (uTag == 0xa48ac63) {\r
200                     if (!wsPlainText.IsEmpty() && wsPlainText[wsPlainText.GetLength() - 1] != '\n') {\r
201                         wsPlainText += L"\n";\r
202                     }\r
203                 }\r
204             }\r
205             break;\r
206         case FDE_XMLNODE_Text: {\r
207                 CFX_WideString wsContent;\r
208                 ((IFDE_XMLText*)pXMLNode)->GetText(wsContent);\r
209                 wsPlainText += wsContent;\r
210             }\r
211             break;\r
212         case FDE_XMLNODE_CharData: {\r
213                 CFX_WideString wsCharData;\r
214                 ((IFDE_XMLCharData*)pXMLNode)->GetCharData(wsCharData);\r
215                 wsPlainText += wsCharData;\r
216             }\r
217             break;\r
218         default:\r
219             break;\r
220     }\r
221     for (IFDE_XMLNode *pChildXML = pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); pChildXML; pChildXML = pChildXML->GetNodeItem(IFDE_XMLNode::NextSibling)) {\r
222         XFA_GetPlainTextFromRichText(pChildXML, wsPlainText);\r
223     }\r
224 }\r
225 FX_BOOL XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode)\r
226 {\r
227     FX_BOOL bRet = FALSE;\r
228     if (!pFieldNode) {\r
229         return bRet;\r
230     }\r
231     CXFA_Node *pUIChild = pFieldNode->GetChild(0, XFA_ELEMENT_Ui);\r
232     if (pUIChild) {\r
233         CXFA_Node *pFirstChild = pUIChild->GetNodeItem(XFA_NODEITEM_FirstChild);\r
234         if (pFirstChild && pFirstChild->GetClassID() == XFA_ELEMENT_ChoiceList) {\r
235             bRet = pFirstChild->GetEnum(XFA_ATTRIBUTE_Open) == XFA_ATTRIBUTEENUM_MultiSelect;\r
236         }\r
237     }\r
238     return bRet;\r
239 }\r
240 FX_BOOL XFA_IsLayoutElement(XFA_ELEMENT eElement, FX_BOOL bLayoutContainer )\r
241 {\r
242     switch (eElement) {\r
243         case XFA_ELEMENT_Draw:\r
244         case XFA_ELEMENT_Field:\r
245         case XFA_ELEMENT_InstanceManager:\r
246             return !bLayoutContainer;\r
247         case XFA_ELEMENT_Area:\r
248         case XFA_ELEMENT_Subform:\r
249         case XFA_ELEMENT_ExclGroup:\r
250         case XFA_ELEMENT_SubformSet:\r
251             return TRUE;\r
252         case XFA_ELEMENT_PageArea:\r
253         case XFA_ELEMENT_Form:\r
254             return TRUE;\r
255         default:\r
256             return FALSE;\r
257     }\r
258     return FALSE;\r
259 }\r
260 FX_BOOL XFA_IsTakingupSpace(XFA_ATTRIBUTEENUM ePresence)\r
261 {\r
262     switch (ePresence) {\r
263         case XFA_ATTRIBUTEENUM_Visible:\r
264         case XFA_ATTRIBUTEENUM_Invisible:\r
265             return TRUE;\r
266         default:\r
267             return FALSE;\r
268     }\r
269     return FALSE;\r
270 }\r
271 FX_BOOL XFA_IsFlowingLayout(XFA_ATTRIBUTEENUM eLayout)\r
272 {\r
273     switch (eLayout) {\r
274         case XFA_ATTRIBUTEENUM_Tb:\r
275         case XFA_ATTRIBUTEENUM_Lr_tb:\r
276         case XFA_ATTRIBUTEENUM_Rl_tb:\r
277             return TRUE;\r
278         default:\r
279             return FALSE;\r
280     }\r
281     return FALSE;\r
282 }\r
283 FX_BOOL XFA_IsHorizontalFlow(XFA_ATTRIBUTEENUM eLayout)\r
284 {\r
285     switch (eLayout) {\r
286         case XFA_ATTRIBUTEENUM_Lr_tb:\r
287         case XFA_ATTRIBUTEENUM_Rl_tb:\r
288             return TRUE;\r
289         default:\r
290             return FALSE;\r
291     }\r
292     return FALSE;\r
293 }\r
294 static const FX_DOUBLE fraction_scales[] = {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001,\r
295                                             0.0000001, 0.00000001, 0.000000001, 0.0000000001, 0.00000000001, 0.000000000001,\r
296                                             0.0000000000001, 0.00000000000001, 0.000000000000001, 0.0000000000000001\r
297                                            };\r
298 FX_DOUBLE XFA_WideStringToDouble(const CFX_WideString &wsStringVal)\r
299 {\r
300     CFX_WideString wsValue = wsStringVal;\r
301     wsValue.TrimLeft();\r
302     wsValue.TrimRight();\r
303     FX_BOOL bValid = TRUE;\r
304     int64_t nIntegral = 0;\r
305     FX_DWORD dwFractional = 0;\r
306     int32_t nExponent = 0;\r
307     int32_t cc = 0;\r
308     FX_BOOL bNegative = FALSE, bExpSign = FALSE;\r
309     FX_LPCWSTR str = (FX_LPCWSTR)wsValue;\r
310     int32_t len = wsValue.GetLength();\r
311     if (str[0] == '+') {\r
312         cc++;\r
313     } else if (str[0] == '-') {\r
314         bNegative = TRUE;\r
315         cc++;\r
316     }\r
317     int32_t nIntegralLen = 0;\r
318     while (cc < len) {\r
319         if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' || nIntegralLen > 17) {\r
320             break;\r
321         }\r
322         if (!XFA_IsDigit(str[cc])) {\r
323             return 0;\r
324         }\r
325         nIntegral = nIntegral * 10 + str[cc] - '0';\r
326         cc ++;\r
327         nIntegralLen++;\r
328     }\r
329     nIntegral = bNegative ? -nIntegral : nIntegral;\r
330     int32_t scale = 0;\r
331     FX_DOUBLE fraction = 0.0;\r
332     if (cc < len && str[cc] == '.') {\r
333         cc ++;\r
334         while (cc < len) {\r
335             fraction += fraction_scales[scale] * (str[cc] - '0');\r
336             scale ++;\r
337             cc ++;\r
338             if (cc == len) {\r
339                 break;\r
340             }\r
341             if (scale == sizeof (fraction_scales) / sizeof(FX_DOUBLE)\r
342                     || str[cc] == 'E'\r
343                     || str[cc] == 'e') {\r
344                 break;\r
345             }\r
346             if (!XFA_IsDigit(str[cc])) {\r
347                 return 0;\r
348             }\r
349         }\r
350         dwFractional = (FX_DWORD)(fraction * 4294967296.0);\r
351     }\r
352     if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {\r
353         cc ++;\r
354         if (cc < len) {\r
355             if (str[cc] == '+') {\r
356                 cc++;\r
357             } else if (str[cc] == '-') {\r
358                 bExpSign = TRUE;\r
359                 cc++;\r
360             }\r
361         }\r
362         while (cc < len) {\r
363             if (str[cc] == '.' || !XFA_IsDigit(str[cc])) {\r
364                 return 0;\r
365             }\r
366             nExponent = nExponent * 10 + str[cc] - '0';\r
367             cc ++;\r
368         }\r
369         nExponent = bExpSign ? -nExponent : nExponent;\r
370     }\r
371     FX_DOUBLE dValue = (dwFractional / 4294967296.0);\r
372     dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue);\r
373     if (nExponent != 0) {\r
374         dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent);\r
375     }\r
376     return dValue;\r
377 }\r
378 \r
379 FX_DOUBLE XFA_ByteStringToDouble(FX_BSTR szStringVal)\r
380 {\r
381     CFX_WideString wsValue = CFX_WideString::FromUTF8(szStringVal.GetCStr(), szStringVal.GetLength());\r
382     return XFA_WideStringToDouble(wsValue);\r
383 }\r
384 \r
385 int32_t XFA_MapRotation(int32_t nRotation) {\r
386     nRotation = nRotation % 360;\r
387     nRotation = nRotation < 0 ? nRotation + 360 : nRotation;\r
388     return nRotation;\r
389 }\r
390 \r