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