blob: fc708584d70b89e75aaf25abc8e8143f4f256fbc [file] [log] [blame]
// Copyright 2017 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 "fxjs/xfa/cjx_object.h"
#include <tuple>
#include "core/fxcrt/cfx_decimal.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/xml/cfx_xmltext.h"
#include "fxjs/cfxjse_engine.h"
#include "fxjs/cfxjse_value.h"
#include "fxjs/cjs_return.h"
#include "third_party/base/ptr_util.h"
#include "xfa/fxfa/cxfa_ffnotify.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/cxfa_object.h"
#include "xfa/fxfa/parser/cxfa_occurdata.h"
#include "xfa/fxfa/parser/xfa_utils.h"
namespace {
void XFA_DeleteWideString(void* pData) {
delete static_cast<WideString*>(pData);
}
void XFA_CopyWideString(void*& pData) {
if (!pData)
return;
pData = new WideString(*reinterpret_cast<WideString*>(pData));
}
XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString,
XFA_CopyWideString};
enum XFA_KEYTYPE {
XFA_KEYTYPE_Custom,
XFA_KEYTYPE_Element,
};
void* GetMapKey_Custom(const WideStringView& wsKey) {
uint32_t dwKey = FX_HashCode_GetW(wsKey, false);
return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom);
}
void* GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
return (void*)(uintptr_t)((static_cast<uint32_t>(eType) << 16) |
(static_cast<uint32_t>(eAttribute) << 8) |
XFA_KEYTYPE_Element);
}
void XFA_DefaultFreeData(void* pData) {}
XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = {XFA_DefaultFreeData,
nullptr};
std::tuple<int32_t, int32_t, int32_t> StrToRGB(const WideString& strRGB) {
int32_t r = 0;
int32_t g = 0;
int32_t b = 0;
size_t iIndex = 0;
for (size_t i = 0; i < strRGB.GetLength(); ++i) {
wchar_t ch = strRGB[i];
if (ch == L',')
++iIndex;
if (iIndex > 2)
break;
int32_t iValue = ch - L'0';
if (iValue >= 0 && iValue <= 9) {
switch (iIndex) {
case 0:
r = r * 10 + iValue;
break;
case 1:
g = g * 10 + iValue;
break;
default:
b = b * 10 + iValue;
break;
}
}
}
return {r, g, b};
}
} // namespace
struct XFA_MAPDATABLOCK {
uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); }
XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo;
int32_t iBytes;
};
struct XFA_MAPMODULEDATA {
XFA_MAPMODULEDATA() {}
~XFA_MAPMODULEDATA() {}
std::map<void*, void*> m_ValueMap;
std::map<void*, XFA_MAPDATABLOCK*> m_BufferMap;
};
CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}
CJX_Object::~CJX_Object() {
ClearMapModuleBuffer();
}
void CJX_Object::DefineMethods(const CJX_MethodSpec method_specs[],
size_t count) {
for (size_t i = 0; i < count; ++i)
method_specs_[method_specs[i].pName] = method_specs[i].pMethodCall;
}
CXFA_Document* CJX_Object::GetDocument() const {
return object_->GetDocument();
}
void CJX_Object::Script_ObjectClass_ClassName(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetString(
FX_UTF8Encode(GetXFAObject()->GetClassName()).AsStringView());
}
bool CJX_Object::HasMethod(const WideString& func) const {
return pdfium::ContainsKey(method_specs_, func.UTF8Encode());
}
CJS_Return CJX_Object::RunMethod(
const WideString& func,
const std::vector<v8::Local<v8::Value>>& params) {
auto it = method_specs_.find(func.UTF8Encode());
if (it == method_specs_.end())
return CJS_Return(false);
return it->second(this, GetXFAObject()->GetDocument()->GetScriptContext(),
params);
}
void CJX_Object::ThrowTooManyOccurancesException(const WideString& obj) const {
ThrowException(
L"The element [%ls] has violated its allowable number of occurrences.",
obj.c_str());
}
void CJX_Object::ThrowInvalidPropertyException() const {
ThrowException(L"Invalid property set operation.");
}
void CJX_Object::ThrowIndexOutOfBoundsException() const {
ThrowException(L"Index value is out of bounds.");
}
void CJX_Object::ThrowParamCountMismatchException(
const WideString& method) const {
ThrowException(L"Incorrect number of parameters calling method '%.16s'.",
method.c_str());
}
void CJX_Object::ThrowArgumentMismatchException() const {
ThrowException(L"Argument mismatch in property or function argument.");
}
void CJX_Object::ThrowException(const wchar_t* str, ...) const {
va_list arg_ptr;
va_start(arg_ptr, str);
WideString wsMessage = WideString::FormatV(str, arg_ptr);
va_end(arg_ptr);
ASSERT(!wsMessage.IsEmpty());
FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView());
}
bool CJX_Object::HasAttribute(XFA_Attribute eAttr) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
return HasMapModuleKey(pKey);
}
bool CJX_Object::SetAttribute(XFA_Attribute eAttr,
const WideStringView& wsValue,
bool bNotify) {
switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
case XFA_AttributeType::Enum: {
pdfium::Optional<XFA_AttributeEnum> item =
CXFA_Node::NameToAttributeEnum(wsValue);
return SetEnum(
eAttr,
item ? *item : *(ToNode(GetXFAObject())->GetDefaultEnum(eAttr)),
bNotify);
}
case XFA_AttributeType::CData:
return SetCData(eAttr, WideString(wsValue), bNotify, false);
case XFA_AttributeType::Boolean:
return SetBoolean(eAttr, wsValue != L"0", bNotify);
case XFA_AttributeType::Integer:
return SetInteger(eAttr,
FXSYS_round(FXSYS_wcstof(wsValue.unterminated_c_str(),
wsValue.GetLength(), nullptr)),
bNotify);
case XFA_AttributeType::Measure:
return SetMeasure(eAttr, CXFA_Measurement(wsValue), bNotify);
default:
break;
}
return false;
}
void CJX_Object::SetMapModuleString(void* pKey, const WideStringView& wsValue) {
SetMapModuleBuffer(pKey, (void*)wsValue.unterminated_c_str(),
wsValue.GetLength() * sizeof(wchar_t), nullptr);
}
bool CJX_Object::SetAttribute(const WideStringView& wsAttr,
const WideStringView& wsValue,
bool bNotify) {
XFA_Attribute attr = CXFA_Node::NameToAttribute(wsValue);
if (attr != XFA_Attribute::Unknown)
return SetAttribute(attr, wsValue, bNotify);
void* pKey = GetMapKey_Custom(wsAttr);
SetMapModuleString(pKey, wsValue);
return true;
}
WideString CJX_Object::GetAttribute(const WideStringView& attr) {
return TryAttribute(attr, true).value_or(WideString());
}
WideString CJX_Object::GetAttribute(XFA_Attribute attr) {
return TryAttribute(attr, true).value_or(WideString());
}
pdfium::Optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
bool bUseDefault) {
switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
case XFA_AttributeType::Enum: {
pdfium::Optional<XFA_AttributeEnum> value = TryEnum(eAttr, bUseDefault);
if (!value)
return {};
return {CXFA_Node::AttributeEnumToName(*value)};
}
case XFA_AttributeType::CData:
return TryCData(eAttr, bUseDefault);
case XFA_AttributeType::Boolean: {
pdfium::Optional<bool> value = TryBoolean(eAttr, bUseDefault);
if (!value)
return {};
return {*value ? L"1" : L"0"};
}
case XFA_AttributeType::Integer: {
pdfium::Optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
if (!iValue)
return {};
return {WideString::Format(L"%d", *iValue)};
}
case XFA_AttributeType::Measure: {
pdfium::Optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
if (!value)
return {};
return {value->ToString()};
}
default:
break;
}
return {};
}
pdfium::Optional<WideString> CJX_Object::TryAttribute(
const WideStringView& wsAttr,
bool bUseDefault) {
XFA_Attribute attr = CXFA_Node::NameToAttribute(wsAttr);
if (attr != XFA_Attribute::Unknown)
return TryAttribute(attr, bUseDefault);
void* pKey = GetMapKey_Custom(wsAttr);
WideStringView wsValueC;
if (!GetMapModuleString(pKey, wsValueC))
return {};
return {WideString(wsValueC)};
}
void CJX_Object::RemoveAttribute(const WideStringView& wsAttr) {
void* pKey = GetMapKey_Custom(wsAttr);
if (pKey)
RemoveMapModuleKey(pKey);
}
pdfium::Optional<bool> CJX_Object::TryBoolean(XFA_Attribute eAttr,
bool bUseDefault) {
void* pValue = nullptr;
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
if (GetMapModuleValue(pKey, pValue))
return {!!pValue};
if (!bUseDefault)
return {};
return ToNode(GetXFAObject())->GetDefaultBoolean(eAttr);
}
bool CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Boolean,
(void*)(uintptr_t)bValue, bNotify);
if (elem)
elem->SetString(CXFA_Node::AttributeToName(eAttr), bValue ? L"1" : L"0");
return true;
}
bool CJX_Object::GetBoolean(XFA_Attribute eAttr) {
return TryBoolean(eAttr, true).value_or(false);
}
bool CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Integer,
(void*)(uintptr_t)iValue, bNotify);
if (elem) {
elem->SetString(CXFA_Node::AttributeToName(eAttr),
WideString::Format(L"%d", iValue));
}
return true;
}
int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) {
return TryInteger(eAttr, true).value_or(0);
}
pdfium::Optional<int32_t> CJX_Object::TryInteger(XFA_Attribute eAttr,
bool bUseDefault) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
void* pValue = nullptr;
if (GetMapModuleValue(pKey, pValue))
return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(pValue))};
if (!bUseDefault)
return {};
return ToNode(GetXFAObject())->GetDefaultInteger(eAttr);
}
pdfium::Optional<XFA_AttributeEnum> CJX_Object::TryEnum(XFA_Attribute eAttr,
bool bUseDefault) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
void* pValue = nullptr;
if (GetMapModuleValue(pKey, pValue)) {
return {
static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(pValue))};
}
if (!bUseDefault)
return {};
return ToNode(GetXFAObject())->GetDefaultEnum(eAttr);
}
bool CJX_Object::SetEnum(XFA_Attribute eAttr,
XFA_AttributeEnum eValue,
bool bNotify) {
CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Enum,
(void*)(uintptr_t)eValue, bNotify);
if (elem) {
elem->SetString(CXFA_Node::AttributeToName(eAttr),
CXFA_Node::AttributeEnumToName(eValue));
}
return true;
}
XFA_AttributeEnum CJX_Object::GetEnum(XFA_Attribute eAttr) {
return TryEnum(eAttr, true).value_or(XFA_AttributeEnum::Unknown);
}
bool CJX_Object::SetMeasure(XFA_Attribute eAttr,
CXFA_Measurement mValue,
bool bNotify) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
OnChanging(eAttr, bNotify);
SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement), nullptr);
OnChanged(eAttr, bNotify, false);
return true;
}
pdfium::Optional<CXFA_Measurement> CJX_Object::TryMeasure(
XFA_Attribute eAttr,
bool bUseDefault) const {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
void* pValue;
int32_t iBytes;
if (GetMapModuleBuffer(pKey, pValue, iBytes, true) &&
iBytes == sizeof(CXFA_Measurement)) {
return {*reinterpret_cast<CXFA_Measurement*>(pValue)};
}
if (!bUseDefault)
return {};
return ToNode(GetXFAObject())->GetDefaultMeasurement(eAttr);
}
CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const {
return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
}
WideString CJX_Object::GetCData(XFA_Attribute eAttr) {
return TryCData(eAttr, true).value_or(WideString());
}
bool CJX_Object::SetCData(XFA_Attribute eAttr,
const WideString& wsValue,
bool bNotify,
bool bScriptModify) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
OnChanging(eAttr, bNotify);
if (eAttr == XFA_Attribute::Value) {
WideString* pClone = new WideString(wsValue);
SetUserData(pKey, pClone, &deleteWideStringCallBack);
} else {
SetMapModuleString(pKey, wsValue.AsStringView());
if (eAttr == XFA_Attribute::Name)
ToNode(GetXFAObject())->UpdateNameHash();
}
OnChanged(eAttr, bNotify, bScriptModify);
if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode() ||
eAttr == XFA_Attribute::QualifiedName ||
eAttr == XFA_Attribute::BindingNode) {
return true;
}
if (eAttr == XFA_Attribute::Name &&
(GetXFAObject()->GetElementType() == XFA_Element::DataValue ||
GetXFAObject()->GetElementType() == XFA_Element::DataGroup)) {
return true;
}
auto* elem =
static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
if (eAttr == XFA_Attribute::Value) {
FX_XMLNODETYPE eXMLType = elem->GetType();
switch (eXMLType) {
case FX_XMLNODE_Element:
if (ToNode(GetXFAObject())->IsAttributeInXML()) {
elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
wsValue);
} else {
bool bDeleteChildren = true;
if (ToNode(GetXFAObject())->GetPacketType() ==
XFA_PacketType::Datasets) {
for (CXFA_Node* pChildDataNode =
ToNode(GetXFAObject())
->GetNodeItem(XFA_NODEITEM_FirstChild);
pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
XFA_NODEITEM_NextSibling)) {
if (!pChildDataNode->GetBindItems()->empty()) {
bDeleteChildren = false;
break;
}
}
}
if (bDeleteChildren)
elem->DeleteChildren();
elem->SetTextData(wsValue);
}
break;
case FX_XMLNODE_Text:
static_cast<CFX_XMLText*>(ToNode(GetXFAObject())->GetXMLMappingNode())
->SetText(wsValue);
break;
default:
NOTREACHED();
}
return true;
}
ASSERT(elem->GetType() == FX_XMLNODE_Element);
WideString wsAttrName = CXFA_Node::AttributeToName(eAttr);
if (eAttr == XFA_Attribute::ContentType)
wsAttrName = L"xfa:" + wsAttrName;
elem->SetString(wsAttrName, wsValue);
return true;
}
void CJX_Object::SetAttributeValue(const WideString& wsValue,
const WideString& wsXMLValue,
bool bNotify,
bool bScriptModify) {
void* pKey =
GetMapKey_Element(GetXFAObject()->GetElementType(), XFA_Attribute::Value);
OnChanging(XFA_Attribute::Value, bNotify);
WideString* pClone = new WideString(wsValue);
SetUserData(pKey, pClone, &deleteWideStringCallBack);
OnChanged(XFA_Attribute::Value, bNotify, bScriptModify);
if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode())
return;
auto* elem =
static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
FX_XMLNODETYPE eXMLType = elem->GetType();
switch (eXMLType) {
case FX_XMLNODE_Element:
if (ToNode(GetXFAObject())->IsAttributeInXML()) {
elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
wsXMLValue);
} else {
bool bDeleteChildren = true;
if (ToNode(GetXFAObject())->GetPacketType() ==
XFA_PacketType::Datasets) {
for (CXFA_Node* pChildDataNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_FirstChild);
pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
XFA_NODEITEM_NextSibling)) {
if (!pChildDataNode->GetBindItems()->empty()) {
bDeleteChildren = false;
break;
}
}
}
if (bDeleteChildren)
elem->DeleteChildren();
elem->SetTextData(wsXMLValue);
}
break;
case FX_XMLNODE_Text:
static_cast<CFX_XMLText*>(ToNode(GetXFAObject())->GetXMLMappingNode())
->SetText(wsXMLValue);
break;
default:
ASSERT(0);
}
}
pdfium::Optional<WideString> CJX_Object::TryCData(XFA_Attribute eAttr,
bool bUseDefault) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
if (eAttr == XFA_Attribute::Value) {
void* pData;
int32_t iBytes = 0;
WideString* pStr = nullptr;
if (GetMapModuleBuffer(pKey, pData, iBytes, true) &&
iBytes == sizeof(void*)) {
memcpy(&pData, pData, iBytes);
pStr = reinterpret_cast<WideString*>(pData);
}
if (pStr)
return {*pStr};
} else {
WideStringView wsValueC;
if (GetMapModuleString(pKey, wsValueC))
return {WideString(wsValueC)};
}
if (!bUseDefault)
return {};
return ToNode(GetXFAObject())->GetDefaultCData(eAttr);
}
CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr,
XFA_AttributeType eType,
void* pValue,
bool bNotify) {
void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
OnChanging(eAttr, bNotify);
SetMapModuleValue(pKey, pValue);
OnChanged(eAttr, bNotify, false);
if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode())
return nullptr;
auto* elem =
static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
ASSERT(elem->GetType() == FX_XMLNODE_Element);
return elem;
}
bool CJX_Object::SetContent(const WideString& wsContent,
const WideString& wsXMLValue,
bool bNotify,
bool bScriptModify,
bool bSyncData) {
CXFA_Node* pNode = nullptr;
CXFA_Node* pBindNode = nullptr;
switch (ToNode(GetXFAObject())->GetObjectType()) {
case XFA_ObjectType::ContainerNode: {
if (XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) {
CXFA_Node* pValue = GetProperty(0, XFA_Element::Value, true);
if (!pValue)
break;
CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild);
ASSERT(pChildValue);
pChildValue->JSObject()->SetCData(XFA_Attribute::ContentType,
L"text/xml", false, false);
pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
bScriptModify, false);
CXFA_Node* pBind = ToNode(GetXFAObject())->GetBindData();
if (bSyncData && pBind) {
std::vector<WideString> wsSaveTextArray;
size_t iSize = 0;
if (!wsContent.IsEmpty()) {
size_t iStart = 0;
size_t iLength = wsContent.GetLength();
auto iEnd = wsContent.Find(L'\n', iStart);
iEnd = !iEnd.has_value() ? iLength : iEnd;
while (iEnd.value() >= iStart) {
wsSaveTextArray.push_back(
wsContent.Mid(iStart, iEnd.value() - iStart));
iStart = iEnd.value() + 1;
if (iStart >= iLength)
break;
iEnd = wsContent.Find(L'\n', iStart);
if (!iEnd.has_value()) {
wsSaveTextArray.push_back(
wsContent.Mid(iStart, iLength - iStart));
}
}
iSize = wsSaveTextArray.size();
}
if (iSize == 0) {
while (CXFA_Node* pChildNode =
pBind->GetNodeItem(XFA_NODEITEM_FirstChild)) {
pBind->RemoveChild(pChildNode, true);
}
} else {
std::vector<CXFA_Node*> valueNodes = pBind->GetNodeList(
XFA_NODEFILTER_Children, XFA_Element::DataValue);
size_t iDatas = valueNodes.size();
if (iDatas < iSize) {
size_t iAddNodes = iSize - iDatas;
CXFA_Node* pValueNodes = nullptr;
while (iAddNodes-- > 0) {
pValueNodes =
pBind->CreateSamePacketNode(XFA_Element::DataValue);
pValueNodes->JSObject()->SetCData(XFA_Attribute::Name, L"value",
false, false);
pValueNodes->CreateXMLMappingNode();
pBind->InsertChild(pValueNodes, nullptr);
}
pValueNodes = nullptr;
} else if (iDatas > iSize) {
size_t iDelNodes = iDatas - iSize;
while (iDelNodes-- > 0) {
pBind->RemoveChild(pBind->GetNodeItem(XFA_NODEITEM_FirstChild),
true);
}
}
int32_t i = 0;
for (CXFA_Node* pValueNode =
pBind->GetNodeItem(XFA_NODEITEM_FirstChild);
pValueNode; pValueNode = pValueNode->GetNodeItem(
XFA_NODEITEM_NextSibling)) {
pValueNode->JSObject()->SetAttributeValue(
wsSaveTextArray[i], wsSaveTextArray[i], false, false);
i++;
}
}
for (const auto& pArrayNode : *(pBind->GetBindItems())) {
if (pArrayNode.Get() != ToNode(GetXFAObject())) {
pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
bScriptModify, false);
}
}
}
break;
}
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) {
pNode = ToNode(GetXFAObject());
} else {
CXFA_Node* pValue = GetProperty(0, XFA_Element::Value, true);
if (!pValue)
break;
CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild);
ASSERT(pChildValue);
pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
bScriptModify, false);
}
pBindNode = ToNode(GetXFAObject())->GetBindData();
if (pBindNode && bSyncData) {
pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
bScriptModify, false);
for (const auto& pArrayNode : *(pBindNode->GetBindItems())) {
if (pArrayNode.Get() != ToNode(GetXFAObject())) {
pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
true, false);
}
}
}
pBindNode = nullptr;
break;
}
case XFA_ObjectType::ContentNode: {
WideString wsContentType;
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) {
pdfium::Optional<WideString> ret =
TryAttribute(XFA_Attribute::ContentType, false);
if (ret)
wsContentType = *ret;
if (wsContentType == L"text/html") {
wsContentType = L"";
SetAttribute(XFA_Attribute::ContentType, wsContentType.AsStringView(),
false);
}
}
CXFA_Node* pContentRawDataNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_FirstChild);
if (!pContentRawDataNode) {
pContentRawDataNode =
ToNode(GetXFAObject())
->CreateSamePacketNode((wsContentType == L"text/xml")
? XFA_Element::Sharpxml
: XFA_Element::Sharptext);
ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr);
}
return pContentRawDataNode->JSObject()->SetContent(
wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData);
}
case XFA_ObjectType::NodeC:
case XFA_ObjectType::TextNode:
pNode = ToNode(GetXFAObject());
break;
case XFA_ObjectType::NodeV:
pNode = ToNode(GetXFAObject());
if (bSyncData &&
ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Form) {
CXFA_Node* pParent =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_Parent);
if (pParent) {
pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent);
}
if (pParent && pParent->GetElementType() == XFA_Element::Value) {
pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent);
if (pParent && pParent->IsContainerNode()) {
pBindNode = pParent->GetBindData();
if (pBindNode) {
pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
bScriptModify, false);
}
}
}
}
break;
default:
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue) {
pNode = ToNode(GetXFAObject());
pBindNode = ToNode(GetXFAObject());
}
break;
}
if (!pNode)
return false;
SetAttributeValue(wsContent, wsXMLValue, bNotify, bScriptModify);
if (pBindNode && bSyncData) {
for (const auto& pArrayNode : *(pBindNode->GetBindItems())) {
pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
bScriptModify, false);
}
}
return true;
}
WideString CJX_Object::GetContent(bool bScriptModify) {
return TryContent(bScriptModify, true).value_or(WideString());
}
pdfium::Optional<WideString> CJX_Object::TryContent(bool bScriptModify,
bool bProto) {
CXFA_Node* pNode = nullptr;
switch (ToNode(GetXFAObject())->GetObjectType()) {
case XFA_ObjectType::ContainerNode:
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExclGroup) {
pNode = ToNode(GetXFAObject());
} else {
CXFA_Node* pValue =
ToNode(GetXFAObject())->GetChild(0, XFA_Element::Value, false);
if (!pValue)
return {};
CXFA_Node* pChildValue = pValue->GetNodeItem(XFA_NODEITEM_FirstChild);
if (pChildValue && XFA_FieldIsMultiListBox(ToNode(GetXFAObject()))) {
pChildValue->JSObject()->SetAttribute(XFA_Attribute::ContentType,
L"text/xml", false);
}
if (pChildValue)
return pChildValue->JSObject()->TryContent(bScriptModify, bProto);
return {};
}
break;
case XFA_ObjectType::ContentNode: {
CXFA_Node* pContentRawDataNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_FirstChild);
if (!pContentRawDataNode) {
XFA_Element element = XFA_Element::Sharptext;
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::ExData) {
pdfium::Optional<WideString> contentType =
TryAttribute(XFA_Attribute::ContentType, false);
if (contentType) {
if (*contentType == L"text/html")
element = XFA_Element::SharpxHTML;
else if (*contentType == L"text/xml")
element = XFA_Element::Sharpxml;
}
}
pContentRawDataNode =
ToNode(GetXFAObject())->CreateSamePacketNode(element);
ToNode(GetXFAObject())->InsertChild(pContentRawDataNode, nullptr);
}
return pContentRawDataNode->JSObject()->TryContent(bScriptModify, true);
}
case XFA_ObjectType::NodeC:
case XFA_ObjectType::NodeV:
case XFA_ObjectType::TextNode:
pNode = ToNode(GetXFAObject());
default:
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue)
pNode = ToNode(GetXFAObject());
break;
}
if (pNode) {
if (bScriptModify) {
CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
if (pScriptContext)
GetDocument()->GetScriptContext()->AddNodesOfRunScript(
ToNode(GetXFAObject()));
}
return TryCData(XFA_Attribute::Value, false);
}
return {};
}
CXFA_Node* CJX_Object::GetProperty(int32_t index,
XFA_Element eProperty,
bool bCreateProperty) {
if (index < 0 ||
index >= ToNode(GetXFAObject())->PropertyOccuranceCount(eProperty)) {
return nullptr;
}
int32_t iCount = 0;
for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetChildNode(); pNode;
pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
if (pNode->GetElementType() == eProperty) {
iCount++;
if (iCount > index)
return pNode;
}
}
if (!bCreateProperty)
return nullptr;
if (ToNode(GetXFAObject())
->HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) {
for (CXFA_Node* pNode = ToNode(GetXFAObject())->GetChildNode(); pNode;
pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
if (ToNode(GetXFAObject())
->HasPropertyFlags(pNode->GetElementType(),
XFA_PROPERTYFLAG_OneOf)) {
return nullptr;
}
}
}
CXFA_Node* pNewNode = nullptr;
for (; iCount <= index; ++iCount) {
pNewNode = GetDocument()->CreateNode(
ToNode(GetXFAObject())->GetPacketType(), eProperty);
if (!pNewNode)
return nullptr;
ToNode(GetXFAObject())->InsertChild(pNewNode, nullptr);
pNewNode->SetFlag(XFA_NodeFlag_Initialized, true);
}
return pNewNode;
}
bool CJX_Object::SetUserData(void* pKey,
void* pData,
XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
SetMapModuleBuffer(pKey, &pData, sizeof(void*),
pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData);
return true;
}
XFA_MAPMODULEDATA* CJX_Object::CreateMapModuleData() {
if (!map_module_data_)
map_module_data_ = pdfium::MakeUnique<XFA_MAPMODULEDATA>();
return map_module_data_.get();
}
XFA_MAPMODULEDATA* CJX_Object::GetMapModuleData() const {
return map_module_data_.get();
}
void CJX_Object::SetMapModuleValue(void* pKey, void* pValue) {
CreateMapModuleData()->m_ValueMap[pKey] = pValue;
}
bool CJX_Object::GetMapModuleValue(void* pKey, void*& pValue) {
for (CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
pNode = pNode->GetTemplateNode()) {
XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData();
if (pModule) {
auto it = pModule->m_ValueMap.find(pKey);
if (it != pModule->m_ValueMap.end()) {
pValue = it->second;
return true;
}
}
if (pNode->GetPacketType() == XFA_PacketType::Datasets)
break;
}
return false;
}
bool CJX_Object::GetMapModuleString(void* pKey, WideStringView& wsValue) {
void* pValue;
int32_t iBytes;
if (!GetMapModuleBuffer(pKey, pValue, iBytes, true))
return false;
// Defensive measure: no out-of-bounds pointers even if zero length.
int32_t iChars = iBytes / sizeof(wchar_t);
wsValue = WideStringView(iChars ? (const wchar_t*)pValue : nullptr, iChars);
return true;
}
void CJX_Object::SetMapModuleBuffer(
void* pKey,
void* pValue,
int32_t iBytes,
XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
XFA_MAPDATABLOCK*& pBuffer = CreateMapModuleData()->m_BufferMap[pKey];
if (!pBuffer) {
pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes));
} else if (pBuffer->iBytes != iBytes) {
if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
FX_Realloc(uint8_t, pBuffer, sizeof(XFA_MAPDATABLOCK) + iBytes));
} else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) {
pBuffer->pCallbackInfo->pFree(
*reinterpret_cast<void**>(pBuffer->GetData()));
}
if (!pBuffer)
return;
pBuffer->pCallbackInfo = pCallbackInfo;
pBuffer->iBytes = iBytes;
memcpy(pBuffer->GetData(), pValue, iBytes);
}
bool CJX_Object::GetMapModuleBuffer(void* pKey,
void*& pValue,
int32_t& iBytes,
bool bProtoAlso) const {
XFA_MAPDATABLOCK* pBuffer = nullptr;
for (const CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
pNode = pNode->GetTemplateNode()) {
XFA_MAPMODULEDATA* pModule = pNode->JSObject()->GetMapModuleData();
if (pModule) {
auto it = pModule->m_BufferMap.find(pKey);
if (it != pModule->m_BufferMap.end()) {
pBuffer = it->second;
break;
}
}
if (!bProtoAlso || pNode->GetPacketType() == XFA_PacketType::Datasets)
break;
}
if (!pBuffer)
return false;
pValue = pBuffer->GetData();
iBytes = pBuffer->iBytes;
return true;
}
bool CJX_Object::HasMapModuleKey(void* pKey) {
XFA_MAPMODULEDATA* pModule = GetMapModuleData();
return pModule && (pdfium::ContainsKey(pModule->m_ValueMap, pKey) ||
pdfium::ContainsKey(pModule->m_BufferMap, pKey));
}
void CJX_Object::ClearMapModuleBuffer() {
XFA_MAPMODULEDATA* pModule = GetMapModuleData();
if (!pModule)
return;
for (auto& pair : pModule->m_BufferMap) {
XFA_MAPDATABLOCK* pBuffer = pair.second;
if (pBuffer) {
if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
FX_Free(pBuffer);
}
}
pModule->m_BufferMap.clear();
pModule->m_ValueMap.clear();
}
void CJX_Object::RemoveMapModuleKey(void* pKey) {
ASSERT(pKey);
XFA_MAPMODULEDATA* pModule = GetMapModuleData();
if (!pModule)
return;
auto it = pModule->m_BufferMap.find(pKey);
if (it != pModule->m_BufferMap.end()) {
XFA_MAPDATABLOCK* pBuffer = it->second;
if (pBuffer) {
if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
FX_Free(pBuffer);
}
pModule->m_BufferMap.erase(it);
}
pModule->m_ValueMap.erase(pKey);
return;
}
void CJX_Object::MergeAllData(CXFA_Object* pDstModule) {
XFA_MAPMODULEDATA* pDstModuleData =
ToNode(pDstModule)->JSObject()->CreateMapModuleData();
XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData();
if (!pSrcModuleData)
return;
for (const auto& pair : pSrcModuleData->m_ValueMap)
pDstModuleData->m_ValueMap[pair.first] = pair.second;
for (const auto& pair : pSrcModuleData->m_BufferMap) {
XFA_MAPDATABLOCK* pSrcBuffer = pair.second;
XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first];
if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree &&
!pSrcBuffer->pCallbackInfo->pCopy) {
if (pDstBuffer) {
pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
pDstModuleData->m_BufferMap.erase(pair.first);
}
continue;
}
if (!pDstBuffer) {
pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc(
uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
} else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) {
if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
}
pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc(
uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
} else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
}
if (!pDstBuffer)
continue;
pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo;
pDstBuffer->iBytes = pSrcBuffer->iBytes;
memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes);
if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) {
pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData());
}
}
}
void CJX_Object::MoveBufferMapData(CXFA_Object* pDstModule) {
if (!pDstModule)
return;
bool bNeedMove = true;
if (pDstModule->GetElementType() != GetXFAObject()->GetElementType())
bNeedMove = false;
if (bNeedMove)
ToNode(pDstModule)->JSObject()->SetCalcData(ReleaseCalcData());
if (!pDstModule->IsNodeV())
return;
WideString wsValue = ToNode(pDstModule)->JSObject()->GetContent(false);
WideString wsFormatValue(wsValue);
CXFA_WidgetData* pWidgetData = ToNode(pDstModule)->GetContainerWidgetData();
if (pWidgetData)
wsFormatValue = pWidgetData->GetFormatDataValue(wsValue);
ToNode(pDstModule)
->JSObject()
->SetContent(wsValue, wsFormatValue, true, true, true);
}
void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcModule,
CXFA_Object* pDstModule) {
if (!pSrcModule || !pDstModule)
return;
CXFA_Node* pSrcChild =
ToNode(pSrcModule)->GetNodeItem(XFA_NODEITEM_FirstChild);
CXFA_Node* pDstChild =
ToNode(pDstModule)->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pSrcChild && pDstChild) {
MoveBufferMapData(pSrcChild, pDstChild);
pSrcChild = pSrcChild->GetNodeItem(XFA_NODEITEM_NextSibling);
pDstChild = pDstChild->GetNodeItem(XFA_NODEITEM_NextSibling);
}
ToNode(pSrcModule)->JSObject()->MoveBufferMapData(pDstModule);
}
void CJX_Object::OnChanging(XFA_Attribute eAttr, bool bNotify) {
if (!bNotify || !ToNode(GetXFAObject())->IsInitialized())
return;
CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
if (pNotify)
pNotify->OnValueChanging(ToNode(GetXFAObject()), eAttr);
}
void CJX_Object::OnChanged(XFA_Attribute eAttr,
bool bNotify,
bool bScriptModify) {
if (bNotify && ToNode(GetXFAObject())->IsInitialized())
ToNode(GetXFAObject())->SendAttributeChangeMessage(eAttr, bScriptModify);
}
void CJX_Object::SetCalcData(std::unique_ptr<CXFA_CalcData> data) {
calc_data_ = std::move(data);
}
std::unique_ptr<CXFA_CalcData> CJX_Object::ReleaseCalcData() {
return std::move(calc_data_);
}
void CJX_Object::Script_Attribute_String(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!bSetting) {
pValue->SetString(GetAttribute(eAttribute).UTF8Encode().AsStringView());
return;
}
WideString wsValue = pValue->ToWideString();
SetAttribute(eAttribute, wsValue.AsStringView(), true);
if (eAttribute != XFA_Attribute::Use ||
GetXFAObject()->GetElementType() != XFA_Element::Desc) {
return;
}
CXFA_Node* pTemplateNode =
ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Template));
CXFA_Node* pProtoRoot =
pTemplateNode->GetFirstChildByClass(XFA_Element::Subform)
->GetFirstChildByClass(XFA_Element::Proto);
WideString wsID;
WideString wsSOM;
if (!wsValue.IsEmpty()) {
if (wsValue[0] == '#')
wsID = WideString(wsValue.c_str() + 1, wsValue.GetLength() - 1);
else
wsSOM = wsValue;
}
CXFA_Node* pProtoNode = nullptr;
if (!wsSOM.IsEmpty()) {
XFA_RESOLVENODE_RS resolveNodeRS;
bool iRet = GetDocument()->GetScriptContext()->ResolveObjects(
pProtoRoot, wsSOM.AsStringView(), &resolveNodeRS,
XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
XFA_RESOLVENODE_Siblings,
nullptr);
if (iRet && resolveNodeRS.objects.front()->IsNode())
pProtoNode = resolveNodeRS.objects.front()->AsNode();
} else if (!wsID.IsEmpty()) {
pProtoNode = GetDocument()->GetNodeByID(pProtoRoot, wsID.AsStringView());
}
if (!pProtoNode)
return;
CXFA_Node* pHeadChild =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pHeadChild) {
CXFA_Node* pSibling = pHeadChild->GetNodeItem(XFA_NODEITEM_NextSibling);
ToNode(GetXFAObject())->RemoveChild(pHeadChild, true);
pHeadChild = pSibling;
}
std::unique_ptr<CXFA_Node> pProtoForm(pProtoNode->CloneTemplateToForm(true));
pHeadChild = pProtoForm->GetNodeItem(XFA_NODEITEM_FirstChild);
while (pHeadChild) {
CXFA_Node* pSibling = pHeadChild->GetNodeItem(XFA_NODEITEM_NextSibling);
pProtoForm->RemoveChild(pHeadChild, true);
ToNode(GetXFAObject())->InsertChild(pHeadChild, nullptr);
pHeadChild = pSibling;
}
GetDocument()->RemovePurgeNode(pProtoForm.get());
}
void CJX_Object::Script_Attribute_BOOL(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
SetBoolean(eAttribute, pValue->ToBoolean(), true);
return;
}
pValue->SetString(GetBoolean(eAttribute) ? "1" : "0");
}
void CJX_Object::Script_Attribute_Integer(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
SetInteger(eAttribute, pValue->ToInteger(), true);
return;
}
pValue->SetInteger(GetInteger(eAttribute));
}
void CJX_Object::Script_Som_FontColor(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
CXFA_FontData fontData = widget_data_->GetFontData(true);
CXFA_Node* pNode = fontData.GetNode();
if (!pNode)
return;
if (bSetting) {
int32_t r;
int32_t g;
int32_t b;
std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
FX_ARGB color = ArgbEncode(0xff, r, g, b);
fontData.SetColor(color);
return;
}
int32_t a;
int32_t r;
int32_t g;
int32_t b;
std::tie(a, r, g, b) = ArgbDecode(fontData.GetColor());
pValue->SetString(ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
}
void CJX_Object::Script_Som_FillColor(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
CXFA_BorderData borderData = widget_data_->GetBorderData(true);
CXFA_FillData borderfillData = borderData.GetFillData(true);
CXFA_Node* pNode = borderfillData.GetNode();
if (!pNode)
return;
if (bSetting) {
int32_t r;
int32_t g;
int32_t b;
std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
FX_ARGB color = ArgbEncode(0xff, r, g, b);
borderfillData.SetColor(color);
return;
}
FX_ARGB color = borderfillData.GetColor(false);
int32_t a;
int32_t r;
int32_t g;
int32_t b;
std::tie(a, r, g, b) = ArgbDecode(color);
pValue->SetString(
WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView());
}
void CJX_Object::Script_Som_BorderColor(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
CXFA_BorderData borderData = widget_data_->GetBorderData(true);
int32_t iSize = borderData.CountEdges();
if (bSetting) {
int32_t r = 0;
int32_t g = 0;
int32_t b = 0;
std::tie(r, g, b) = StrToRGB(pValue->ToWideString());
FX_ARGB rgb = ArgbEncode(100, r, g, b);
for (int32_t i = 0; i < iSize; ++i)
borderData.GetEdgeData(i).SetColor(rgb);
return;
}
FX_ARGB color = borderData.GetEdgeData(0).GetColor();
int32_t a;
int32_t r;
int32_t g;
int32_t b;
std::tie(a, r, g, b) = ArgbDecode(color);
pValue->SetString(
WideString::Format(L"%d,%d,%d", r, g, b).UTF8Encode().AsStringView());
}
void CJX_Object::Script_Som_BorderWidth(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
CXFA_BorderData borderData = widget_data_->GetBorderData(true);
if (bSetting) {
CXFA_Measurement thickness = borderData.GetEdgeData(0).GetMSThickness();
pValue->SetString(thickness.ToString().UTF8Encode().AsStringView());
return;
}
WideString wsThickness = pValue->ToWideString();
for (int32_t i = 0; i < borderData.CountEdges(); ++i) {
borderData.GetEdgeData(i).SetMSThickness(
CXFA_Measurement(wsThickness.AsStringView()));
}
}
void CJX_Object::Script_Som_Message(CFXJSE_Value* pValue,
bool bSetting,
XFA_SOM_MESSAGETYPE iMessageType) {
if (!widget_data_)
return;
bool bNew = false;
CXFA_ValidateData validateData = widget_data_->GetValidateData(false);
if (!validateData.HasValidNode()) {
validateData = widget_data_->GetValidateData(true);
bNew = true;
}
if (bSetting) {
switch (iMessageType) {
case XFA_SOM_ValidationMessage:
validateData.SetScriptMessageText(pValue->ToWideString());
break;
case XFA_SOM_FormatMessage:
validateData.SetFormatMessageText(pValue->ToWideString());
break;
case XFA_SOM_MandatoryMessage:
validateData.SetNullMessageText(pValue->ToWideString());
break;
default:
break;
}
if (!bNew) {
CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
if (!pNotify) {
return;
}
pNotify->AddCalcValidate(ToNode(GetXFAObject()));
}
return;
}
WideString wsMessage;
switch (iMessageType) {
case XFA_SOM_ValidationMessage:
wsMessage = validateData.GetScriptMessageText();
break;
case XFA_SOM_FormatMessage:
wsMessage = validateData.GetFormatMessageText();
break;
case XFA_SOM_MandatoryMessage:
wsMessage = validateData.GetNullMessageText();
break;
default:
break;
}
pValue->SetString(wsMessage.UTF8Encode().AsStringView());
}
void CJX_Object::Script_Som_ValidationMessage(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
Script_Som_Message(pValue, bSetting, XFA_SOM_ValidationMessage);
}
void CJX_Object::Script_Field_FormatMessage(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
Script_Som_Message(pValue, bSetting, XFA_SOM_FormatMessage);
}
void CJX_Object::Script_Som_MandatoryMessage(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
Script_Som_Message(pValue, bSetting, XFA_SOM_MandatoryMessage);
}
void CJX_Object::Script_Som_DefaultValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute /* unused */) {
XFA_Element eType = ToNode(GetXFAObject())->GetElementType();
if (eType == XFA_Element::Field) {
Script_Field_DefaultValue(pValue, bSetting, XFA_Attribute::Unknown);
return;
}
if (eType == XFA_Element::Draw) {
Script_Draw_DefaultValue(pValue, bSetting, XFA_Attribute::Unknown);
return;
}
if (eType == XFA_Element::Boolean) {
Script_Boolean_DefaultValue(pValue, bSetting, XFA_Attribute::Unknown);
return;
}
if (bSetting) {
WideString wsNewValue;
if (pValue && !(pValue->IsNull() || pValue->IsUndefined()))
wsNewValue = pValue->ToWideString();
WideString wsFormatValue(wsNewValue);
CXFA_WidgetData* pContainerWidgetData = nullptr;
if (ToNode(GetXFAObject())->GetPacketType() == XFA_PacketType::Datasets) {
WideString wsPicture;
for (const auto& pFormNode : *(ToNode(GetXFAObject())->GetBindItems())) {
if (!pFormNode || pFormNode->HasRemovedChildren())
continue;
pContainerWidgetData = pFormNode->GetContainerWidgetData();
if (pContainerWidgetData) {
wsPicture = pContainerWidgetData->GetPictureContent(
XFA_VALUEPICTURE_DataBind);
}
if (!wsPicture.IsEmpty())
break;
pContainerWidgetData = nullptr;
}
} else if (ToNode(GetXFAObject())->GetPacketType() ==
XFA_PacketType::Form) {
pContainerWidgetData = ToNode(GetXFAObject())->GetContainerWidgetData();
}
if (pContainerWidgetData)
wsFormatValue = pContainerWidgetData->GetFormatDataValue(wsNewValue);
SetContent(wsNewValue, wsFormatValue, true, true, true);
return;
}
WideString content = GetContent(true);
if (content.IsEmpty() && eType != XFA_Element::Text &&
eType != XFA_Element::SubmitUrl) {
pValue->SetNull();
} else if (eType == XFA_Element::Integer) {
pValue->SetInteger(FXSYS_wtoi(content.c_str()));
} else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) {
CFX_Decimal decimal(content.AsStringView());
pValue->SetFloat((float)(double)decimal);
} else {
pValue->SetString(content.UTF8Encode().AsStringView());
}
}
void CJX_Object::Script_Som_DefaultValue_Read(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
WideString content = GetContent(true);
if (content.IsEmpty()) {
pValue->SetNull();
return;
}
pValue->SetString(content.UTF8Encode().AsStringView());
}
void CJX_Object::Script_Som_DataNode(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
CXFA_Node* pDataNode = ToNode(GetXFAObject())->GetBindData();
if (!pDataNode) {
pValue->SetNull();
return;
}
pValue->Assign(
GetDocument()->GetScriptContext()->GetJSValueFromMap(pDataNode));
}
void CJX_Object::Script_Som_Mandatory(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
CXFA_ValidateData validateData = widget_data_->GetValidateData(true);
if (bSetting) {
validateData.SetNullTest(pValue->ToWideString());
return;
}
WideString str = CXFA_Node::AttributeEnumToName(validateData.GetNullTest());
pValue->SetString(str.UTF8Encode().AsStringView());
}
void CJX_Object::Script_Som_InstanceIndex(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!bSetting) {
pValue->SetInteger(Subform_and_SubformSet_InstanceIndex());
return;
}
int32_t iTo = pValue->ToInteger();
int32_t iFrom = Subform_and_SubformSet_InstanceIndex();
CXFA_Node* pManagerNode = nullptr;
for (CXFA_Node* pNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_PrevSibling);
pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) {
if (pNode->GetElementType() == XFA_Element::InstanceManager) {
pManagerNode = pNode;
break;
}
}
if (!pManagerNode)
return;
pManagerNode->JSObject()->InstanceManager_MoveInstance(iTo, iFrom);
CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
if (!pNotify)
return;
CXFA_Node* pToInstance = pManagerNode->GetItem(iTo);
if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) {
pNotify->RunSubformIndexChange(pToInstance);
}
CXFA_Node* pFromInstance = pManagerNode->GetItem(iFrom);
if (pFromInstance &&
pFromInstance->GetElementType() == XFA_Element::Subform) {
pNotify->RunSubformIndexChange(pFromInstance);
}
}
void CJX_Object::Script_Field_DefaultValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
if (bSetting) {
if (pValue) {
widget_data_->SetPreNull(widget_data_->IsNull());
widget_data_->SetIsNull(pValue->IsNull());
}
WideString wsNewText;
if (pValue && !(pValue->IsNull() || pValue->IsUndefined()))
wsNewText = pValue->ToWideString();
CXFA_Node* pUIChild = widget_data_->GetUIChild();
if (pUIChild->GetElementType() == XFA_Element::NumericEdit) {
wsNewText =
widget_data_->NumericLimit(wsNewText, widget_data_->GetLeadDigits(),
widget_data_->GetFracDigits());
}
CXFA_WidgetData* pContainerWidgetData =
ToNode(GetXFAObject())->GetContainerWidgetData();
WideString wsFormatText(wsNewText);
if (pContainerWidgetData)
wsFormatText = pContainerWidgetData->GetFormatDataValue(wsNewText);
SetContent(wsNewText, wsFormatText, true, true, true);
return;
}
WideString content = GetContent(true);
if (content.IsEmpty()) {
pValue->SetNull();
return;
}
CXFA_Node* pUIChild = widget_data_->GetUIChild();
CXFA_Node* pNode = widget_data_->GetFormValueData().GetNode()->GetNodeItem(
XFA_NODEITEM_FirstChild);
if (pNode && pNode->GetElementType() == XFA_Element::Decimal) {
if (pUIChild->GetElementType() == XFA_Element::NumericEdit &&
(pNode->JSObject()->GetInteger(XFA_Attribute::FracDigits) == -1)) {
pValue->SetString(content.UTF8Encode().AsStringView());
} else {
CFX_Decimal decimal(content.AsStringView());
pValue->SetFloat((float)(double)decimal);
}
} else if (pNode && pNode->GetElementType() == XFA_Element::Integer) {
pValue->SetInteger(FXSYS_wtoi(content.c_str()));
} else if (pNode && pNode->GetElementType() == XFA_Element::Boolean) {
pValue->SetBoolean(FXSYS_wtoi(content.c_str()) == 0 ? false : true);
} else if (pNode && pNode->GetElementType() == XFA_Element::Float) {
CFX_Decimal decimal(content.AsStringView());
pValue->SetFloat((float)(double)decimal);
} else {
pValue->SetString(content.UTF8Encode().AsStringView());
}
}
void CJX_Object::Script_Boolean_DefaultValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!bSetting) {
WideString wsValue = GetContent(true);
pValue->SetBoolean(wsValue == L"1");
return;
}
ByteString newValue;
if (pValue && !(pValue->IsNull() || pValue->IsUndefined()))
newValue = pValue->ToString();
int32_t iValue = FXSYS_atoi(newValue.c_str());
WideString wsNewValue(iValue == 0 ? L"0" : L"1");
WideString wsFormatValue(wsNewValue);
CXFA_WidgetData* pContainerWidgetData =
ToNode(GetXFAObject())->GetContainerWidgetData();
if (pContainerWidgetData)
wsFormatValue = pContainerWidgetData->GetFormatDataValue(wsNewValue);
SetContent(wsNewValue, wsFormatValue, true, true, true);
}
void CJX_Object::Script_Draw_DefaultValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!bSetting) {
WideString content = GetContent(true);
if (content.IsEmpty())
pValue->SetNull();
else
pValue->SetString(content.UTF8Encode().AsStringView());
return;
}
if (!pValue || !pValue->IsString())
return;
if (widget_data_->GetUIType() != XFA_Element::Text)
return;
WideString wsNewValue = pValue->ToWideString();
SetContent(wsNewValue, wsNewValue, true, true, true);
}
int32_t CJX_Object::Subform_and_SubformSet_InstanceIndex() {
int32_t index = 0;
for (CXFA_Node* pNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_PrevSibling);
pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) {
if ((pNode->GetElementType() != XFA_Element::Subform) &&
(pNode->GetElementType() != XFA_Element::SubformSet)) {
break;
}
index++;
}
return index;
}
void CJX_Object::Script_NodeClass_Ns(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetString(
TryNamespace().value_or(WideString()).UTF8Encode().AsStringView());
}
void CJX_Object::Script_NodeClass_Model(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
ToNode(GetXFAObject())->GetModelNode()));
}
void CJX_Object::Script_NodeClass_IsContainer(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetBoolean(GetXFAObject()->IsContainerNode());
}
void CJX_Object::Script_NodeClass_IsNull(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::Subform) {
pValue->SetBoolean(false);
return;
}
pValue->SetBoolean(GetContent(false).IsEmpty());
}
void CJX_Object::Script_NodeClass_OneOfChild(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
std::vector<CXFA_Node*> properties =
ToNode(GetXFAObject())
->GetNodeList(XFA_NODEFILTER_OneOfProperty, XFA_Element::Unknown);
if (!properties.empty()) {
pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
properties.front()));
}
}
void CJX_Object::Script_ModelClass_Context(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_ModelClass_AliasNode(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Delta_CurrentValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Delta_SavedValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Delta_Target(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Field_Length(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
if (!widget_data_) {
pValue->SetInteger(0);
return;
}
pValue->SetInteger(widget_data_->CountChoiceListItems(true));
}
void CJX_Object::Script_Field_EditValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
if (bSetting) {
widget_data_->SetValue(XFA_VALUEPICTURE_Edit, pValue->ToWideString());
return;
}
pValue->SetString(widget_data_->GetValue(XFA_VALUEPICTURE_Edit)
.UTF8Encode()
.AsStringView());
}
void CJX_Object::Script_Field_FormattedValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
if (bSetting) {
widget_data_->SetValue(XFA_VALUEPICTURE_Display, pValue->ToWideString());
return;
}
pValue->SetString(widget_data_->GetValue(XFA_VALUEPICTURE_Display)
.UTF8Encode()
.AsStringView());
}
void CJX_Object::Script_Field_ParentSubform(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetNull();
}
void CJX_Object::Script_Field_SelectedIndex(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
if (!bSetting) {
pValue->SetInteger(widget_data_->GetSelectedItem(0));
return;
}
int32_t iIndex = pValue->ToInteger();
if (iIndex == -1) {
widget_data_->ClearAllSelections();
return;
}
widget_data_->SetItemState(iIndex, true, true, true, true);
}
void CJX_Object::Script_ExclGroup_ErrorText(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting)
ThrowInvalidPropertyException();
}
void CJX_Object::Script_ExclGroup_DefaultAndRawValue(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (!widget_data_)
return;
if (bSetting) {
widget_data_->SetSelectedMemberByValue(
pValue->ToWideString().AsStringView(), true, true, true);
return;
}
WideString wsValue = GetContent(true);
XFA_VERSION curVersion = GetDocument()->GetCurVersionMode();
if (wsValue.IsEmpty() && curVersion >= XFA_VERSION_300) {
pValue->SetNull();
return;
}
pValue->SetString(wsValue.UTF8Encode().AsStringView());
}
void CJX_Object::Script_ExclGroup_Transient(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Subform_InstanceManager(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
WideString wsName = GetCData(XFA_Attribute::Name);
CXFA_Node* pInstanceMgr = nullptr;
for (CXFA_Node* pNode =
ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_PrevSibling);
pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_PrevSibling)) {
if (pNode->GetElementType() == XFA_Element::InstanceManager) {
WideString wsInstMgrName =
pNode->JSObject()->GetCData(XFA_Attribute::Name);
if (wsInstMgrName.GetLength() >= 1 && wsInstMgrName[0] == '_' &&
wsInstMgrName.Right(wsInstMgrName.GetLength() - 1) == wsName) {
pInstanceMgr = pNode;
}
break;
}
}
if (!pInstanceMgr) {
pValue->SetNull();
return;
}
pValue->Assign(
GetDocument()->GetScriptContext()->GetJSValueFromMap(pInstanceMgr));
}
void CJX_Object::Script_Subform_Locale(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
SetCData(XFA_Attribute::Locale, pValue->ToWideString(), true, true);
return;
}
WideString wsLocaleName;
ToNode(GetXFAObject())->GetLocaleName(wsLocaleName);
pValue->SetString(wsLocaleName.UTF8Encode().AsStringView());
}
void CJX_Object::Script_InstanceManager_Max(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetInteger(
CXFA_OccurData(ToNode(GetXFAObject())->GetOccurNode()).GetMax());
}
void CJX_Object::Script_InstanceManager_Min(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetInteger(
CXFA_OccurData(ToNode(GetXFAObject())->GetOccurNode()).GetMin());
}
void CJX_Object::Script_InstanceManager_Count(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
pValue->SetInteger(ToNode(GetXFAObject())->GetCount());
return;
}
InstanceManager_SetInstances(pValue->ToInteger());
}
void CJX_Object::Script_Occur_Max(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
CXFA_OccurData occurData(ToNode(GetXFAObject()));
if (!bSetting) {
pValue->SetInteger(occurData.GetMax());
return;
}
occurData.SetMax(pValue->ToInteger());
}
void CJX_Object::Script_Occur_Min(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
CXFA_OccurData occurData(ToNode(GetXFAObject()));
if (!bSetting) {
pValue->SetInteger(occurData.GetMin());
return;
}
occurData.SetMin(pValue->ToInteger());
}
void CJX_Object::Script_Form_Checksum(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
SetAttribute(XFA_Attribute::Checksum, pValue->ToWideString().AsStringView(),
false);
return;
}
pdfium::Optional<WideString> checksum =
TryAttribute(XFA_Attribute::Checksum, false);
pValue->SetString(checksum ? checksum->UTF8Encode().AsStringView() : "");
}
void CJX_Object::Script_Packet_Content(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode();
if (bSetting) {
if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
pXMLElement->SetTextData(pValue->ToWideString());
}
return;
}
WideString wsTextData;
if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
wsTextData = pXMLElement->GetTextData();
}
pValue->SetString(wsTextData.UTF8Encode().AsStringView());
}
void CJX_Object::Script_Source_Db(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Xfa_This(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting)
return;
CXFA_Object* pThis = GetDocument()->GetScriptContext()->GetThisObject();
ASSERT(pThis);
pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pThis));
}
void CJX_Object::Script_Handler_Version(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_SubmitFormat_Mode(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Extras_Type(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
void CJX_Object::Script_Script_Stateless(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {
if (bSetting) {
ThrowInvalidPropertyException();
return;
}
pValue->SetString(FX_UTF8Encode(WideStringView(L"0", 1)).AsStringView());
}
void CJX_Object::Script_Encrypt_Format(CFXJSE_Value* pValue,
bool bSetting,
XFA_Attribute eAttribute) {}
pdfium::Optional<WideString> CJX_Object::TryNamespace() {
if (ToNode(GetXFAObject())->IsModelNode() ||
ToNode(GetXFAObject())->GetElementType() == XFA_Element::Packet) {
CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode();
if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
return {};
return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
}
if (ToNode(GetXFAObject())->GetPacketType() != XFA_PacketType::Datasets)
return ToNode(GetXFAObject())->GetModelNode()->JSObject()->TryNamespace();
CFX_XMLNode* pXMLNode = ToNode(GetXFAObject())->GetXMLMappingNode();
if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
return {};
if (ToNode(GetXFAObject())->GetElementType() == XFA_Element::DataValue &&
GetEnum(XFA_Attribute::Contains) == XFA_AttributeEnum::MetaData) {
WideString wsNamespace;
bool ret = XFA_FDEExtension_ResolveNamespaceQualifier(
static_cast<CFX_XMLElement*>(pXMLNode),
GetCData(XFA_Attribute::QualifiedName), &wsNamespace);
if (!ret)
return {};
return {wsNamespace};
}
return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
}
int32_t CJX_Object::InstanceManager_SetInstances(int32_t iDesired) {
CXFA_OccurData occurData(ToNode(GetXFAObject())->GetOccurNode());
if (iDesired < occurData.GetMin()) {
ThrowTooManyOccurancesException(L"min");
return 1;
}
int32_t iMax = occurData.GetMax();
if (iMax >= 0 && iDesired > iMax) {
ThrowTooManyOccurancesException(L"max");
return 2;
}
int32_t iCount = ToNode(GetXFAObject())->GetCount();
if (iDesired == iCount)
return 0;
if (iDesired < iCount) {
WideString wsInstManagerName = GetCData(XFA_Attribute::Name);
WideString wsInstanceName = WideString(
wsInstManagerName.IsEmpty()
? wsInstManagerName
: wsInstManagerName.Right(wsInstManagerName.GetLength() - 1));
uint32_t dInstanceNameHash =
FX_HashCode_GetW(wsInstanceName.AsStringView(), false);
CXFA_Node* pPrevSibling =
iDesired == 0 ? ToNode(GetXFAObject())
: ToNode(GetXFAObject())->GetItem(iDesired - 1);
while (iCount > iDesired) {
CXFA_Node* pRemoveInstance =
pPrevSibling->GetNodeItem(XFA_NODEITEM_NextSibling);
if (pRemoveInstance->GetElementType() != XFA_Element::Subform &&
pRemoveInstance->GetElementType() != XFA_Element::SubformSet) {
continue;
}
if (pRemoveInstance->GetElementType() == XFA_Element::InstanceManager) {
NOTREACHED();
break;
}
if (pRemoveInstance->GetNameHash() == dInstanceNameHash) {
ToNode(GetXFAObject())->RemoveItem(pRemoveInstance, true);
iCount--;
}
}
} else {
while (iCount < iDesired) {
CXFA_Node* pNewInstance = ToNode(GetXFAObject())->CreateInstance(true);
ToNode(GetXFAObject())->InsertItem(pNewInstance, iCount, iCount, false);
iCount++;
CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
if (!pNotify)
return 0;
pNotify->RunNodeInitialize(pNewInstance);
}
}
CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
if (pLayoutPro) {
pLayoutPro->AddChangedContainer(
ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
}
return 0;
}
int32_t CJX_Object::InstanceManager_MoveInstance(int32_t iTo, int32_t iFrom) {
int32_t iCount = ToNode(GetXFAObject())->GetCount();
if (iFrom > iCount || iTo > iCount - 1) {
ThrowIndexOutOfBoundsException();
return 1;
}
if (iFrom < 0 || iTo < 0 || iFrom == iTo)
return 0;
CXFA_Node* pMoveInstance = ToNode(GetXFAObject())->GetItem(iFrom);
ToNode(GetXFAObject())->RemoveItem(pMoveInstance, false);
ToNode(GetXFAObject())->InsertItem(pMoveInstance, iTo, iCount - 1, true);
CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
if (pLayoutPro) {
pLayoutPro->AddChangedContainer(
ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
}
return 0;
}