Home | History | Annotate | Download | only in xfa
      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