// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "xfa/src/foxitlib.h" | |
#include "xfa/src/fxfa/src/common/xfa_utils.h" | |
#include "xfa/src/fxfa/src/common/xfa_object.h" | |
#include "xfa/src/fxfa/src/common/xfa_document.h" | |
#include "xfa/src/fxfa/src/common/xfa_parser.h" | |
#include "xfa/src/fxfa/src/common/xfa_script.h" | |
#include "xfa/src/fxfa/src/common/xfa_docdata.h" | |
#include "xfa/src/fxfa/src/common/xfa_doclayout.h" | |
#include "xfa/src/fxfa/src/common/xfa_localemgr.h" | |
#include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h" | |
CXFA_Node* XFA_CreateUIChild(CXFA_Node* pNode, XFA_ELEMENT& eWidgetType) { | |
XFA_ELEMENT eType = pNode->GetClassID(); | |
eWidgetType = eType; | |
if (eType != XFA_ELEMENT_Field && eType != XFA_ELEMENT_Draw) { | |
return NULL; | |
} | |
eWidgetType = XFA_ELEMENT_UNKNOWN; | |
XFA_ELEMENT eUIType = XFA_ELEMENT_UNKNOWN; | |
CXFA_Value defValue = pNode->GetProperty(0, XFA_ELEMENT_Value, TRUE); | |
XFA_ELEMENT eValueType = (XFA_ELEMENT)defValue.GetChildValueClassID(); | |
switch (eValueType) { | |
case XFA_ELEMENT_Boolean: | |
eUIType = XFA_ELEMENT_CheckButton; | |
break; | |
case XFA_ELEMENT_Integer: | |
case XFA_ELEMENT_Decimal: | |
case XFA_ELEMENT_Float: | |
eUIType = XFA_ELEMENT_NumericEdit; | |
break; | |
case XFA_ELEMENT_ExData: | |
case XFA_ELEMENT_Text: | |
eUIType = XFA_ELEMENT_TextEdit; | |
eWidgetType = XFA_ELEMENT_Text; | |
break; | |
case XFA_ELEMENT_Date: | |
case XFA_ELEMENT_Time: | |
case XFA_ELEMENT_DateTime: | |
eUIType = XFA_ELEMENT_DateTimeEdit; | |
break; | |
case XFA_ELEMENT_Image: | |
eUIType = XFA_ELEMENT_ImageEdit; | |
eWidgetType = XFA_ELEMENT_Image; | |
break; | |
; | |
case XFA_ELEMENT_Arc: | |
case XFA_ELEMENT_Line: | |
case XFA_ELEMENT_Rectangle: | |
eUIType = XFA_ELEMENT_DefaultUi; | |
eWidgetType = eValueType; | |
break; | |
default: | |
break; | |
} | |
CXFA_Node* pUIChild = NULL; | |
CXFA_Node* pUI = pNode->GetProperty(0, XFA_ELEMENT_Ui, TRUE); | |
CXFA_Node* pChild = pUI->GetNodeItem(XFA_NODEITEM_FirstChild); | |
for (; pChild; pChild = pChild->GetNodeItem(XFA_NODEITEM_NextSibling)) { | |
XFA_ELEMENT eChild = pChild->GetClassID(); | |
if (eChild == XFA_ELEMENT_Extras || eChild == XFA_ELEMENT_Picture) { | |
continue; | |
} | |
XFA_LPCPROPERTY pProterty = | |
XFA_GetPropertyOfElement(XFA_ELEMENT_Ui, eChild, XFA_XDPPACKET_Form); | |
if (pProterty && (pProterty->uFlags & XFA_PROPERTYFLAG_OneOf)) { | |
pUIChild = pChild; | |
break; | |
} | |
} | |
if (eType == XFA_ELEMENT_Draw) { | |
XFA_ELEMENT eDraw = pUIChild ? pUIChild->GetClassID() : XFA_ELEMENT_UNKNOWN; | |
switch (eDraw) { | |
case XFA_ELEMENT_TextEdit: | |
eWidgetType = XFA_ELEMENT_Text; | |
break; | |
case XFA_ELEMENT_ImageEdit: | |
eWidgetType = XFA_ELEMENT_Image; | |
break; | |
default: | |
eWidgetType = | |
eWidgetType == XFA_ELEMENT_UNKNOWN ? XFA_ELEMENT_Text : eWidgetType; | |
break; | |
} | |
} else { | |
if (pUIChild && pUIChild->GetClassID() == XFA_ELEMENT_DefaultUi) { | |
eWidgetType = XFA_ELEMENT_TextEdit; | |
} else { | |
eWidgetType = pUIChild | |
? pUIChild->GetClassID() | |
: (eUIType == XFA_ELEMENT_UNKNOWN ? XFA_ELEMENT_TextEdit | |
: eUIType); | |
} | |
} | |
if (!pUIChild) { | |
if (eUIType == XFA_ELEMENT_UNKNOWN) { | |
eUIType = XFA_ELEMENT_TextEdit; | |
((CXFA_Node*)defValue)->GetProperty(0, XFA_ELEMENT_Text, TRUE); | |
} | |
pUIChild = pUI->GetProperty(0, eUIType, TRUE); | |
} else if (eUIType == XFA_ELEMENT_UNKNOWN) { | |
switch (pUIChild->GetClassID()) { | |
case XFA_ELEMENT_CheckButton: { | |
eValueType = XFA_ELEMENT_Text; | |
if (CXFA_Node* pItems = pNode->GetChild(0, XFA_ELEMENT_Items)) { | |
if (CXFA_Node* pItem = pItems->GetChild(0, XFA_ELEMENT_UNKNOWN)) { | |
eValueType = pItem->GetClassID(); | |
} | |
} | |
} break; | |
case XFA_ELEMENT_DateTimeEdit: | |
eValueType = XFA_ELEMENT_DateTime; | |
break; | |
case XFA_ELEMENT_ImageEdit: | |
eValueType = XFA_ELEMENT_Image; | |
break; | |
case XFA_ELEMENT_NumericEdit: | |
eValueType = XFA_ELEMENT_Float; | |
break; | |
case XFA_ELEMENT_ChoiceList: { | |
eValueType = (pUIChild->GetEnum(XFA_ATTRIBUTE_Open) == | |
XFA_ATTRIBUTEENUM_MultiSelect) | |
? XFA_ELEMENT_ExData | |
: XFA_ELEMENT_Text; | |
} break; | |
case XFA_ELEMENT_Barcode: | |
case XFA_ELEMENT_Button: | |
case XFA_ELEMENT_PasswordEdit: | |
case XFA_ELEMENT_Signature: | |
case XFA_ELEMENT_TextEdit: | |
default: | |
eValueType = XFA_ELEMENT_Text; | |
break; | |
} | |
((CXFA_Node*)defValue)->GetProperty(0, eValueType, TRUE); | |
} | |
return pUIChild; | |
} | |
CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData) { | |
CXFA_Node* pNodeValue = | |
pWidgetData->GetNode()->GetChild(0, XFA_ELEMENT_Value); | |
if (!pNodeValue) { | |
return CXFA_LocaleValue(); | |
} | |
CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild); | |
if (!pValueChild) { | |
return CXFA_LocaleValue(); | |
} | |
int32_t iVTType = XFA_VT_NULL; | |
XFA_ELEMENT eType = pValueChild->GetClassID(); | |
switch (eType) { | |
case XFA_ELEMENT_Decimal: | |
iVTType = XFA_VT_DECIMAL; | |
break; | |
case XFA_ELEMENT_Float: | |
iVTType = XFA_VT_FLOAT; | |
break; | |
case XFA_ELEMENT_Date: | |
iVTType = XFA_VT_DATE; | |
break; | |
case XFA_ELEMENT_Time: | |
iVTType = XFA_VT_TIME; | |
break; | |
case XFA_ELEMENT_DateTime: | |
iVTType = XFA_VT_DATETIME; | |
break; | |
case XFA_ELEMENT_Boolean: | |
iVTType = XFA_VT_BOOLEAN; | |
break; | |
case XFA_ELEMENT_Integer: | |
iVTType = XFA_VT_INTEGER; | |
break; | |
case XFA_ELEMENT_Text: | |
iVTType = XFA_VT_TEXT; | |
break; | |
default: | |
iVTType = XFA_VT_NULL; | |
break; | |
} | |
return CXFA_LocaleValue(iVTType, pWidgetData->GetRawValue(), | |
pWidgetData->GetNode()->GetDocument()->GetLocalMgr()); | |
} | |
void XFA_GetPlainTextFromRichText(IFDE_XMLNode* pXMLNode, | |
CFX_WideString& wsPlainText) { | |
if (pXMLNode == NULL) { | |
return; | |
} | |
switch (pXMLNode->GetType()) { | |
case FDE_XMLNODE_Element: { | |
IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode; | |
CFX_WideString wsTag; | |
pXMLElement->GetLocalTagName(wsTag); | |
uint32_t uTag = FX_HashCode_String_GetW(wsTag, wsTag.GetLength(), TRUE); | |
if (uTag == 0x0001f714) { | |
wsPlainText += L"\n"; | |
} else if (uTag == 0x00000070) { | |
if (!wsPlainText.IsEmpty()) { | |
wsPlainText += L"\n"; | |
} | |
} else if (uTag == 0xa48ac63) { | |
if (!wsPlainText.IsEmpty() && | |
wsPlainText[wsPlainText.GetLength() - 1] != '\n') { | |
wsPlainText += L"\n"; | |
} | |
} | |
} break; | |
case FDE_XMLNODE_Text: { | |
CFX_WideString wsContent; | |
((IFDE_XMLText*)pXMLNode)->GetText(wsContent); | |
wsPlainText += wsContent; | |
} break; | |
case FDE_XMLNODE_CharData: { | |
CFX_WideString wsCharData; | |
((IFDE_XMLCharData*)pXMLNode)->GetCharData(wsCharData); | |
wsPlainText += wsCharData; | |
} break; | |
default: | |
break; | |
} | |
for (IFDE_XMLNode* pChildXML = | |
pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); | |
pChildXML; | |
pChildXML = pChildXML->GetNodeItem(IFDE_XMLNode::NextSibling)) { | |
XFA_GetPlainTextFromRichText(pChildXML, wsPlainText); | |
} | |
} | |
FX_BOOL XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode) { | |
FX_BOOL bRet = FALSE; | |
if (!pFieldNode) { | |
return bRet; | |
} | |
CXFA_Node* pUIChild = pFieldNode->GetChild(0, XFA_ELEMENT_Ui); | |
if (pUIChild) { | |
CXFA_Node* pFirstChild = pUIChild->GetNodeItem(XFA_NODEITEM_FirstChild); | |
if (pFirstChild && pFirstChild->GetClassID() == XFA_ELEMENT_ChoiceList) { | |
bRet = pFirstChild->GetEnum(XFA_ATTRIBUTE_Open) == | |
XFA_ATTRIBUTEENUM_MultiSelect; | |
} | |
} | |
return bRet; | |
} | |
FX_BOOL XFA_IsLayoutElement(XFA_ELEMENT eElement, FX_BOOL bLayoutContainer) { | |
switch (eElement) { | |
case XFA_ELEMENT_Draw: | |
case XFA_ELEMENT_Field: | |
case XFA_ELEMENT_InstanceManager: | |
return !bLayoutContainer; | |
case XFA_ELEMENT_Area: | |
case XFA_ELEMENT_Subform: | |
case XFA_ELEMENT_ExclGroup: | |
case XFA_ELEMENT_SubformSet: | |
return TRUE; | |
case XFA_ELEMENT_PageArea: | |
case XFA_ELEMENT_Form: | |
return TRUE; | |
default: | |
return FALSE; | |
} | |
return FALSE; | |
} | |
FX_BOOL XFA_IsTakingupSpace(XFA_ATTRIBUTEENUM ePresence) { | |
switch (ePresence) { | |
case XFA_ATTRIBUTEENUM_Visible: | |
case XFA_ATTRIBUTEENUM_Invisible: | |
return TRUE; | |
default: | |
return FALSE; | |
} | |
return FALSE; | |
} | |
FX_BOOL XFA_IsFlowingLayout(XFA_ATTRIBUTEENUM eLayout) { | |
switch (eLayout) { | |
case XFA_ATTRIBUTEENUM_Tb: | |
case XFA_ATTRIBUTEENUM_Lr_tb: | |
case XFA_ATTRIBUTEENUM_Rl_tb: | |
return TRUE; | |
default: | |
return FALSE; | |
} | |
return FALSE; | |
} | |
FX_BOOL XFA_IsHorizontalFlow(XFA_ATTRIBUTEENUM eLayout) { | |
switch (eLayout) { | |
case XFA_ATTRIBUTEENUM_Lr_tb: | |
case XFA_ATTRIBUTEENUM_Rl_tb: | |
return TRUE; | |
default: | |
return FALSE; | |
} | |
return FALSE; | |
} | |
static const FX_DOUBLE fraction_scales[] = {0.1, | |
0.01, | |
0.001, | |
0.0001, | |
0.00001, | |
0.000001, | |
0.0000001, | |
0.00000001, | |
0.000000001, | |
0.0000000001, | |
0.00000000001, | |
0.000000000001, | |
0.0000000000001, | |
0.00000000000001, | |
0.000000000000001, | |
0.0000000000000001}; | |
FX_DOUBLE XFA_WideStringToDouble(const CFX_WideString& wsStringVal) { | |
CFX_WideString wsValue = wsStringVal; | |
wsValue.TrimLeft(); | |
wsValue.TrimRight(); | |
int64_t nIntegral = 0; | |
FX_DWORD dwFractional = 0; | |
int32_t nExponent = 0; | |
int32_t cc = 0; | |
FX_BOOL bNegative = FALSE, bExpSign = FALSE; | |
const FX_WCHAR* str = (const FX_WCHAR*)wsValue; | |
int32_t len = wsValue.GetLength(); | |
if (str[0] == '+') { | |
cc++; | |
} else if (str[0] == '-') { | |
bNegative = TRUE; | |
cc++; | |
} | |
int32_t nIntegralLen = 0; | |
while (cc < len) { | |
if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' || | |
nIntegralLen > 17) { | |
break; | |
} | |
if (!XFA_IsDigit(str[cc])) { | |
return 0; | |
} | |
nIntegral = nIntegral * 10 + str[cc] - '0'; | |
cc++; | |
nIntegralLen++; | |
} | |
nIntegral = bNegative ? -nIntegral : nIntegral; | |
int32_t scale = 0; | |
FX_DOUBLE fraction = 0.0; | |
if (cc < len && str[cc] == '.') { | |
cc++; | |
while (cc < len) { | |
fraction += fraction_scales[scale] * (str[cc] - '0'); | |
scale++; | |
cc++; | |
if (cc == len) { | |
break; | |
} | |
if (scale == sizeof(fraction_scales) / sizeof(FX_DOUBLE) || | |
str[cc] == 'E' || str[cc] == 'e') { | |
break; | |
} | |
if (!XFA_IsDigit(str[cc])) { | |
return 0; | |
} | |
} | |
dwFractional = (FX_DWORD)(fraction * 4294967296.0); | |
} | |
if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { | |
cc++; | |
if (cc < len) { | |
if (str[cc] == '+') { | |
cc++; | |
} else if (str[cc] == '-') { | |
bExpSign = TRUE; | |
cc++; | |
} | |
} | |
while (cc < len) { | |
if (str[cc] == '.' || !XFA_IsDigit(str[cc])) { | |
return 0; | |
} | |
nExponent = nExponent * 10 + str[cc] - '0'; | |
cc++; | |
} | |
nExponent = bExpSign ? -nExponent : nExponent; | |
} | |
FX_DOUBLE dValue = (dwFractional / 4294967296.0); | |
dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); | |
if (nExponent != 0) { | |
dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); | |
} | |
return dValue; | |
} | |
FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal) { | |
CFX_WideString wsValue = | |
CFX_WideString::FromUTF8(szStringVal.GetCStr(), szStringVal.GetLength()); | |
return XFA_WideStringToDouble(wsValue); | |
} | |
int32_t XFA_MapRotation(int32_t nRotation) { | |
nRotation = nRotation % 360; | |
nRotation = nRotation < 0 ? nRotation + 360 : nRotation; | |
return nRotation; | |
} |