1 // Copyright 2017 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 "fxjs/xfa/cjx_field.h" 8 9 #include <vector> 10 11 #include "core/fxcrt/cfx_decimal.h" 12 #include "fxjs/cfxjse_value.h" 13 #include "fxjs/js_resources.h" 14 #include "xfa/fxfa/cxfa_eventparam.h" 15 #include "xfa/fxfa/cxfa_ffnotify.h" 16 #include "xfa/fxfa/fxfa.h" 17 #include "xfa/fxfa/parser/cxfa_document.h" 18 #include "xfa/fxfa/parser/cxfa_field.h" 19 #include "xfa/fxfa/parser/cxfa_value.h" 20 21 const CJX_MethodSpec CJX_Field::MethodSpecs[] = { 22 {"addItem", addItem_static}, 23 {"boundItem", boundItem_static}, 24 {"clearItems", clearItems_static}, 25 {"deleteItem", deleteItem_static}, 26 {"execCalculate", execCalculate_static}, 27 {"execEvent", execEvent_static}, 28 {"execInitialize", execInitialize_static}, 29 {"execValidate", execValidate_static}, 30 {"getDisplayItem", getDisplayItem_static}, 31 {"getItemState", getItemState_static}, 32 {"getSaveItem", getSaveItem_static}, 33 {"setItemState", setItemState_static}}; 34 35 CJX_Field::CJX_Field(CXFA_Field* field) : CJX_Container(field) { 36 DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs)); 37 } 38 39 CJX_Field::~CJX_Field() {} 40 41 CJS_Return CJX_Field::clearItems( 42 CJS_V8* runtime, 43 const std::vector<v8::Local<v8::Value>>& params) { 44 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 45 if (pWidgetAcc) 46 pWidgetAcc->DeleteItem(-1, true, false); 47 return CJS_Return(true); 48 } 49 50 CJS_Return CJX_Field::execEvent( 51 CJS_V8* runtime, 52 const std::vector<v8::Local<v8::Value>>& params) { 53 if (params.size() != 1) 54 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 55 56 WideString eventString = runtime->ToWideString(params[0]); 57 int32_t iRet = 58 execSingleEventByName(eventString.AsStringView(), XFA_Element::Field); 59 if (eventString != L"validate") 60 return CJS_Return(true); 61 62 return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); 63 } 64 65 CJS_Return CJX_Field::execInitialize( 66 CJS_V8* runtime, 67 const std::vector<v8::Local<v8::Value>>& params) { 68 if (!params.empty()) 69 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 70 71 CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); 72 if (pNotify) { 73 pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize, false, 74 false); 75 } 76 return CJS_Return(true); 77 } 78 79 CJS_Return CJX_Field::deleteItem( 80 CJS_V8* runtime, 81 const std::vector<v8::Local<v8::Value>>& params) { 82 if (params.size() != 1) 83 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 84 85 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 86 if (!pWidgetAcc) 87 return CJS_Return(true); 88 89 bool bValue = pWidgetAcc->DeleteItem(runtime->ToInt32(params[0]), true, true); 90 return CJS_Return(runtime->NewBoolean(bValue)); 91 } 92 93 CJS_Return CJX_Field::getSaveItem( 94 CJS_V8* runtime, 95 const std::vector<v8::Local<v8::Value>>& params) { 96 if (params.size() != 1) 97 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 98 99 int32_t iIndex = runtime->ToInt32(params[0]); 100 if (iIndex < 0) 101 return CJS_Return(runtime->NewNull()); 102 103 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 104 if (!pWidgetAcc) 105 return CJS_Return(runtime->NewNull()); 106 107 Optional<WideString> value = pWidgetAcc->GetChoiceListItem(iIndex, true); 108 if (!value) 109 return CJS_Return(runtime->NewNull()); 110 111 return CJS_Return(runtime->NewString(value->UTF8Encode().AsStringView())); 112 } 113 114 CJS_Return CJX_Field::boundItem( 115 CJS_V8* runtime, 116 const std::vector<v8::Local<v8::Value>>& params) { 117 if (params.size() != 1) 118 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 119 120 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 121 if (!pWidgetAcc) 122 return CJS_Return(true); 123 124 WideString value = runtime->ToWideString(params[0]); 125 WideString boundValue = pWidgetAcc->GetItemValue(value.AsStringView()); 126 return CJS_Return(runtime->NewString(boundValue.UTF8Encode().AsStringView())); 127 } 128 129 CJS_Return CJX_Field::getItemState( 130 CJS_V8* runtime, 131 const std::vector<v8::Local<v8::Value>>& params) { 132 if (params.size() != 1) 133 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 134 135 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 136 if (!pWidgetAcc) 137 return CJS_Return(true); 138 139 int32_t state = pWidgetAcc->GetItemState(runtime->ToInt32(params[0])); 140 return CJS_Return(runtime->NewBoolean(state != 0)); 141 } 142 143 CJS_Return CJX_Field::execCalculate( 144 CJS_V8* runtime, 145 const std::vector<v8::Local<v8::Value>>& params) { 146 if (!params.empty()) 147 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 148 149 CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); 150 if (pNotify) { 151 pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate, false, 152 false); 153 } 154 return CJS_Return(true); 155 } 156 157 CJS_Return CJX_Field::getDisplayItem( 158 CJS_V8* runtime, 159 const std::vector<v8::Local<v8::Value>>& params) { 160 if (params.size() != 1) 161 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 162 163 int32_t iIndex = runtime->ToInt32(params[0]); 164 if (iIndex < 0) 165 return CJS_Return(runtime->NewNull()); 166 167 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 168 if (!pWidgetAcc) 169 return CJS_Return(runtime->NewNull()); 170 171 Optional<WideString> value = pWidgetAcc->GetChoiceListItem(iIndex, false); 172 if (!value) 173 return CJS_Return(runtime->NewNull()); 174 175 return CJS_Return(runtime->NewString(value->UTF8Encode().AsStringView())); 176 } 177 178 CJS_Return CJX_Field::setItemState( 179 CJS_V8* runtime, 180 const std::vector<v8::Local<v8::Value>>& params) { 181 if (params.size() != 2) 182 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 183 184 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 185 if (!pWidgetAcc) 186 return CJS_Return(true); 187 188 int32_t iIndex = runtime->ToInt32(params[0]); 189 if (runtime->ToInt32(params[1]) != 0) { 190 pWidgetAcc->SetItemState(iIndex, true, true, true, true); 191 return CJS_Return(true); 192 } 193 if (pWidgetAcc->GetItemState(iIndex)) 194 pWidgetAcc->SetItemState(iIndex, false, true, true, true); 195 196 return CJS_Return(true); 197 } 198 199 CJS_Return CJX_Field::addItem(CJS_V8* runtime, 200 const std::vector<v8::Local<v8::Value>>& params) { 201 if (params.size() != 1 && params.size() != 2) 202 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 203 204 CXFA_WidgetAcc* pWidgetAcc = ToNode(GetXFAObject())->GetWidgetAcc(); 205 if (!pWidgetAcc) 206 return CJS_Return(true); 207 208 WideString label; 209 if (params.size() >= 1) 210 label = runtime->ToWideString(params[0]); 211 212 WideString value; 213 if (params.size() >= 2) 214 value = runtime->ToWideString(params[1]); 215 216 pWidgetAcc->InsertItem(label, value, true); 217 return CJS_Return(true); 218 } 219 220 CJS_Return CJX_Field::execValidate( 221 CJS_V8* runtime, 222 const std::vector<v8::Local<v8::Value>>& params) { 223 if (!params.empty()) 224 return CJS_Return(JSGetStringFromID(JSMessage::kParamError)); 225 226 CXFA_FFNotify* pNotify = GetDocument()->GetNotify(); 227 if (!pNotify) 228 return CJS_Return(runtime->NewBoolean(false)); 229 230 int32_t iRet = pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate, 231 false, false); 232 return CJS_Return(runtime->NewBoolean(iRet != XFA_EVENTERROR_Error)); 233 } 234 235 void CJX_Field::defaultValue(CFXJSE_Value* pValue, 236 bool bSetting, 237 XFA_Attribute eAttribute) { 238 CXFA_Node* xfaNode = GetXFANode(); 239 CXFA_WidgetAcc* pWidgetAcc = xfaNode->GetWidgetAcc(); 240 if (!pWidgetAcc) 241 return; 242 243 if (bSetting) { 244 if (pValue) { 245 pWidgetAcc->SetPreNull(pWidgetAcc->IsNull()); 246 pWidgetAcc->SetIsNull(pValue->IsNull()); 247 } 248 249 WideString wsNewText; 250 if (pValue && !(pValue->IsNull() || pValue->IsUndefined())) 251 wsNewText = pValue->ToWideString(); 252 253 CXFA_Node* pUIChild = pWidgetAcc->GetUIChild(); 254 if (pUIChild->GetElementType() == XFA_Element::NumericEdit) { 255 wsNewText = pWidgetAcc->NumericLimit( 256 wsNewText, pWidgetAcc->GetLeadDigits(), pWidgetAcc->GetFracDigits()); 257 } 258 259 CXFA_WidgetAcc* pContainerWidgetAcc = xfaNode->GetContainerWidgetAcc(); 260 WideString wsFormatText(wsNewText); 261 if (pContainerWidgetAcc) 262 wsFormatText = pContainerWidgetAcc->GetFormatDataValue(wsNewText); 263 264 SetContent(wsNewText, wsFormatText, true, true, true); 265 return; 266 } 267 268 WideString content = GetContent(true); 269 if (content.IsEmpty()) { 270 pValue->SetNull(); 271 return; 272 } 273 274 CXFA_Node* pUIChild = pWidgetAcc->GetUIChild(); 275 CXFA_Node* formValue = xfaNode->GetFormValueIfExists(); 276 CXFA_Node* pNode = formValue ? formValue->GetFirstChild() : nullptr; 277 if (pNode && pNode->GetElementType() == XFA_Element::Decimal) { 278 if (pUIChild->GetElementType() == XFA_Element::NumericEdit && 279 (pNode->JSObject()->GetInteger(XFA_Attribute::FracDigits) == -1)) { 280 pValue->SetString(content.UTF8Encode().AsStringView()); 281 } else { 282 CFX_Decimal decimal(content.AsStringView()); 283 pValue->SetFloat((float)(double)decimal); 284 } 285 } else if (pNode && pNode->GetElementType() == XFA_Element::Integer) { 286 pValue->SetInteger(FXSYS_wtoi(content.c_str())); 287 } else if (pNode && pNode->GetElementType() == XFA_Element::Boolean) { 288 pValue->SetBoolean(FXSYS_wtoi(content.c_str()) == 0 ? false : true); 289 } else if (pNode && pNode->GetElementType() == XFA_Element::Float) { 290 CFX_Decimal decimal(content.AsStringView()); 291 pValue->SetFloat((float)(double)decimal); 292 } else { 293 pValue->SetString(content.UTF8Encode().AsStringView()); 294 } 295 } 296 297 void CJX_Field::editValue(CFXJSE_Value* pValue, 298 bool bSetting, 299 XFA_Attribute eAttribute) { 300 CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); 301 if (!pWidgetAcc) 302 return; 303 304 if (bSetting) { 305 pWidgetAcc->SetValue(XFA_VALUEPICTURE_Edit, pValue->ToWideString()); 306 return; 307 } 308 pValue->SetString( 309 pWidgetAcc->GetValue(XFA_VALUEPICTURE_Edit).UTF8Encode().AsStringView()); 310 } 311 312 void CJX_Field::formatMessage(CFXJSE_Value* pValue, 313 bool bSetting, 314 XFA_Attribute eAttribute) { 315 Script_Som_Message(pValue, bSetting, XFA_SOM_FormatMessage); 316 } 317 318 void CJX_Field::formattedValue(CFXJSE_Value* pValue, 319 bool bSetting, 320 XFA_Attribute eAttribute) { 321 CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); 322 if (!pWidgetAcc) 323 return; 324 325 if (bSetting) { 326 pWidgetAcc->SetValue(XFA_VALUEPICTURE_Display, pValue->ToWideString()); 327 return; 328 } 329 pValue->SetString(pWidgetAcc->GetValue(XFA_VALUEPICTURE_Display) 330 .UTF8Encode() 331 .AsStringView()); 332 } 333 334 void CJX_Field::parentSubform(CFXJSE_Value* pValue, 335 bool bSetting, 336 XFA_Attribute eAttribute) { 337 if (bSetting) { 338 ThrowInvalidPropertyException(); 339 return; 340 } 341 pValue->SetNull(); 342 } 343 344 void CJX_Field::selectedIndex(CFXJSE_Value* pValue, 345 bool bSetting, 346 XFA_Attribute eAttribute) { 347 CXFA_WidgetAcc* pWidgetAcc = GetXFANode()->GetWidgetAcc(); 348 if (!pWidgetAcc) 349 return; 350 351 if (!bSetting) { 352 pValue->SetInteger(pWidgetAcc->GetSelectedItem(0)); 353 return; 354 } 355 356 int32_t iIndex = pValue->ToInteger(); 357 if (iIndex == -1) { 358 pWidgetAcc->ClearAllSelections(); 359 return; 360 } 361 362 pWidgetAcc->SetItemState(iIndex, true, true, true, true); 363 } 364 365 void CJX_Field::access(CFXJSE_Value* pValue, 366 bool bSetting, 367 XFA_Attribute eAttribute) { 368 Script_Attribute_String(pValue, bSetting, eAttribute); 369 } 370 371 void CJX_Field::accessKey(CFXJSE_Value* pValue, 372 bool bSetting, 373 XFA_Attribute eAttribute) { 374 Script_Attribute_String(pValue, bSetting, eAttribute); 375 } 376 377 void CJX_Field::anchorType(CFXJSE_Value* pValue, 378 bool bSetting, 379 XFA_Attribute eAttribute) { 380 Script_Attribute_String(pValue, bSetting, eAttribute); 381 } 382 383 void CJX_Field::borderColor(CFXJSE_Value* pValue, 384 bool bSetting, 385 XFA_Attribute eAttribute) { 386 Script_Som_BorderColor(pValue, bSetting, eAttribute); 387 } 388 389 void CJX_Field::borderWidth(CFXJSE_Value* pValue, 390 bool bSetting, 391 XFA_Attribute eAttribute) { 392 Script_Som_BorderWidth(pValue, bSetting, eAttribute); 393 } 394 395 void CJX_Field::colSpan(CFXJSE_Value* pValue, 396 bool bSetting, 397 XFA_Attribute eAttribute) { 398 Script_Attribute_String(pValue, bSetting, eAttribute); 399 } 400 401 void CJX_Field::fillColor(CFXJSE_Value* pValue, 402 bool bSetting, 403 XFA_Attribute eAttribute) { 404 Script_Som_FillColor(pValue, bSetting, eAttribute); 405 } 406 407 void CJX_Field::fontColor(CFXJSE_Value* pValue, 408 bool bSetting, 409 XFA_Attribute eAttribute) { 410 Script_Som_FontColor(pValue, bSetting, eAttribute); 411 } 412 413 void CJX_Field::h(CFXJSE_Value* pValue, 414 bool bSetting, 415 XFA_Attribute eAttribute) { 416 Script_Attribute_String(pValue, bSetting, eAttribute); 417 } 418 419 void CJX_Field::hAlign(CFXJSE_Value* pValue, 420 bool bSetting, 421 XFA_Attribute eAttribute) { 422 Script_Attribute_String(pValue, bSetting, eAttribute); 423 } 424 425 void CJX_Field::locale(CFXJSE_Value* pValue, 426 bool bSetting, 427 XFA_Attribute eAttribute) { 428 Script_Attribute_String(pValue, bSetting, eAttribute); 429 } 430 431 void CJX_Field::mandatory(CFXJSE_Value* pValue, 432 bool bSetting, 433 XFA_Attribute eAttribute) { 434 Script_Som_Mandatory(pValue, bSetting, eAttribute); 435 } 436 437 void CJX_Field::mandatoryMessage(CFXJSE_Value* pValue, 438 bool bSetting, 439 XFA_Attribute eAttribute) { 440 Script_Som_MandatoryMessage(pValue, bSetting, eAttribute); 441 } 442 443 void CJX_Field::maxH(CFXJSE_Value* pValue, 444 bool bSetting, 445 XFA_Attribute eAttribute) { 446 Script_Attribute_String(pValue, bSetting, eAttribute); 447 } 448 449 void CJX_Field::maxW(CFXJSE_Value* pValue, 450 bool bSetting, 451 XFA_Attribute eAttribute) { 452 Script_Attribute_String(pValue, bSetting, eAttribute); 453 } 454 455 void CJX_Field::minH(CFXJSE_Value* pValue, 456 bool bSetting, 457 XFA_Attribute eAttribute) { 458 Script_Attribute_String(pValue, bSetting, eAttribute); 459 } 460 461 void CJX_Field::minW(CFXJSE_Value* pValue, 462 bool bSetting, 463 XFA_Attribute eAttribute) { 464 Script_Attribute_String(pValue, bSetting, eAttribute); 465 } 466 467 void CJX_Field::presence(CFXJSE_Value* pValue, 468 bool bSetting, 469 XFA_Attribute eAttribute) { 470 Script_Attribute_String(pValue, bSetting, eAttribute); 471 } 472 473 void CJX_Field::rawValue(CFXJSE_Value* pValue, 474 bool bSetting, 475 XFA_Attribute eAttribute) { 476 defaultValue(pValue, bSetting, eAttribute); 477 } 478 479 void CJX_Field::relevant(CFXJSE_Value* pValue, 480 bool bSetting, 481 XFA_Attribute eAttribute) { 482 Script_Attribute_String(pValue, bSetting, eAttribute); 483 } 484 485 void CJX_Field::rotate(CFXJSE_Value* pValue, 486 bool bSetting, 487 XFA_Attribute eAttribute) { 488 Script_Attribute_String(pValue, bSetting, eAttribute); 489 } 490 491 void CJX_Field::use(CFXJSE_Value* pValue, 492 bool bSetting, 493 XFA_Attribute eAttribute) { 494 Script_Attribute_String(pValue, bSetting, eAttribute); 495 } 496 497 void CJX_Field::usehref(CFXJSE_Value* pValue, 498 bool bSetting, 499 XFA_Attribute eAttribute) { 500 Script_Attribute_String(pValue, bSetting, eAttribute); 501 } 502 503 void CJX_Field::validationMessage(CFXJSE_Value* pValue, 504 bool bSetting, 505 XFA_Attribute eAttribute) { 506 Script_Som_ValidationMessage(pValue, bSetting, eAttribute); 507 } 508 509 void CJX_Field::vAlign(CFXJSE_Value* pValue, 510 bool bSetting, 511 XFA_Attribute eAttribute) { 512 Script_Attribute_String(pValue, bSetting, eAttribute); 513 } 514 515 void CJX_Field::w(CFXJSE_Value* pValue, 516 bool bSetting, 517 XFA_Attribute eAttribute) { 518 Script_Attribute_String(pValue, bSetting, eAttribute); 519 } 520 521 void CJX_Field::x(CFXJSE_Value* pValue, 522 bool bSetting, 523 XFA_Attribute eAttribute) { 524 Script_Attribute_String(pValue, bSetting, eAttribute); 525 } 526 527 void CJX_Field::y(CFXJSE_Value* pValue, 528 bool bSetting, 529 XFA_Attribute eAttribute) { 530 Script_Attribute_String(pValue, bSetting, eAttribute); 531 } 532