Home | History | Annotate | Download | only in fxjs
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "fxjs/cjs_field.h"
      8 
      9 #include <algorithm>
     10 #include <memory>
     11 
     12 #include "core/fpdfapi/font/cpdf_font.h"
     13 #include "core/fpdfdoc/cpdf_formfield.h"
     14 #include "core/fpdfdoc/cpdf_interform.h"
     15 #include "fpdfsdk/cpdfsdk_interform.h"
     16 #include "fpdfsdk/cpdfsdk_pageview.h"
     17 #include "fpdfsdk/cpdfsdk_widget.h"
     18 #include "fxjs/cjs_color.h"
     19 #include "fxjs/cjs_delaydata.h"
     20 #include "fxjs/cjs_document.h"
     21 #include "fxjs/cjs_icon.h"
     22 #include "fxjs/js_resources.h"
     23 
     24 namespace {
     25 
     26 bool SetWidgetDisplayStatus(CPDFSDK_Widget* pWidget, int value) {
     27   if (!pWidget)
     28     return false;
     29 
     30   uint32_t dwFlag = pWidget->GetFlags();
     31   switch (value) {
     32     case 0:
     33       dwFlag &= ~ANNOTFLAG_INVISIBLE;
     34       dwFlag &= ~ANNOTFLAG_HIDDEN;
     35       dwFlag &= ~ANNOTFLAG_NOVIEW;
     36       dwFlag |= ANNOTFLAG_PRINT;
     37       break;
     38     case 1:
     39       dwFlag &= ~ANNOTFLAG_INVISIBLE;
     40       dwFlag &= ~ANNOTFLAG_NOVIEW;
     41       dwFlag |= (ANNOTFLAG_HIDDEN | ANNOTFLAG_PRINT);
     42       break;
     43     case 2:
     44       dwFlag &= ~ANNOTFLAG_INVISIBLE;
     45       dwFlag &= ~ANNOTFLAG_PRINT;
     46       dwFlag &= ~ANNOTFLAG_HIDDEN;
     47       dwFlag &= ~ANNOTFLAG_NOVIEW;
     48       break;
     49     case 3:
     50       dwFlag |= ANNOTFLAG_NOVIEW;
     51       dwFlag |= ANNOTFLAG_PRINT;
     52       dwFlag &= ~ANNOTFLAG_HIDDEN;
     53       break;
     54   }
     55 
     56   if (dwFlag != pWidget->GetFlags()) {
     57     pWidget->SetFlags(dwFlag);
     58     return true;
     59   }
     60 
     61   return false;
     62 }
     63 
     64 }  // namespace
     65 
     66 const JSPropertySpec CJS_Field::PropertySpecs[] = {
     67     {"alignment", get_alignment_static, set_alignment_static},
     68     {"borderStyle", get_border_style_static, set_border_style_static},
     69     {"buttonAlignX", get_button_align_x_static, set_button_align_x_static},
     70     {"buttonAlignY", get_button_align_y_static, set_button_align_y_static},
     71     {"buttonFitBounds", get_button_fit_bounds_static,
     72      set_button_fit_bounds_static},
     73     {"buttonPosition", get_button_position_static, set_button_position_static},
     74     {"buttonScaleHow", get_button_scale_how_static,
     75      set_button_scale_how_static},
     76     {"buttonScaleWhen", get_button_scale_when_static,
     77      set_button_scale_when_static},
     78     {"calcOrderIndex", get_calc_order_index_static,
     79      set_calc_order_index_static},
     80     {"charLimit", get_char_limit_static, set_char_limit_static},
     81     {"comb", get_comb_static, set_comb_static},
     82     {"commitOnSelChange", get_commit_on_sel_change_static,
     83      set_commit_on_sel_change_static},
     84     {"currentValueIndices", get_current_value_indices_static,
     85      set_current_value_indices_static},
     86     {"defaultStyle", get_default_style_static, set_default_style_static},
     87     {"defaultValue", get_default_value_static, set_default_value_static},
     88     {"doNotScroll", get_do_not_scroll_static, set_do_not_scroll_static},
     89     {"doNotSpellCheck", get_do_not_spell_check_static,
     90      set_do_not_spell_check_static},
     91     {"delay", get_delay_static, set_delay_static},
     92     {"display", get_display_static, set_display_static},
     93     {"doc", get_doc_static, set_doc_static},
     94     {"editable", get_editable_static, set_editable_static},
     95     {"exportValues", get_export_values_static, set_export_values_static},
     96     {"hidden", get_hidden_static, set_hidden_static},
     97     {"fileSelect", get_file_select_static, set_file_select_static},
     98     {"fillColor", get_fill_color_static, set_fill_color_static},
     99     {"lineWidth", get_line_width_static, set_line_width_static},
    100     {"highlight", get_highlight_static, set_highlight_static},
    101     {"multiline", get_multiline_static, set_multiline_static},
    102     {"multipleSelection", get_multiple_selection_static,
    103      set_multiple_selection_static},
    104     {"name", get_name_static, set_name_static},
    105     {"numItems", get_num_items_static, set_num_items_static},
    106     {"page", get_page_static, set_page_static},
    107     {"password", get_password_static, set_password_static},
    108     {"print", get_print_static, set_print_static},
    109     {"radiosInUnison", get_radios_in_unison_static,
    110      set_radios_in_unison_static},
    111     {"readonly", get_readonly_static, set_readonly_static},
    112     {"rect", get_rect_static, set_rect_static},
    113     {"required", get_required_static, set_required_static},
    114     {"richText", get_rich_text_static, set_rich_text_static},
    115     {"richValue", get_rich_value_static, set_rich_value_static},
    116     {"rotation", get_rotation_static, set_rotation_static},
    117     {"strokeColor", get_stroke_color_static, set_stroke_color_static},
    118     {"style", get_style_static, set_style_static},
    119     {"submitName", get_submit_name_static, set_submit_name_static},
    120     {"textColor", get_text_color_static, set_text_color_static},
    121     {"textFont", get_text_font_static, set_text_font_static},
    122     {"textSize", get_text_size_static, set_text_size_static},
    123     {"type", get_type_static, set_type_static},
    124     {"userName", get_user_name_static, set_user_name_static},
    125     {"value", get_value_static, set_value_static},
    126     {"valueAsString", get_value_as_string_static, set_value_as_string_static},
    127     {"source", get_source_static, set_source_static}};
    128 
    129 const JSMethodSpec CJS_Field::MethodSpecs[] = {
    130     {"browseForFileToSubmit", browseForFileToSubmit_static},
    131     {"buttonGetCaption", buttonGetCaption_static},
    132     {"buttonGetIcon", buttonGetIcon_static},
    133     {"buttonImportIcon", buttonImportIcon_static},
    134     {"buttonSetCaption", buttonSetCaption_static},
    135     {"buttonSetIcon", buttonSetIcon_static},
    136     {"checkThisBox", checkThisBox_static},
    137     {"clearItems", clearItems_static},
    138     {"defaultIsChecked", defaultIsChecked_static},
    139     {"deleteItemAt", deleteItemAt_static},
    140     {"getArray", getArray_static},
    141     {"getItemAt", getItemAt_static},
    142     {"getLock", getLock_static},
    143     {"insertItemAt", insertItemAt_static},
    144     {"isBoxChecked", isBoxChecked_static},
    145     {"isDefaultChecked", isDefaultChecked_static},
    146     {"setAction", setAction_static},
    147     {"setFocus", setFocus_static},
    148     {"setItems", setItems_static},
    149     {"setLock", setLock_static},
    150     {"signatureGetModifications", signatureGetModifications_static},
    151     {"signatureGetSeedValue", signatureGetSeedValue_static},
    152     {"signatureInfo", signatureInfo_static},
    153     {"signatureSetSeedValue", signatureSetSeedValue_static},
    154     {"signatureSign", signatureSign_static},
    155     {"signatureValidate", signatureValidate_static}};
    156 
    157 int CJS_Field::ObjDefnID = -1;
    158 
    159 // static
    160 int CJS_Field::GetObjDefnID() {
    161   return ObjDefnID;
    162 }
    163 
    164 // static
    165 void CJS_Field::DefineJSObjects(CFXJS_Engine* pEngine) {
    166   ObjDefnID = pEngine->DefineObj("Field", FXJSOBJTYPE_DYNAMIC,
    167                                  JSConstructor<CJS_Field, Field>,
    168                                  JSDestructor<CJS_Field>);
    169   DefineProps(pEngine, ObjDefnID, PropertySpecs, FX_ArraySize(PropertySpecs));
    170   DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs));
    171 }
    172 
    173 void CJS_Field::InitInstance(IJS_Runtime* pIRuntime) {}
    174 
    175 Field::Field(CJS_Object* pJSObject)
    176     : CJS_EmbedObj(pJSObject),
    177       m_pJSDoc(nullptr),
    178       m_pFormFillEnv(nullptr),
    179       m_nFormControlIndex(-1),
    180       m_bCanSet(false),
    181       m_bDelay(false) {}
    182 
    183 Field::~Field() {}
    184 
    185 // note: iControlNo = -1, means not a widget.
    186 void Field::ParseFieldName(const std::wstring& strFieldNameParsed,
    187                            std::wstring& strFieldName,
    188                            int& iControlNo) {
    189   int iStart = strFieldNameParsed.find_last_of(L'.');
    190   if (iStart == -1) {
    191     strFieldName = strFieldNameParsed;
    192     iControlNo = -1;
    193     return;
    194   }
    195   std::wstring suffixal = strFieldNameParsed.substr(iStart + 1);
    196   iControlNo = FXSYS_wtoi(suffixal.c_str());
    197   if (iControlNo == 0) {
    198     int iSpaceStart;
    199     while ((iSpaceStart = suffixal.find_last_of(L" ")) != -1) {
    200       suffixal.erase(iSpaceStart, 1);
    201     }
    202 
    203     if (suffixal.compare(L"0") != 0) {
    204       strFieldName = strFieldNameParsed;
    205       iControlNo = -1;
    206       return;
    207     }
    208   }
    209   strFieldName = strFieldNameParsed.substr(0, iStart);
    210 }
    211 
    212 bool Field::AttachField(Document* pDocument, const WideString& csFieldName) {
    213   m_pJSDoc = pDocument;
    214   m_pFormFillEnv.Reset(pDocument->GetFormFillEnv());
    215   m_bCanSet = m_pFormFillEnv->GetPermissions(FPDFPERM_FILL_FORM) ||
    216               m_pFormFillEnv->GetPermissions(FPDFPERM_ANNOT_FORM) ||
    217               m_pFormFillEnv->GetPermissions(FPDFPERM_MODIFY);
    218 
    219   CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm();
    220   CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm();
    221   WideString swFieldNameTemp = csFieldName;
    222   swFieldNameTemp.Replace(L"..", L".");
    223 
    224   if (pInterForm->CountFields(swFieldNameTemp) <= 0) {
    225     std::wstring strFieldName;
    226     int iControlNo = -1;
    227     ParseFieldName(swFieldNameTemp.c_str(), strFieldName, iControlNo);
    228     if (iControlNo == -1)
    229       return false;
    230 
    231     m_FieldName = strFieldName.c_str();
    232     m_nFormControlIndex = iControlNo;
    233     return true;
    234   }
    235 
    236   m_FieldName = swFieldNameTemp;
    237   m_nFormControlIndex = -1;
    238 
    239   return true;
    240 }
    241 
    242 std::vector<CPDF_FormField*> Field::GetFormFields(
    243     CPDFSDK_FormFillEnvironment* pFormFillEnv,
    244     const WideString& csFieldName) {
    245   std::vector<CPDF_FormField*> fields;
    246   CPDFSDK_InterForm* pReaderInterForm = pFormFillEnv->GetInterForm();
    247   CPDF_InterForm* pInterForm = pReaderInterForm->GetInterForm();
    248   for (int i = 0, sz = pInterForm->CountFields(csFieldName); i < sz; ++i) {
    249     if (CPDF_FormField* pFormField = pInterForm->GetField(i, csFieldName))
    250       fields.push_back(pFormField);
    251   }
    252   return fields;
    253 }
    254 
    255 std::vector<CPDF_FormField*> Field::GetFormFields(
    256     const WideString& csFieldName) const {
    257   return Field::GetFormFields(m_pFormFillEnv.Get(), csFieldName);
    258 }
    259 
    260 void Field::UpdateFormField(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    261                             CPDF_FormField* pFormField,
    262                             bool bChangeMark,
    263                             bool bResetAP,
    264                             bool bRefresh) {
    265   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
    266 
    267   if (bResetAP) {
    268     std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
    269     pInterForm->GetWidgets(pFormField, &widgets);
    270 
    271     FormFieldType fieldType = pFormField->GetFieldType();
    272     if (fieldType == FormFieldType::kComboBox ||
    273         fieldType == FormFieldType::kTextField) {
    274       for (auto& pObserved : widgets) {
    275         if (pObserved) {
    276           bool bFormatted = false;
    277           WideString sValue = static_cast<CPDFSDK_Widget*>(pObserved.Get())
    278                                   ->OnFormat(bFormatted);
    279           if (pObserved) {  // Not redundant, may be clobbered by OnFormat.
    280             static_cast<CPDFSDK_Widget*>(pObserved.Get())
    281                 ->ResetAppearance(bFormatted ? &sValue : nullptr, false);
    282           }
    283         }
    284       }
    285     } else {
    286       for (auto& pObserved : widgets) {
    287         if (pObserved) {
    288           static_cast<CPDFSDK_Widget*>(pObserved.Get())
    289               ->ResetAppearance(nullptr, false);
    290         }
    291       }
    292     }
    293   }
    294 
    295   if (bRefresh) {
    296     // Refresh the widget list. The calls in |bResetAP| may have caused widgets
    297     // to be removed from the list. We need to call |GetWidgets| again to be
    298     // sure none of the widgets have been deleted.
    299     std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
    300     pInterForm->GetWidgets(pFormField, &widgets);
    301 
    302     // TODO(dsinclair): Determine if all widgets share the same
    303     // CPDFSDK_InterForm. If that's the case, we can move the code to
    304     // |GetFormFillEnv| out of the loop.
    305     for (auto& pObserved : widgets) {
    306       if (pObserved) {
    307         CPDFSDK_Widget* pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
    308         pWidget->GetInterForm()->GetFormFillEnv()->UpdateAllViews(nullptr,
    309                                                                   pWidget);
    310       }
    311     }
    312   }
    313 
    314   if (bChangeMark)
    315     pFormFillEnv->SetChangeMark();
    316 }
    317 
    318 void Field::UpdateFormControl(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    319                               CPDF_FormControl* pFormControl,
    320                               bool bChangeMark,
    321                               bool bResetAP,
    322                               bool bRefresh) {
    323   ASSERT(pFormControl);
    324 
    325   CPDFSDK_InterForm* pForm = pFormFillEnv->GetInterForm();
    326   CPDFSDK_Widget* pWidget = pForm->GetWidget(pFormControl);
    327 
    328   if (pWidget) {
    329     CPDFSDK_Widget::ObservedPtr observed_widget(pWidget);
    330     if (bResetAP) {
    331       FormFieldType fieldType = pWidget->GetFieldType();
    332       if (fieldType == FormFieldType::kComboBox ||
    333           fieldType == FormFieldType::kTextField) {
    334         bool bFormatted = false;
    335         WideString sValue = pWidget->OnFormat(bFormatted);
    336         if (!observed_widget)
    337           return;
    338         pWidget->ResetAppearance(bFormatted ? &sValue : nullptr, false);
    339       } else {
    340         pWidget->ResetAppearance(nullptr, false);
    341       }
    342       if (!observed_widget)
    343         return;
    344     }
    345 
    346     if (bRefresh) {
    347       CPDFSDK_InterForm* pInterForm = pWidget->GetInterForm();
    348       pInterForm->GetFormFillEnv()->UpdateAllViews(nullptr, pWidget);
    349     }
    350   }
    351 
    352   if (bChangeMark)
    353     pFormFillEnv->SetChangeMark();
    354 }
    355 
    356 CPDFSDK_Widget* Field::GetWidget(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    357                                  CPDF_FormControl* pFormControl) {
    358   CPDFSDK_InterForm* pInterForm =
    359       static_cast<CPDFSDK_InterForm*>(pFormFillEnv->GetInterForm());
    360   return pInterForm ? pInterForm->GetWidget(pFormControl) : nullptr;
    361 }
    362 
    363 bool Field::ValueIsOccur(CPDF_FormField* pFormField, WideString csOptLabel) {
    364   for (int i = 0, sz = pFormField->CountOptions(); i < sz; i++) {
    365     if (csOptLabel.Compare(pFormField->GetOptionLabel(i)) == 0)
    366       return true;
    367   }
    368 
    369   return false;
    370 }
    371 
    372 CPDF_FormControl* Field::GetSmartFieldControl(CPDF_FormField* pFormField) {
    373   if (!pFormField->CountControls() ||
    374       m_nFormControlIndex >= pFormField->CountControls())
    375     return nullptr;
    376   if (m_nFormControlIndex < 0)
    377     return pFormField->GetControl(0);
    378   return pFormField->GetControl(m_nFormControlIndex);
    379 }
    380 
    381 CJS_Return Field::get_alignment(CJS_Runtime* pRuntime) {
    382   ASSERT(m_pFormFillEnv);
    383 
    384   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    385   if (FieldArray.empty())
    386     return CJS_Return(false);
    387 
    388   CPDF_FormField* pFormField = FieldArray[0];
    389   if (pFormField->GetFieldType() != FormFieldType::kTextField)
    390     return CJS_Return(false);
    391 
    392   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    393   if (!pFormControl)
    394     return CJS_Return(false);
    395 
    396   switch (pFormControl->GetControlAlignment()) {
    397     case 0:
    398       return CJS_Return(pRuntime->NewString(L"left"));
    399     case 1:
    400       return CJS_Return(pRuntime->NewString(L"center"));
    401     case 2:
    402       return CJS_Return(pRuntime->NewString(L"right"));
    403   }
    404   return CJS_Return(pRuntime->NewString(L""));
    405 }
    406 
    407 CJS_Return Field::set_alignment(CJS_Runtime* pRuntime,
    408                                 v8::Local<v8::Value> vp) {
    409   ASSERT(m_pFormFillEnv);
    410   return CJS_Return(m_bCanSet);
    411 }
    412 
    413 CJS_Return Field::get_border_style(CJS_Runtime* pRuntime) {
    414   ASSERT(m_pFormFillEnv);
    415 
    416   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    417   if (FieldArray.empty())
    418     return CJS_Return(false);
    419 
    420   CPDF_FormField* pFormField = FieldArray[0];
    421   if (!pFormField)
    422     return CJS_Return(false);
    423 
    424   CPDFSDK_Widget* pWidget =
    425       GetWidget(m_pFormFillEnv.Get(), GetSmartFieldControl(pFormField));
    426   if (!pWidget)
    427     return CJS_Return(false);
    428 
    429   switch (pWidget->GetBorderStyle()) {
    430     case BorderStyle::SOLID:
    431       return CJS_Return(pRuntime->NewString(L"solid"));
    432     case BorderStyle::DASH:
    433       return CJS_Return(pRuntime->NewString(L"dashed"));
    434     case BorderStyle::BEVELED:
    435       return CJS_Return(pRuntime->NewString(L"beveled"));
    436     case BorderStyle::INSET:
    437       return CJS_Return(pRuntime->NewString(L"inset"));
    438     case BorderStyle::UNDERLINE:
    439       return CJS_Return(pRuntime->NewString(L"underline"));
    440   }
    441   return CJS_Return(pRuntime->NewString(L""));
    442 }
    443 
    444 CJS_Return Field::set_border_style(CJS_Runtime* pRuntime,
    445                                    v8::Local<v8::Value> vp) {
    446   ASSERT(m_pFormFillEnv);
    447 
    448   if (!m_bCanSet)
    449     return CJS_Return(false);
    450 
    451   ByteString byte_str = ByteString::FromUnicode(pRuntime->ToWideString(vp));
    452   if (m_bDelay) {
    453     AddDelay_String(FP_BORDERSTYLE, byte_str);
    454   } else {
    455     Field::SetBorderStyle(m_pFormFillEnv.Get(), m_FieldName,
    456                           m_nFormControlIndex, byte_str);
    457   }
    458   return CJS_Return(true);
    459 }
    460 
    461 void Field::SetBorderStyle(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    462                            const WideString& swFieldName,
    463                            int nControlIndex,
    464                            const ByteString& string) {
    465   ASSERT(pFormFillEnv);
    466 
    467   BorderStyle nBorderStyle = BorderStyle::SOLID;
    468   if (string == "solid")
    469     nBorderStyle = BorderStyle::SOLID;
    470   else if (string == "beveled")
    471     nBorderStyle = BorderStyle::BEVELED;
    472   else if (string == "dashed")
    473     nBorderStyle = BorderStyle::DASH;
    474   else if (string == "inset")
    475     nBorderStyle = BorderStyle::INSET;
    476   else if (string == "underline")
    477     nBorderStyle = BorderStyle::UNDERLINE;
    478   else
    479     return;
    480 
    481   std::vector<CPDF_FormField*> FieldArray =
    482       GetFormFields(pFormFillEnv, swFieldName);
    483   for (CPDF_FormField* pFormField : FieldArray) {
    484     if (nControlIndex < 0) {
    485       bool bSet = false;
    486       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
    487         if (CPDFSDK_Widget* pWidget =
    488                 GetWidget(pFormFillEnv, pFormField->GetControl(i))) {
    489           if (pWidget->GetBorderStyle() != nBorderStyle) {
    490             pWidget->SetBorderStyle(nBorderStyle);
    491             bSet = true;
    492           }
    493         }
    494       }
    495       if (bSet)
    496         UpdateFormField(pFormFillEnv, pFormField, true, true, true);
    497     } else {
    498       if (nControlIndex >= pFormField->CountControls())
    499         return;
    500       if (CPDF_FormControl* pFormControl =
    501               pFormField->GetControl(nControlIndex)) {
    502         if (CPDFSDK_Widget* pWidget = GetWidget(pFormFillEnv, pFormControl)) {
    503           if (pWidget->GetBorderStyle() != nBorderStyle) {
    504             pWidget->SetBorderStyle(nBorderStyle);
    505             UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
    506           }
    507         }
    508       }
    509     }
    510   }
    511 }
    512 
    513 CJS_Return Field::get_button_align_x(CJS_Runtime* pRuntime) {
    514   ASSERT(m_pFormFillEnv);
    515 
    516   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    517   if (FieldArray.empty())
    518     return CJS_Return(false);
    519 
    520   CPDF_FormField* pFormField = FieldArray[0];
    521   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    522     return CJS_Return(false);
    523 
    524   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    525   if (!pFormControl)
    526     return CJS_Return(false);
    527 
    528   CPDF_IconFit IconFit = pFormControl->GetIconFit();
    529 
    530   float fLeft;
    531   float fBottom;
    532   IconFit.GetIconPosition(fLeft, fBottom);
    533 
    534   return CJS_Return(pRuntime->NewNumber(static_cast<int32_t>(fLeft)));
    535 }
    536 
    537 CJS_Return Field::set_button_align_x(CJS_Runtime* pRuntime,
    538                                      v8::Local<v8::Value> vp) {
    539   ASSERT(m_pFormFillEnv);
    540   return CJS_Return(m_bCanSet);
    541 }
    542 
    543 CJS_Return Field::get_button_align_y(CJS_Runtime* pRuntime) {
    544   ASSERT(m_pFormFillEnv);
    545 
    546   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    547   if (FieldArray.empty())
    548     return CJS_Return(false);
    549 
    550   CPDF_FormField* pFormField = FieldArray[0];
    551   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    552     return CJS_Return(false);
    553 
    554   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    555   if (!pFormControl)
    556     return CJS_Return(false);
    557 
    558   CPDF_IconFit IconFit = pFormControl->GetIconFit();
    559 
    560   float fLeft;
    561   float fBottom;
    562   IconFit.GetIconPosition(fLeft, fBottom);
    563 
    564   return CJS_Return(pRuntime->NewNumber(static_cast<int32_t>(fBottom)));
    565 }
    566 
    567 CJS_Return Field::set_button_align_y(CJS_Runtime* pRuntime,
    568                                      v8::Local<v8::Value> vp) {
    569   ASSERT(m_pFormFillEnv);
    570   return CJS_Return(m_bCanSet);
    571 }
    572 
    573 CJS_Return Field::get_button_fit_bounds(CJS_Runtime* pRuntime) {
    574   ASSERT(m_pFormFillEnv);
    575 
    576   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    577   if (FieldArray.empty())
    578     return CJS_Return(false);
    579 
    580   CPDF_FormField* pFormField = FieldArray[0];
    581   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    582     return CJS_Return(false);
    583 
    584   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    585   if (!pFormControl)
    586     return CJS_Return(false);
    587 
    588   return CJS_Return(
    589       pRuntime->NewBoolean(pFormControl->GetIconFit().GetFittingBounds()));
    590 }
    591 
    592 CJS_Return Field::set_button_fit_bounds(CJS_Runtime* pRuntime,
    593                                         v8::Local<v8::Value> vp) {
    594   ASSERT(m_pFormFillEnv);
    595   return CJS_Return(m_bCanSet);
    596 }
    597 
    598 CJS_Return Field::get_button_position(CJS_Runtime* pRuntime) {
    599   ASSERT(m_pFormFillEnv);
    600 
    601   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    602   if (FieldArray.empty())
    603     return CJS_Return(false);
    604 
    605   CPDF_FormField* pFormField = FieldArray[0];
    606   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    607     return CJS_Return(false);
    608 
    609   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    610   if (!pFormControl)
    611     return CJS_Return(false);
    612 
    613   return CJS_Return(pRuntime->NewNumber(pFormControl->GetTextPosition()));
    614 }
    615 
    616 CJS_Return Field::set_button_position(CJS_Runtime* pRuntime,
    617                                       v8::Local<v8::Value> vp) {
    618   ASSERT(m_pFormFillEnv);
    619   return CJS_Return(m_bCanSet);
    620 }
    621 
    622 CJS_Return Field::get_button_scale_how(CJS_Runtime* pRuntime) {
    623   ASSERT(m_pFormFillEnv);
    624 
    625   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    626   if (FieldArray.empty())
    627     return CJS_Return(false);
    628 
    629   CPDF_FormField* pFormField = FieldArray[0];
    630   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    631     return CJS_Return(false);
    632 
    633   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    634   if (!pFormControl)
    635     return CJS_Return(false);
    636 
    637   return CJS_Return(pRuntime->NewBoolean(
    638       pFormControl->GetIconFit().IsProportionalScale() ? 0 : 1));
    639 }
    640 
    641 CJS_Return Field::set_button_scale_how(CJS_Runtime* pRuntime,
    642                                        v8::Local<v8::Value> vp) {
    643   ASSERT(m_pFormFillEnv);
    644   return CJS_Return(m_bCanSet);
    645 }
    646 
    647 CJS_Return Field::get_button_scale_when(CJS_Runtime* pRuntime) {
    648   ASSERT(m_pFormFillEnv);
    649 
    650   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    651   if (FieldArray.empty())
    652     return CJS_Return(false);
    653 
    654   CPDF_FormField* pFormField = FieldArray[0];
    655   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
    656     return CJS_Return(false);
    657 
    658   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
    659   if (!pFormControl)
    660     return CJS_Return(false);
    661 
    662   CPDF_IconFit IconFit = pFormControl->GetIconFit();
    663   int ScaleM = IconFit.GetScaleMethod();
    664   switch (ScaleM) {
    665     case CPDF_IconFit::Always:
    666       return CJS_Return(
    667           pRuntime->NewNumber(static_cast<int32_t>(CPDF_IconFit::Always)));
    668     case CPDF_IconFit::Bigger:
    669       return CJS_Return(
    670           pRuntime->NewNumber(static_cast<int32_t>(CPDF_IconFit::Bigger)));
    671     case CPDF_IconFit::Never:
    672       return CJS_Return(
    673           pRuntime->NewNumber(static_cast<int32_t>(CPDF_IconFit::Never)));
    674     case CPDF_IconFit::Smaller:
    675       return CJS_Return(
    676           pRuntime->NewNumber(static_cast<int32_t>(CPDF_IconFit::Smaller)));
    677   }
    678   return CJS_Return(true);
    679 }
    680 
    681 CJS_Return Field::set_button_scale_when(CJS_Runtime* pRuntime,
    682                                         v8::Local<v8::Value> vp) {
    683   ASSERT(m_pFormFillEnv);
    684   return CJS_Return(m_bCanSet);
    685 }
    686 
    687 CJS_Return Field::get_calc_order_index(CJS_Runtime* pRuntime) {
    688   ASSERT(m_pFormFillEnv);
    689 
    690   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    691   if (FieldArray.empty())
    692     return CJS_Return(false);
    693 
    694   CPDF_FormField* pFormField = FieldArray[0];
    695   if (pFormField->GetFieldType() != FormFieldType::kComboBox &&
    696       pFormField->GetFieldType() != FormFieldType::kTextField) {
    697     return CJS_Return(false);
    698   }
    699 
    700   CPDFSDK_InterForm* pRDInterForm = m_pFormFillEnv->GetInterForm();
    701   CPDF_InterForm* pInterForm = pRDInterForm->GetInterForm();
    702   return CJS_Return(pRuntime->NewNumber(static_cast<int32_t>(
    703       pInterForm->FindFieldInCalculationOrder(pFormField))));
    704 }
    705 
    706 CJS_Return Field::set_calc_order_index(CJS_Runtime* pRuntime,
    707                                        v8::Local<v8::Value> vp) {
    708   ASSERT(m_pFormFillEnv);
    709   return CJS_Return(m_bCanSet);
    710 }
    711 
    712 CJS_Return Field::get_char_limit(CJS_Runtime* pRuntime) {
    713   ASSERT(m_pFormFillEnv);
    714 
    715   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    716   if (FieldArray.empty())
    717     return CJS_Return(false);
    718 
    719   CPDF_FormField* pFormField = FieldArray[0];
    720   if (pFormField->GetFieldType() != FormFieldType::kTextField)
    721     return CJS_Return(false);
    722   return CJS_Return(
    723       pRuntime->NewNumber(static_cast<int32_t>(pFormField->GetMaxLen())));
    724 }
    725 
    726 CJS_Return Field::set_char_limit(CJS_Runtime* pRuntime,
    727                                  v8::Local<v8::Value> vp) {
    728   ASSERT(m_pFormFillEnv);
    729   return CJS_Return(m_bCanSet);
    730 }
    731 
    732 CJS_Return Field::get_comb(CJS_Runtime* pRuntime) {
    733   ASSERT(m_pFormFillEnv);
    734 
    735   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    736   if (FieldArray.empty())
    737     return CJS_Return(false);
    738 
    739   CPDF_FormField* pFormField = FieldArray[0];
    740   if (pFormField->GetFieldType() != FormFieldType::kTextField)
    741     return CJS_Return(false);
    742 
    743   return CJS_Return(
    744       pRuntime->NewBoolean(!!(pFormField->GetFieldFlags() & FIELDFLAG_COMB)));
    745 }
    746 
    747 CJS_Return Field::set_comb(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    748   ASSERT(m_pFormFillEnv);
    749   return CJS_Return(m_bCanSet);
    750 }
    751 
    752 CJS_Return Field::get_commit_on_sel_change(CJS_Runtime* pRuntime) {
    753   ASSERT(m_pFormFillEnv);
    754 
    755   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    756   if (FieldArray.empty())
    757     return CJS_Return(false);
    758 
    759   CPDF_FormField* pFormField = FieldArray[0];
    760   if (pFormField->GetFieldType() != FormFieldType::kComboBox &&
    761       pFormField->GetFieldType() != FormFieldType::kListBox) {
    762     return CJS_Return(false);
    763   }
    764 
    765   return CJS_Return(pRuntime->NewBoolean(
    766       !!(pFormField->GetFieldFlags() & FIELDFLAG_COMMITONSELCHANGE)));
    767 }
    768 
    769 CJS_Return Field::set_commit_on_sel_change(CJS_Runtime* pRuntime,
    770                                            v8::Local<v8::Value> vp) {
    771   ASSERT(m_pFormFillEnv);
    772   return CJS_Return(m_bCanSet);
    773 }
    774 
    775 CJS_Return Field::get_current_value_indices(CJS_Runtime* pRuntime) {
    776   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    777   if (FieldArray.empty())
    778     return CJS_Return(false);
    779 
    780   CPDF_FormField* pFormField = FieldArray[0];
    781   if (pFormField->GetFieldType() != FormFieldType::kComboBox &&
    782       pFormField->GetFieldType() != FormFieldType::kListBox) {
    783     return CJS_Return(false);
    784   }
    785 
    786   int count = pFormField->CountSelectedItems();
    787   if (count <= 0)
    788     return CJS_Return(pRuntime->NewNumber(-1));
    789   if (count == 1)
    790     return CJS_Return(pRuntime->NewNumber(pFormField->GetSelectedIndex(0)));
    791 
    792   v8::Local<v8::Array> SelArray = pRuntime->NewArray();
    793   for (int i = 0; i < count; i++) {
    794     pRuntime->PutArrayElement(
    795         SelArray, i, pRuntime->NewNumber(pFormField->GetSelectedIndex(i)));
    796   }
    797   if (SelArray.IsEmpty())
    798     return CJS_Return(pRuntime->NewArray());
    799   return CJS_Return(SelArray);
    800 }
    801 
    802 CJS_Return Field::set_current_value_indices(CJS_Runtime* pRuntime,
    803                                             v8::Local<v8::Value> vp) {
    804   if (!m_bCanSet)
    805     return CJS_Return(false);
    806 
    807   std::vector<uint32_t> array;
    808   if (vp->IsNumber()) {
    809     array.push_back(pRuntime->ToInt32(vp));
    810   } else if (!vp.IsEmpty() && vp->IsArray()) {
    811     v8::Local<v8::Array> SelArray = pRuntime->ToArray(vp);
    812     for (size_t i = 0; i < pRuntime->GetArrayLength(SelArray); i++) {
    813       array.push_back(
    814           pRuntime->ToInt32(pRuntime->GetArrayElement(SelArray, i)));
    815     }
    816   }
    817 
    818   if (m_bDelay) {
    819     AddDelay_WordArray(FP_CURRENTVALUEINDICES, array);
    820   } else {
    821     Field::SetCurrentValueIndices(m_pFormFillEnv.Get(), m_FieldName,
    822                                   m_nFormControlIndex, array);
    823   }
    824   return CJS_Return(true);
    825 }
    826 
    827 void Field::SetCurrentValueIndices(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    828                                    const WideString& swFieldName,
    829                                    int nControlIndex,
    830                                    const std::vector<uint32_t>& array) {
    831   ASSERT(pFormFillEnv);
    832   std::vector<CPDF_FormField*> FieldArray =
    833       GetFormFields(pFormFillEnv, swFieldName);
    834 
    835   for (CPDF_FormField* pFormField : FieldArray) {
    836     FormFieldType fieldType = pFormField->GetFieldType();
    837     if (fieldType == FormFieldType::kComboBox ||
    838         fieldType == FormFieldType::kListBox) {
    839       uint32_t dwFieldFlags = pFormField->GetFieldFlags();
    840       pFormField->ClearSelection(true);
    841       for (size_t i = 0; i < array.size(); ++i) {
    842         if (i != 0 && !(dwFieldFlags & (1 << 21)))
    843           break;
    844         if (array[i] < static_cast<uint32_t>(pFormField->CountOptions()) &&
    845             !pFormField->IsItemSelected(array[i])) {
    846           pFormField->SetItemSelection(array[i], true);
    847         }
    848       }
    849       UpdateFormField(pFormFillEnv, pFormField, true, true, true);
    850     }
    851   }
    852 }
    853 
    854 CJS_Return Field::get_default_style(CJS_Runtime* pRuntime) {
    855   return CJS_Return(false);
    856 }
    857 
    858 CJS_Return Field::set_default_style(CJS_Runtime* pRuntime,
    859                                     v8::Local<v8::Value> vp) {
    860   return CJS_Return(false);
    861 }
    862 
    863 CJS_Return Field::get_default_value(CJS_Runtime* pRuntime) {
    864   ASSERT(m_pFormFillEnv);
    865 
    866   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    867   if (FieldArray.empty())
    868     return CJS_Return(false);
    869 
    870   CPDF_FormField* pFormField = FieldArray[0];
    871   if (pFormField->GetFieldType() == FormFieldType::kPushButton ||
    872       pFormField->GetFieldType() == FormFieldType::kSignature) {
    873     return CJS_Return(false);
    874   }
    875 
    876   return CJS_Return(pRuntime->NewString(pFormField->GetDefaultValue().c_str()));
    877 }
    878 
    879 CJS_Return Field::set_default_value(CJS_Runtime* pRuntime,
    880                                     v8::Local<v8::Value> vp) {
    881   ASSERT(m_pFormFillEnv);
    882   return CJS_Return(m_bCanSet);
    883 }
    884 
    885 CJS_Return Field::get_do_not_scroll(CJS_Runtime* pRuntime) {
    886   ASSERT(m_pFormFillEnv);
    887 
    888   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    889   if (FieldArray.empty())
    890     return CJS_Return(false);
    891 
    892   CPDF_FormField* pFormField = FieldArray[0];
    893   if (pFormField->GetFieldType() != FormFieldType::kTextField)
    894     return CJS_Return(false);
    895 
    896   return CJS_Return(pRuntime->NewBoolean(
    897       !!(pFormField->GetFieldFlags() & FIELDFLAG_DONOTSCROLL)));
    898 }
    899 
    900 CJS_Return Field::set_do_not_scroll(CJS_Runtime* pRuntime,
    901                                     v8::Local<v8::Value> vp) {
    902   ASSERT(m_pFormFillEnv);
    903   return CJS_Return(m_bCanSet);
    904 }
    905 
    906 CJS_Return Field::get_do_not_spell_check(CJS_Runtime* pRuntime) {
    907   ASSERT(m_pFormFillEnv);
    908 
    909   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    910   if (FieldArray.empty())
    911     return CJS_Return(false);
    912 
    913   CPDF_FormField* pFormField = FieldArray[0];
    914   if (pFormField->GetFieldType() != FormFieldType::kTextField &&
    915       pFormField->GetFieldType() != FormFieldType::kComboBox) {
    916     return CJS_Return(false);
    917   }
    918 
    919   return CJS_Return(pRuntime->NewBoolean(
    920       !!(pFormField->GetFieldFlags() & FIELDFLAG_DONOTSPELLCHECK)));
    921 }
    922 
    923 CJS_Return Field::set_do_not_spell_check(CJS_Runtime* pRuntime,
    924                                          v8::Local<v8::Value> vp) {
    925   ASSERT(m_pFormFillEnv);
    926   return CJS_Return(m_bCanSet);
    927 }
    928 
    929 void Field::SetDelay(bool bDelay) {
    930   m_bDelay = bDelay;
    931 
    932   if (m_bDelay)
    933     return;
    934   if (m_pJSDoc)
    935     m_pJSDoc->DoFieldDelay(m_FieldName, m_nFormControlIndex);
    936 }
    937 
    938 CJS_Return Field::get_delay(CJS_Runtime* pRuntime) {
    939   return CJS_Return(pRuntime->NewBoolean(m_bDelay));
    940 }
    941 
    942 CJS_Return Field::set_delay(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    943   if (!m_bCanSet)
    944     return CJS_Return(false);
    945 
    946   SetDelay(pRuntime->ToBoolean(vp));
    947   return CJS_Return(true);
    948 }
    949 
    950 CJS_Return Field::get_display(CJS_Runtime* pRuntime) {
    951   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
    952   if (FieldArray.empty())
    953     return CJS_Return(false);
    954 
    955   CPDF_FormField* pFormField = FieldArray[0];
    956   ASSERT(pFormField);
    957 
    958   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
    959   CPDFSDK_Widget* pWidget =
    960       pInterForm->GetWidget(GetSmartFieldControl(pFormField));
    961   if (!pWidget)
    962     return CJS_Return(false);
    963 
    964   uint32_t dwFlag = pWidget->GetFlags();
    965   if (ANNOTFLAG_INVISIBLE & dwFlag || ANNOTFLAG_HIDDEN & dwFlag)
    966     return CJS_Return(pRuntime->NewNumber(1));
    967 
    968   if (ANNOTFLAG_PRINT & dwFlag) {
    969     if (ANNOTFLAG_NOVIEW & dwFlag)
    970       return CJS_Return(pRuntime->NewNumber(3));
    971     return CJS_Return(pRuntime->NewNumber(0));
    972   }
    973   return CJS_Return(pRuntime->NewNumber(2));
    974 }
    975 
    976 CJS_Return Field::set_display(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
    977   if (!m_bCanSet)
    978     return CJS_Return(false);
    979 
    980   if (m_bDelay) {
    981     AddDelay_Int(FP_DISPLAY, pRuntime->ToInt32(vp));
    982   } else {
    983     Field::SetDisplay(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
    984                       pRuntime->ToInt32(vp));
    985   }
    986   return CJS_Return(true);
    987 }
    988 
    989 void Field::SetDisplay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
    990                        const WideString& swFieldName,
    991                        int nControlIndex,
    992                        int number) {
    993   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
    994   std::vector<CPDF_FormField*> FieldArray =
    995       GetFormFields(pFormFillEnv, swFieldName);
    996   for (CPDF_FormField* pFormField : FieldArray) {
    997     if (nControlIndex < 0) {
    998       bool bAnySet = false;
    999       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
   1000         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
   1001         ASSERT(pFormControl);
   1002 
   1003         CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl);
   1004         if (SetWidgetDisplayStatus(pWidget, number))
   1005           bAnySet = true;
   1006       }
   1007 
   1008       if (bAnySet)
   1009         UpdateFormField(pFormFillEnv, pFormField, true, false, true);
   1010     } else {
   1011       if (nControlIndex >= pFormField->CountControls())
   1012         return;
   1013 
   1014       CPDF_FormControl* pFormControl = pFormField->GetControl(nControlIndex);
   1015       if (!pFormControl)
   1016         return;
   1017 
   1018       CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl);
   1019       if (SetWidgetDisplayStatus(pWidget, number))
   1020         UpdateFormControl(pFormFillEnv, pFormControl, true, false, true);
   1021     }
   1022   }
   1023 }
   1024 
   1025 CJS_Return Field::get_doc(CJS_Runtime* pRuntime) {
   1026   return CJS_Return(m_pJSDoc->GetCJSDoc()->ToV8Object());
   1027 }
   1028 
   1029 CJS_Return Field::set_doc(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1030   return CJS_Return(false);
   1031 }
   1032 
   1033 CJS_Return Field::get_editable(CJS_Runtime* pRuntime) {
   1034   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1035   if (FieldArray.empty())
   1036     return CJS_Return(false);
   1037 
   1038   CPDF_FormField* pFormField = FieldArray[0];
   1039   if (pFormField->GetFieldType() != FormFieldType::kComboBox)
   1040     return CJS_Return(false);
   1041 
   1042   return CJS_Return(
   1043       pRuntime->NewBoolean(!!(pFormField->GetFieldFlags() & FIELDFLAG_EDIT)));
   1044 }
   1045 
   1046 CJS_Return Field::set_editable(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1047   return CJS_Return(m_bCanSet);
   1048 }
   1049 
   1050 CJS_Return Field::get_export_values(CJS_Runtime* pRuntime) {
   1051   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1052   if (FieldArray.empty())
   1053     return CJS_Return(false);
   1054 
   1055   CPDF_FormField* pFormField = FieldArray[0];
   1056   if (pFormField->GetFieldType() != FormFieldType::kCheckBox &&
   1057       pFormField->GetFieldType() != FormFieldType::kRadioButton) {
   1058     return CJS_Return(false);
   1059   }
   1060 
   1061   v8::Local<v8::Array> ExportValuesArray = pRuntime->NewArray();
   1062   if (m_nFormControlIndex < 0) {
   1063     for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
   1064       CPDF_FormControl* pFormControl = pFormField->GetControl(i);
   1065       pRuntime->PutArrayElement(
   1066           ExportValuesArray, i,
   1067           pRuntime->NewString(pFormControl->GetExportValue().c_str()));
   1068     }
   1069   } else {
   1070     if (m_nFormControlIndex >= pFormField->CountControls())
   1071       return CJS_Return(false);
   1072 
   1073     CPDF_FormControl* pFormControl =
   1074         pFormField->GetControl(m_nFormControlIndex);
   1075     if (!pFormControl)
   1076       return CJS_Return(false);
   1077 
   1078     pRuntime->PutArrayElement(
   1079         ExportValuesArray, 0,
   1080         pRuntime->NewString(pFormControl->GetExportValue().c_str()));
   1081   }
   1082   return CJS_Return(ExportValuesArray);
   1083 }
   1084 
   1085 CJS_Return Field::set_export_values(CJS_Runtime* pRuntime,
   1086                                     v8::Local<v8::Value> vp) {
   1087   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1088   if (FieldArray.empty())
   1089     return CJS_Return(false);
   1090 
   1091   CPDF_FormField* pFormField = FieldArray[0];
   1092   if (pFormField->GetFieldType() != FormFieldType::kCheckBox &&
   1093       pFormField->GetFieldType() != FormFieldType::kRadioButton) {
   1094     return CJS_Return(false);
   1095   }
   1096 
   1097   return CJS_Return(m_bCanSet && !vp.IsEmpty() && vp->IsArray());
   1098 }
   1099 
   1100 CJS_Return Field::get_file_select(CJS_Runtime* pRuntime) {
   1101   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1102   if (FieldArray.empty())
   1103     return CJS_Return(false);
   1104 
   1105   CPDF_FormField* pFormField = FieldArray[0];
   1106   if (pFormField->GetFieldType() != FormFieldType::kTextField)
   1107     return CJS_Return(false);
   1108 
   1109   return CJS_Return(pRuntime->NewBoolean(
   1110       !!(pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT)));
   1111 }
   1112 
   1113 CJS_Return Field::set_file_select(CJS_Runtime* pRuntime,
   1114                                   v8::Local<v8::Value> vp) {
   1115   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1116   if (FieldArray.empty())
   1117     return CJS_Return(false);
   1118 
   1119   CPDF_FormField* pFormField = FieldArray[0];
   1120   if (pFormField->GetFieldType() != FormFieldType::kTextField)
   1121     return CJS_Return(false);
   1122   return CJS_Return(m_bCanSet);
   1123 }
   1124 
   1125 CJS_Return Field::get_fill_color(CJS_Runtime* pRuntime) {
   1126   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1127   if (FieldArray.empty())
   1128     return CJS_Return(false);
   1129 
   1130   CPDF_FormField* pFormField = FieldArray[0];
   1131   ASSERT(pFormField);
   1132   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1133   if (!pFormControl)
   1134     return CJS_Return(false);
   1135 
   1136   int iColorType;
   1137   pFormControl->GetBackgroundColor(iColorType);
   1138 
   1139   CFX_Color color;
   1140   if (iColorType == CFX_Color::kTransparent) {
   1141     color = CFX_Color(CFX_Color::kTransparent);
   1142   } else if (iColorType == CFX_Color::kGray) {
   1143     color = CFX_Color(CFX_Color::kGray,
   1144                       pFormControl->GetOriginalBackgroundColor(0));
   1145   } else if (iColorType == CFX_Color::kRGB) {
   1146     color =
   1147         CFX_Color(CFX_Color::kRGB, pFormControl->GetOriginalBackgroundColor(0),
   1148                   pFormControl->GetOriginalBackgroundColor(1),
   1149                   pFormControl->GetOriginalBackgroundColor(2));
   1150   } else if (iColorType == CFX_Color::kCMYK) {
   1151     color =
   1152         CFX_Color(CFX_Color::kCMYK, pFormControl->GetOriginalBackgroundColor(0),
   1153                   pFormControl->GetOriginalBackgroundColor(1),
   1154                   pFormControl->GetOriginalBackgroundColor(2),
   1155                   pFormControl->GetOriginalBackgroundColor(3));
   1156   } else {
   1157     return CJS_Return(false);
   1158   }
   1159 
   1160   v8::Local<v8::Value> array = color::ConvertPWLColorToArray(pRuntime, color);
   1161   if (array.IsEmpty())
   1162     return CJS_Return(pRuntime->NewArray());
   1163   return CJS_Return(array);
   1164 }
   1165 
   1166 CJS_Return Field::set_fill_color(CJS_Runtime* pRuntime,
   1167                                  v8::Local<v8::Value> vp) {
   1168   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1169   if (FieldArray.empty())
   1170     return CJS_Return(false);
   1171   if (!m_bCanSet)
   1172     return CJS_Return(false);
   1173   if (vp.IsEmpty() || !vp->IsArray())
   1174     return CJS_Return(false);
   1175   return CJS_Return(true);
   1176 }
   1177 
   1178 CJS_Return Field::get_hidden(CJS_Runtime* pRuntime) {
   1179   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1180   if (FieldArray.empty())
   1181     return CJS_Return(false);
   1182 
   1183   CPDF_FormField* pFormField = FieldArray[0];
   1184   ASSERT(pFormField);
   1185 
   1186   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   1187   CPDFSDK_Widget* pWidget =
   1188       pInterForm->GetWidget(GetSmartFieldControl(pFormField));
   1189   if (!pWidget)
   1190     return CJS_Return(false);
   1191 
   1192   uint32_t dwFlags = pWidget->GetFlags();
   1193   return CJS_Return(pRuntime->NewBoolean(ANNOTFLAG_INVISIBLE & dwFlags ||
   1194                                          ANNOTFLAG_HIDDEN & dwFlags));
   1195 }
   1196 
   1197 CJS_Return Field::set_hidden(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1198   if (!m_bCanSet)
   1199     return CJS_Return(false);
   1200 
   1201   if (m_bDelay) {
   1202     AddDelay_Bool(FP_HIDDEN, pRuntime->ToBoolean(vp));
   1203   } else {
   1204     Field::SetHidden(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
   1205                      pRuntime->ToBoolean(vp));
   1206   }
   1207   return CJS_Return(true);
   1208 }
   1209 
   1210 void Field::SetHidden(CPDFSDK_FormFillEnvironment* pFormFillEnv,
   1211                       const WideString& swFieldName,
   1212                       int nControlIndex,
   1213                       bool b) {
   1214   int display = b ? 1 /*Hidden*/ : 0 /*Visible*/;
   1215   SetDisplay(pFormFillEnv, swFieldName, nControlIndex, display);
   1216 }
   1217 
   1218 CJS_Return Field::get_highlight(CJS_Runtime* pRuntime) {
   1219   ASSERT(m_pFormFillEnv);
   1220 
   1221   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1222   if (FieldArray.empty())
   1223     return CJS_Return(false);
   1224 
   1225   CPDF_FormField* pFormField = FieldArray[0];
   1226   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
   1227     return CJS_Return(false);
   1228 
   1229   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1230   if (!pFormControl)
   1231     return CJS_Return(false);
   1232 
   1233   int eHM = pFormControl->GetHighlightingMode();
   1234   switch (eHM) {
   1235     case CPDF_FormControl::None:
   1236       return CJS_Return(pRuntime->NewString(L"none"));
   1237     case CPDF_FormControl::Push:
   1238       return CJS_Return(pRuntime->NewString(L"push"));
   1239     case CPDF_FormControl::Invert:
   1240       return CJS_Return(pRuntime->NewString(L"invert"));
   1241     case CPDF_FormControl::Outline:
   1242       return CJS_Return(pRuntime->NewString(L"outline"));
   1243     case CPDF_FormControl::Toggle:
   1244       return CJS_Return(pRuntime->NewString(L"toggle"));
   1245   }
   1246   return CJS_Return(true);
   1247 }
   1248 
   1249 CJS_Return Field::set_highlight(CJS_Runtime* pRuntime,
   1250                                 v8::Local<v8::Value> vp) {
   1251   ASSERT(m_pFormFillEnv);
   1252   return CJS_Return(m_bCanSet);
   1253 }
   1254 
   1255 CJS_Return Field::get_line_width(CJS_Runtime* pRuntime) {
   1256   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1257   if (FieldArray.empty())
   1258     return CJS_Return(false);
   1259 
   1260   CPDF_FormField* pFormField = FieldArray[0];
   1261   ASSERT(pFormField);
   1262 
   1263   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1264   if (!pFormControl)
   1265     return CJS_Return(false);
   1266 
   1267   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   1268   if (!pFormField->CountControls())
   1269     return CJS_Return(false);
   1270 
   1271   CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormField->GetControl(0));
   1272   if (!pWidget)
   1273     return CJS_Return(false);
   1274 
   1275   return CJS_Return(pRuntime->NewNumber(pWidget->GetBorderWidth()));
   1276 }
   1277 
   1278 CJS_Return Field::set_line_width(CJS_Runtime* pRuntime,
   1279                                  v8::Local<v8::Value> vp) {
   1280   if (!m_bCanSet)
   1281     return CJS_Return(false);
   1282 
   1283   if (m_bDelay) {
   1284     AddDelay_Int(FP_LINEWIDTH, pRuntime->ToInt32(vp));
   1285   } else {
   1286     Field::SetLineWidth(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
   1287                         pRuntime->ToInt32(vp));
   1288   }
   1289   return CJS_Return(true);
   1290 }
   1291 
   1292 void Field::SetLineWidth(CPDFSDK_FormFillEnvironment* pFormFillEnv,
   1293                          const WideString& swFieldName,
   1294                          int nControlIndex,
   1295                          int number) {
   1296   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
   1297   std::vector<CPDF_FormField*> FieldArray =
   1298       GetFormFields(pFormFillEnv, swFieldName);
   1299   for (CPDF_FormField* pFormField : FieldArray) {
   1300     if (nControlIndex < 0) {
   1301       bool bSet = false;
   1302       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
   1303         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
   1304         ASSERT(pFormControl);
   1305 
   1306         if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
   1307           if (number != pWidget->GetBorderWidth()) {
   1308             pWidget->SetBorderWidth(number);
   1309             bSet = true;
   1310           }
   1311         }
   1312       }
   1313       if (bSet)
   1314         UpdateFormField(pFormFillEnv, pFormField, true, true, true);
   1315     } else {
   1316       if (nControlIndex >= pFormField->CountControls())
   1317         return;
   1318       if (CPDF_FormControl* pFormControl =
   1319               pFormField->GetControl(nControlIndex)) {
   1320         if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
   1321           if (number != pWidget->GetBorderWidth()) {
   1322             pWidget->SetBorderWidth(number);
   1323             UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
   1324           }
   1325         }
   1326       }
   1327     }
   1328   }
   1329 }
   1330 
   1331 CJS_Return Field::get_multiline(CJS_Runtime* pRuntime) {
   1332   ASSERT(m_pFormFillEnv);
   1333 
   1334   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1335   if (FieldArray.empty())
   1336     return CJS_Return(false);
   1337 
   1338   CPDF_FormField* pFormField = FieldArray[0];
   1339   if (pFormField->GetFieldType() != FormFieldType::kTextField)
   1340     return CJS_Return(false);
   1341 
   1342   return CJS_Return(pRuntime->NewBoolean(
   1343       !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTILINE)));
   1344 }
   1345 
   1346 CJS_Return Field::set_multiline(CJS_Runtime* pRuntime,
   1347                                 v8::Local<v8::Value> vp) {
   1348   ASSERT(m_pFormFillEnv);
   1349   return CJS_Return(m_bCanSet);
   1350 }
   1351 
   1352 CJS_Return Field::get_multiple_selection(CJS_Runtime* pRuntime) {
   1353   ASSERT(m_pFormFillEnv);
   1354   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1355   if (FieldArray.empty())
   1356     return CJS_Return(false);
   1357 
   1358   CPDF_FormField* pFormField = FieldArray[0];
   1359   if (pFormField->GetFieldType() != FormFieldType::kListBox)
   1360     return CJS_Return(false);
   1361 
   1362   return CJS_Return(pRuntime->NewBoolean(
   1363       !!(pFormField->GetFieldFlags() & FIELDFLAG_MULTISELECT)));
   1364 }
   1365 
   1366 CJS_Return Field::set_multiple_selection(CJS_Runtime* pRuntime,
   1367                                          v8::Local<v8::Value> vp) {
   1368   ASSERT(m_pFormFillEnv);
   1369   return CJS_Return(m_bCanSet);
   1370 }
   1371 
   1372 CJS_Return Field::get_name(CJS_Runtime* pRuntime) {
   1373   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1374   if (FieldArray.empty())
   1375     return CJS_Return(false);
   1376 
   1377   return CJS_Return(pRuntime->NewString(m_FieldName.c_str()));
   1378 }
   1379 
   1380 CJS_Return Field::set_name(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1381   return CJS_Return(false);
   1382 }
   1383 
   1384 CJS_Return Field::get_num_items(CJS_Runtime* pRuntime) {
   1385   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1386   if (FieldArray.empty())
   1387     return CJS_Return(false);
   1388 
   1389   CPDF_FormField* pFormField = FieldArray[0];
   1390   if (pFormField->GetFieldType() != FormFieldType::kComboBox &&
   1391       pFormField->GetFieldType() != FormFieldType::kListBox) {
   1392     return CJS_Return(false);
   1393   }
   1394 
   1395   return CJS_Return(pRuntime->NewNumber(pFormField->CountOptions()));
   1396 }
   1397 
   1398 CJS_Return Field::set_num_items(CJS_Runtime* pRuntime,
   1399                                 v8::Local<v8::Value> vp) {
   1400   return CJS_Return(false);
   1401 }
   1402 
   1403 CJS_Return Field::get_page(CJS_Runtime* pRuntime) {
   1404   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1405   if (FieldArray.empty())
   1406     return CJS_Return(false);
   1407 
   1408   CPDF_FormField* pFormField = FieldArray[0];
   1409   if (!pFormField)
   1410     return CJS_Return(false);
   1411 
   1412   std::vector<CPDFSDK_Annot::ObservedPtr> widgets;
   1413   m_pFormFillEnv->GetInterForm()->GetWidgets(pFormField, &widgets);
   1414   if (widgets.empty())
   1415     return CJS_Return(pRuntime->NewNumber(-1));
   1416 
   1417   v8::Local<v8::Array> PageArray = pRuntime->NewArray();
   1418   int i = 0;
   1419   for (const auto& pObserved : widgets) {
   1420     if (!pObserved)
   1421       return CJS_Return(JSGetStringFromID(JSMessage::kBadObjectError));
   1422 
   1423     auto* pWidget = static_cast<CPDFSDK_Widget*>(pObserved.Get());
   1424     CPDFSDK_PageView* pPageView = pWidget->GetPageView();
   1425     if (!pPageView)
   1426       return CJS_Return(false);
   1427 
   1428     pRuntime->PutArrayElement(
   1429         PageArray, i,
   1430         pRuntime->NewNumber(static_cast<int32_t>(pPageView->GetPageIndex())));
   1431     ++i;
   1432   }
   1433   return CJS_Return(PageArray);
   1434 }
   1435 
   1436 CJS_Return Field::set_page(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1437   return CJS_Return(JSGetStringFromID(JSMessage::kReadOnlyError));
   1438 }
   1439 
   1440 CJS_Return Field::get_password(CJS_Runtime* pRuntime) {
   1441   ASSERT(m_pFormFillEnv);
   1442 
   1443   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1444   if (FieldArray.empty())
   1445     return CJS_Return(false);
   1446 
   1447   CPDF_FormField* pFormField = FieldArray[0];
   1448   if (pFormField->GetFieldType() != FormFieldType::kTextField)
   1449     return CJS_Return(false);
   1450 
   1451   return CJS_Return(pRuntime->NewBoolean(
   1452       !!(pFormField->GetFieldFlags() & FIELDFLAG_PASSWORD)));
   1453 }
   1454 
   1455 CJS_Return Field::set_password(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1456   ASSERT(m_pFormFillEnv);
   1457   return CJS_Return(m_bCanSet);
   1458 }
   1459 
   1460 CJS_Return Field::get_print(CJS_Runtime* pRuntime) {
   1461   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   1462   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1463   if (FieldArray.empty())
   1464     return CJS_Return(false);
   1465 
   1466   CPDF_FormField* pFormField = FieldArray[0];
   1467   CPDFSDK_Widget* pWidget =
   1468       pInterForm->GetWidget(GetSmartFieldControl(pFormField));
   1469   if (!pWidget)
   1470     return CJS_Return(false);
   1471 
   1472   return CJS_Return(
   1473       pRuntime->NewBoolean(!!(pWidget->GetFlags() & ANNOTFLAG_PRINT)));
   1474 }
   1475 
   1476 CJS_Return Field::set_print(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1477   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   1478   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1479   if (FieldArray.empty())
   1480     return CJS_Return(false);
   1481 
   1482   if (!m_bCanSet)
   1483     return CJS_Return(false);
   1484 
   1485   for (CPDF_FormField* pFormField : FieldArray) {
   1486     if (m_nFormControlIndex < 0) {
   1487       bool bSet = false;
   1488       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
   1489         if (CPDFSDK_Widget* pWidget =
   1490                 pInterForm->GetWidget(pFormField->GetControl(i))) {
   1491           uint32_t dwFlags = pWidget->GetFlags();
   1492           if (pRuntime->ToBoolean(vp))
   1493             dwFlags |= ANNOTFLAG_PRINT;
   1494           else
   1495             dwFlags &= ~ANNOTFLAG_PRINT;
   1496 
   1497           if (dwFlags != pWidget->GetFlags()) {
   1498             pWidget->SetFlags(dwFlags);
   1499             bSet = true;
   1500           }
   1501         }
   1502       }
   1503 
   1504       if (bSet)
   1505         UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, false, true);
   1506 
   1507       continue;
   1508     }
   1509 
   1510     if (m_nFormControlIndex >= pFormField->CountControls())
   1511       return CJS_Return(false);
   1512 
   1513     if (CPDF_FormControl* pFormControl =
   1514             pFormField->GetControl(m_nFormControlIndex)) {
   1515       if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
   1516         uint32_t dwFlags = pWidget->GetFlags();
   1517         if (pRuntime->ToBoolean(vp))
   1518           dwFlags |= ANNOTFLAG_PRINT;
   1519         else
   1520           dwFlags &= ~ANNOTFLAG_PRINT;
   1521 
   1522         if (dwFlags != pWidget->GetFlags()) {
   1523           pWidget->SetFlags(dwFlags);
   1524           UpdateFormControl(m_pFormFillEnv.Get(),
   1525                             pFormField->GetControl(m_nFormControlIndex), true,
   1526                             false, true);
   1527         }
   1528       }
   1529     }
   1530   }
   1531   return CJS_Return(true);
   1532 }
   1533 
   1534 CJS_Return Field::get_radios_in_unison(CJS_Runtime* pRuntime) {
   1535   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1536   if (FieldArray.empty())
   1537     return CJS_Return(false);
   1538 
   1539   CPDF_FormField* pFormField = FieldArray[0];
   1540   if (pFormField->GetFieldType() != FormFieldType::kRadioButton)
   1541     return CJS_Return(false);
   1542 
   1543   return CJS_Return(pRuntime->NewBoolean(
   1544       !!(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON)));
   1545 }
   1546 
   1547 CJS_Return Field::set_radios_in_unison(CJS_Runtime* pRuntime,
   1548                                        v8::Local<v8::Value> vp) {
   1549   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1550   if (FieldArray.empty())
   1551     return CJS_Return(false);
   1552   return CJS_Return(m_bCanSet);
   1553 }
   1554 
   1555 CJS_Return Field::get_readonly(CJS_Runtime* pRuntime) {
   1556   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1557   if (FieldArray.empty())
   1558     return CJS_Return(false);
   1559 
   1560   return CJS_Return(pRuntime->NewBoolean(
   1561       !!(FieldArray[0]->GetFieldFlags() & FIELDFLAG_READONLY)));
   1562 }
   1563 
   1564 CJS_Return Field::set_readonly(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1565   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1566   if (FieldArray.empty())
   1567     return CJS_Return(false);
   1568   return CJS_Return(m_bCanSet);
   1569 }
   1570 
   1571 CJS_Return Field::get_rect(CJS_Runtime* pRuntime) {
   1572   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1573   if (FieldArray.empty())
   1574     return CJS_Return(false);
   1575 
   1576   CPDF_FormField* pFormField = FieldArray[0];
   1577   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   1578   CPDFSDK_Widget* pWidget =
   1579       pInterForm->GetWidget(GetSmartFieldControl(pFormField));
   1580   if (!pWidget)
   1581     return CJS_Return(false);
   1582 
   1583   CFX_FloatRect crRect = pWidget->GetRect();
   1584   v8::Local<v8::Array> rcArray = pRuntime->NewArray();
   1585   pRuntime->PutArrayElement(
   1586       rcArray, 0, pRuntime->NewNumber(static_cast<int32_t>(crRect.left)));
   1587   pRuntime->PutArrayElement(
   1588       rcArray, 1, pRuntime->NewNumber(static_cast<int32_t>(crRect.top)));
   1589   pRuntime->PutArrayElement(
   1590       rcArray, 2, pRuntime->NewNumber(static_cast<int32_t>(crRect.right)));
   1591   pRuntime->PutArrayElement(
   1592       rcArray, 3, pRuntime->NewNumber(static_cast<int32_t>(crRect.bottom)));
   1593 
   1594   return CJS_Return(rcArray);
   1595 }
   1596 
   1597 CJS_Return Field::set_rect(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1598   if (!m_bCanSet)
   1599     return CJS_Return(false);
   1600   if (vp.IsEmpty() || !vp->IsArray())
   1601     return CJS_Return(false);
   1602 
   1603   v8::Local<v8::Array> rcArray = pRuntime->ToArray(vp);
   1604   if (pRuntime->GetArrayLength(rcArray) < 4)
   1605     return CJS_Return(false);
   1606 
   1607   float pArray[4];
   1608   pArray[0] = static_cast<float>(
   1609       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 0)));
   1610   pArray[1] = static_cast<float>(
   1611       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 1)));
   1612   pArray[2] = static_cast<float>(
   1613       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 2)));
   1614   pArray[3] = static_cast<float>(
   1615       pRuntime->ToInt32(pRuntime->GetArrayElement(rcArray, 3)));
   1616 
   1617   CFX_FloatRect crRect(pArray);
   1618   if (m_bDelay) {
   1619     AddDelay_Rect(FP_RECT, crRect);
   1620   } else {
   1621     Field::SetRect(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
   1622                    crRect);
   1623   }
   1624   return CJS_Return(true);
   1625 }
   1626 
   1627 void Field::SetRect(CPDFSDK_FormFillEnvironment* pFormFillEnv,
   1628                     const WideString& swFieldName,
   1629                     int nControlIndex,
   1630                     const CFX_FloatRect& rect) {
   1631   CPDFSDK_InterForm* pInterForm = pFormFillEnv->GetInterForm();
   1632   std::vector<CPDF_FormField*> FieldArray =
   1633       GetFormFields(pFormFillEnv, swFieldName);
   1634   for (CPDF_FormField* pFormField : FieldArray) {
   1635     if (nControlIndex < 0) {
   1636       bool bSet = false;
   1637       for (int i = 0, sz = pFormField->CountControls(); i < sz; ++i) {
   1638         CPDF_FormControl* pFormControl = pFormField->GetControl(i);
   1639         ASSERT(pFormControl);
   1640 
   1641         if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
   1642           CFX_FloatRect crRect = rect;
   1643 
   1644           CPDF_Page* pPDFPage = pWidget->GetPDFPage();
   1645           crRect.Intersect(pPDFPage->GetPageBBox());
   1646 
   1647           if (!crRect.IsEmpty()) {
   1648             CFX_FloatRect rcOld = pWidget->GetRect();
   1649             if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
   1650                 crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
   1651               pWidget->SetRect(crRect);
   1652               bSet = true;
   1653             }
   1654           }
   1655         }
   1656       }
   1657 
   1658       if (bSet)
   1659         UpdateFormField(pFormFillEnv, pFormField, true, true, true);
   1660 
   1661       continue;
   1662     }
   1663 
   1664     if (nControlIndex >= pFormField->CountControls())
   1665       return;
   1666     if (CPDF_FormControl* pFormControl =
   1667             pFormField->GetControl(nControlIndex)) {
   1668       if (CPDFSDK_Widget* pWidget = pInterForm->GetWidget(pFormControl)) {
   1669         CFX_FloatRect crRect = rect;
   1670 
   1671         CPDF_Page* pPDFPage = pWidget->GetPDFPage();
   1672         crRect.Intersect(pPDFPage->GetPageBBox());
   1673 
   1674         if (!crRect.IsEmpty()) {
   1675           CFX_FloatRect rcOld = pWidget->GetRect();
   1676           if (crRect.left != rcOld.left || crRect.right != rcOld.right ||
   1677               crRect.top != rcOld.top || crRect.bottom != rcOld.bottom) {
   1678             pWidget->SetRect(crRect);
   1679             UpdateFormControl(pFormFillEnv, pFormControl, true, true, true);
   1680           }
   1681         }
   1682       }
   1683     }
   1684   }
   1685 }
   1686 
   1687 CJS_Return Field::get_required(CJS_Runtime* pRuntime) {
   1688   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1689   if (FieldArray.empty())
   1690     return CJS_Return(false);
   1691 
   1692   CPDF_FormField* pFormField = FieldArray[0];
   1693   if (pFormField->GetFieldType() == FormFieldType::kPushButton)
   1694     return CJS_Return(false);
   1695 
   1696   return CJS_Return(pRuntime->NewBoolean(
   1697       !!(pFormField->GetFieldFlags() & FIELDFLAG_REQUIRED)));
   1698 }
   1699 
   1700 CJS_Return Field::set_required(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1701   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1702   if (FieldArray.empty())
   1703     return CJS_Return(false);
   1704   return CJS_Return(m_bCanSet);
   1705 }
   1706 
   1707 CJS_Return Field::get_rich_text(CJS_Runtime* pRuntime) {
   1708   ASSERT(m_pFormFillEnv);
   1709 
   1710   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1711   if (FieldArray.empty())
   1712     return CJS_Return(false);
   1713 
   1714   CPDF_FormField* pFormField = FieldArray[0];
   1715   if (pFormField->GetFieldType() != FormFieldType::kTextField)
   1716     return CJS_Return(false);
   1717 
   1718   return CJS_Return(pRuntime->NewBoolean(
   1719       !!(pFormField->GetFieldFlags() & FIELDFLAG_RICHTEXT)));
   1720 }
   1721 
   1722 CJS_Return Field::set_rich_text(CJS_Runtime* pRuntime,
   1723                                 v8::Local<v8::Value> vp) {
   1724   ASSERT(m_pFormFillEnv);
   1725   return CJS_Return(m_bCanSet);
   1726 }
   1727 
   1728 CJS_Return Field::get_rich_value(CJS_Runtime* pRuntime) {
   1729   return CJS_Return(true);
   1730 }
   1731 
   1732 CJS_Return Field::set_rich_value(CJS_Runtime* pRuntime,
   1733                                  v8::Local<v8::Value> vp) {
   1734   return CJS_Return(true);
   1735 }
   1736 
   1737 CJS_Return Field::get_rotation(CJS_Runtime* pRuntime) {
   1738   ASSERT(m_pFormFillEnv);
   1739 
   1740   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1741   if (FieldArray.empty())
   1742     return CJS_Return(false);
   1743 
   1744   CPDF_FormField* pFormField = FieldArray[0];
   1745   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1746   if (!pFormControl)
   1747     return CJS_Return(false);
   1748 
   1749   return CJS_Return(pRuntime->NewNumber(pFormControl->GetRotation()));
   1750 }
   1751 
   1752 CJS_Return Field::set_rotation(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1753   ASSERT(m_pFormFillEnv);
   1754   return CJS_Return(m_bCanSet);
   1755 }
   1756 
   1757 CJS_Return Field::get_stroke_color(CJS_Runtime* pRuntime) {
   1758   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1759   if (FieldArray.empty())
   1760     return CJS_Return(false);
   1761 
   1762   CPDF_FormField* pFormField = FieldArray[0];
   1763   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1764   if (!pFormControl)
   1765     return CJS_Return(false);
   1766 
   1767   int iColorType;
   1768   pFormControl->GetBorderColor(iColorType);
   1769 
   1770   CFX_Color color;
   1771   if (iColorType == CFX_Color::kTransparent) {
   1772     color = CFX_Color(CFX_Color::kTransparent);
   1773   } else if (iColorType == CFX_Color::kGray) {
   1774     color =
   1775         CFX_Color(CFX_Color::kGray, pFormControl->GetOriginalBorderColor(0));
   1776   } else if (iColorType == CFX_Color::kRGB) {
   1777     color = CFX_Color(CFX_Color::kRGB, pFormControl->GetOriginalBorderColor(0),
   1778                       pFormControl->GetOriginalBorderColor(1),
   1779                       pFormControl->GetOriginalBorderColor(2));
   1780   } else if (iColorType == CFX_Color::kCMYK) {
   1781     color = CFX_Color(CFX_Color::kCMYK, pFormControl->GetOriginalBorderColor(0),
   1782                       pFormControl->GetOriginalBorderColor(1),
   1783                       pFormControl->GetOriginalBorderColor(2),
   1784                       pFormControl->GetOriginalBorderColor(3));
   1785   } else {
   1786     return CJS_Return(false);
   1787   }
   1788 
   1789   v8::Local<v8::Value> array = color::ConvertPWLColorToArray(pRuntime, color);
   1790   if (array.IsEmpty())
   1791     return CJS_Return(pRuntime->NewArray());
   1792   return CJS_Return(array);
   1793 }
   1794 
   1795 CJS_Return Field::set_stroke_color(CJS_Runtime* pRuntime,
   1796                                    v8::Local<v8::Value> vp) {
   1797   if (!m_bCanSet)
   1798     return CJS_Return(false);
   1799   if (vp.IsEmpty() || !vp->IsArray())
   1800     return CJS_Return(false);
   1801   return CJS_Return(true);
   1802 }
   1803 
   1804 CJS_Return Field::get_style(CJS_Runtime* pRuntime) {
   1805   ASSERT(m_pFormFillEnv);
   1806 
   1807   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1808   if (FieldArray.empty())
   1809     return CJS_Return(false);
   1810 
   1811   CPDF_FormField* pFormField = FieldArray[0];
   1812   if (pFormField->GetFieldType() != FormFieldType::kRadioButton &&
   1813       pFormField->GetFieldType() != FormFieldType::kCheckBox) {
   1814     return CJS_Return(false);
   1815   }
   1816 
   1817   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1818   if (!pFormControl)
   1819     return CJS_Return(false);
   1820 
   1821   WideString csWCaption = pFormControl->GetNormalCaption();
   1822   ByteString csBCaption;
   1823 
   1824   switch (csWCaption[0]) {
   1825     case L'l':
   1826       csBCaption = "circle";
   1827       break;
   1828     case L'8':
   1829       csBCaption = "cross";
   1830       break;
   1831     case L'u':
   1832       csBCaption = "diamond";
   1833       break;
   1834     case L'n':
   1835       csBCaption = "square";
   1836       break;
   1837     case L'H':
   1838       csBCaption = "star";
   1839       break;
   1840     default:  // L'4'
   1841       csBCaption = "check";
   1842       break;
   1843   }
   1844   return CJS_Return(
   1845       pRuntime->NewString(WideString::FromLocal(csBCaption.c_str()).c_str()));
   1846 }
   1847 
   1848 CJS_Return Field::set_style(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1849   ASSERT(m_pFormFillEnv);
   1850   return CJS_Return(m_bCanSet);
   1851 }
   1852 
   1853 CJS_Return Field::get_submit_name(CJS_Runtime* pRuntime) {
   1854   return CJS_Return(true);
   1855 }
   1856 
   1857 CJS_Return Field::set_submit_name(CJS_Runtime* pRuntime,
   1858                                   v8::Local<v8::Value> vp) {
   1859   return CJS_Return(true);
   1860 }
   1861 
   1862 CJS_Return Field::get_text_color(CJS_Runtime* pRuntime) {
   1863   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1864   if (FieldArray.empty())
   1865     return CJS_Return(false);
   1866 
   1867   CPDF_FormField* pFormField = FieldArray[0];
   1868   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1869   if (!pFormControl)
   1870     return CJS_Return(false);
   1871 
   1872   int iColorType;
   1873   FX_ARGB color;
   1874   CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
   1875   FieldAppearance.GetColor(color, iColorType);
   1876 
   1877   int32_t a;
   1878   int32_t r;
   1879   int32_t g;
   1880   int32_t b;
   1881   std::tie(a, r, g, b) = ArgbDecode(color);
   1882 
   1883   CFX_Color crRet =
   1884       CFX_Color(CFX_Color::kRGB, r / 255.0f, g / 255.0f, b / 255.0f);
   1885 
   1886   if (iColorType == CFX_Color::kTransparent)
   1887     crRet = CFX_Color(CFX_Color::kTransparent);
   1888 
   1889   v8::Local<v8::Value> array = color::ConvertPWLColorToArray(pRuntime, crRet);
   1890   if (array.IsEmpty())
   1891     return CJS_Return(pRuntime->NewArray());
   1892   return CJS_Return(array);
   1893 }
   1894 
   1895 CJS_Return Field::set_text_color(CJS_Runtime* pRuntime,
   1896                                  v8::Local<v8::Value> vp) {
   1897   if (!m_bCanSet)
   1898     return CJS_Return(false);
   1899   if (vp.IsEmpty() || !vp->IsArray())
   1900     return CJS_Return(false);
   1901   return CJS_Return(true);
   1902 }
   1903 
   1904 CJS_Return Field::get_text_font(CJS_Runtime* pRuntime) {
   1905   ASSERT(m_pFormFillEnv);
   1906 
   1907   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1908   if (FieldArray.empty())
   1909     return CJS_Return(false);
   1910 
   1911   CPDF_FormField* pFormField = FieldArray[0];
   1912   ASSERT(pFormField);
   1913   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1914   if (!pFormControl)
   1915     return CJS_Return(false);
   1916 
   1917   FormFieldType fieldType = pFormField->GetFieldType();
   1918   if (fieldType != FormFieldType::kPushButton &&
   1919       fieldType != FormFieldType::kComboBox &&
   1920       fieldType != FormFieldType::kListBox &&
   1921       fieldType != FormFieldType::kTextField) {
   1922     return CJS_Return(false);
   1923   }
   1924 
   1925   CPDF_Font* pFont = pFormControl->GetDefaultControlFont();
   1926   if (!pFont)
   1927     return CJS_Return(false);
   1928 
   1929   return CJS_Return(pRuntime->NewString(
   1930       WideString::FromLocal(pFont->GetBaseFont().c_str()).c_str()));
   1931 }
   1932 
   1933 CJS_Return Field::set_text_font(CJS_Runtime* pRuntime,
   1934                                 v8::Local<v8::Value> vp) {
   1935   ASSERT(m_pFormFillEnv);
   1936 
   1937   if (!m_bCanSet)
   1938     return CJS_Return(false);
   1939   return CJS_Return(
   1940       !ByteString::FromUnicode(pRuntime->ToWideString(vp)).IsEmpty());
   1941 }
   1942 
   1943 CJS_Return Field::get_text_size(CJS_Runtime* pRuntime) {
   1944   ASSERT(m_pFormFillEnv);
   1945 
   1946   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1947   if (FieldArray.empty())
   1948     return CJS_Return(false);
   1949 
   1950   CPDF_FormField* pFormField = FieldArray[0];
   1951   ASSERT(pFormField);
   1952   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   1953   if (!pFormControl)
   1954     return CJS_Return(false);
   1955 
   1956   float fFontSize;
   1957   CPDF_DefaultAppearance FieldAppearance = pFormControl->GetDefaultAppearance();
   1958   FieldAppearance.GetFont(&fFontSize);
   1959   return CJS_Return(pRuntime->NewNumber(static_cast<int>(fFontSize)));
   1960 }
   1961 
   1962 CJS_Return Field::set_text_size(CJS_Runtime* pRuntime,
   1963                                 v8::Local<v8::Value> vp) {
   1964   ASSERT(m_pFormFillEnv);
   1965   return CJS_Return(m_bCanSet);
   1966 }
   1967 
   1968 CJS_Return Field::get_type(CJS_Runtime* pRuntime) {
   1969   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   1970   if (FieldArray.empty())
   1971     return CJS_Return(false);
   1972 
   1973   CPDF_FormField* pFormField = FieldArray[0];
   1974   switch (pFormField->GetFieldType()) {
   1975     case FormFieldType::kUnknown:
   1976       return CJS_Return(pRuntime->NewString(L"unknown"));
   1977     case FormFieldType::kPushButton:
   1978       return CJS_Return(pRuntime->NewString(L"button"));
   1979     case FormFieldType::kCheckBox:
   1980       return CJS_Return(pRuntime->NewString(L"checkbox"));
   1981     case FormFieldType::kRadioButton:
   1982       return CJS_Return(pRuntime->NewString(L"radiobutton"));
   1983     case FormFieldType::kComboBox:
   1984       return CJS_Return(pRuntime->NewString(L"combobox"));
   1985     case FormFieldType::kListBox:
   1986       return CJS_Return(pRuntime->NewString(L"listbox"));
   1987     case FormFieldType::kTextField:
   1988       return CJS_Return(pRuntime->NewString(L"text"));
   1989     case FormFieldType::kSignature:
   1990       return CJS_Return(pRuntime->NewString(L"signature"));
   1991     default:
   1992       return CJS_Return(pRuntime->NewString(L"unknown"));
   1993   }
   1994 }
   1995 
   1996 CJS_Return Field::set_type(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   1997   return CJS_Return(false);
   1998 }
   1999 
   2000 CJS_Return Field::get_user_name(CJS_Runtime* pRuntime) {
   2001   ASSERT(m_pFormFillEnv);
   2002 
   2003   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2004   if (FieldArray.empty())
   2005     return CJS_Return(false);
   2006 
   2007   return CJS_Return(
   2008       pRuntime->NewString(FieldArray[0]->GetAlternateName().c_str()));
   2009 }
   2010 
   2011 CJS_Return Field::set_user_name(CJS_Runtime* pRuntime,
   2012                                 v8::Local<v8::Value> vp) {
   2013   ASSERT(m_pFormFillEnv);
   2014   return CJS_Return(m_bCanSet);
   2015 }
   2016 
   2017 CJS_Return Field::get_value(CJS_Runtime* pRuntime) {
   2018   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2019   if (FieldArray.empty())
   2020     return CJS_Return(false);
   2021 
   2022   v8::Local<v8::Value> ret;
   2023 
   2024   CPDF_FormField* pFormField = FieldArray[0];
   2025   switch (pFormField->GetFieldType()) {
   2026     case FormFieldType::kPushButton:
   2027       return CJS_Return(false);
   2028     case FormFieldType::kComboBox:
   2029     case FormFieldType::kTextField:
   2030       ret = pRuntime->NewString(pFormField->GetValue().c_str());
   2031       break;
   2032     case FormFieldType::kListBox: {
   2033       if (pFormField->CountSelectedItems() > 1) {
   2034         v8::Local<v8::Array> ValueArray = pRuntime->NewArray();
   2035         v8::Local<v8::Value> ElementValue;
   2036         int iIndex;
   2037         for (int i = 0, sz = pFormField->CountSelectedItems(); i < sz; i++) {
   2038           iIndex = pFormField->GetSelectedIndex(i);
   2039           ElementValue =
   2040               pRuntime->NewString(pFormField->GetOptionValue(iIndex).c_str());
   2041           if (wcslen(pRuntime->ToWideString(ElementValue).c_str()) == 0) {
   2042             ElementValue =
   2043                 pRuntime->NewString(pFormField->GetOptionLabel(iIndex).c_str());
   2044           }
   2045           pRuntime->PutArrayElement(ValueArray, i, ElementValue);
   2046         }
   2047         ret = ValueArray;
   2048       } else {
   2049         ret = pRuntime->NewString(pFormField->GetValue().c_str());
   2050       }
   2051       break;
   2052     }
   2053     case FormFieldType::kCheckBox:
   2054     case FormFieldType::kRadioButton: {
   2055       bool bFind = false;
   2056       for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
   2057         if (pFormField->GetControl(i)->IsChecked()) {
   2058           ret = pRuntime->NewString(
   2059               pFormField->GetControl(i)->GetExportValue().c_str());
   2060           bFind = true;
   2061           break;
   2062         }
   2063       }
   2064       if (!bFind)
   2065         ret = pRuntime->NewString(L"Off");
   2066 
   2067       break;
   2068     }
   2069     default:
   2070       ret = pRuntime->NewString(pFormField->GetValue().c_str());
   2071       break;
   2072   }
   2073   return CJS_Return(pRuntime->MaybeCoerceToNumber(ret));
   2074 }
   2075 
   2076 CJS_Return Field::set_value(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   2077   if (!m_bCanSet)
   2078     return CJS_Return(false);
   2079 
   2080   std::vector<WideString> strArray;
   2081   if (!vp.IsEmpty() && vp->IsArray()) {
   2082     v8::Local<v8::Array> ValueArray = pRuntime->ToArray(vp);
   2083     for (size_t i = 0; i < pRuntime->GetArrayLength(ValueArray); i++) {
   2084       strArray.push_back(
   2085           pRuntime->ToWideString(pRuntime->GetArrayElement(ValueArray, i)));
   2086     }
   2087   } else {
   2088     strArray.push_back(pRuntime->ToWideString(vp));
   2089   }
   2090 
   2091   if (m_bDelay) {
   2092     AddDelay_WideStringArray(FP_VALUE, strArray);
   2093   } else {
   2094     Field::SetValue(m_pFormFillEnv.Get(), m_FieldName, m_nFormControlIndex,
   2095                     strArray);
   2096   }
   2097   return CJS_Return(true);
   2098 }
   2099 
   2100 void Field::SetValue(CPDFSDK_FormFillEnvironment* pFormFillEnv,
   2101                      const WideString& swFieldName,
   2102                      int nControlIndex,
   2103                      const std::vector<WideString>& strArray) {
   2104   ASSERT(pFormFillEnv);
   2105   if (strArray.empty())
   2106     return;
   2107 
   2108   std::vector<CPDF_FormField*> FieldArray =
   2109       GetFormFields(pFormFillEnv, swFieldName);
   2110 
   2111   for (CPDF_FormField* pFormField : FieldArray) {
   2112     if (pFormField->GetFullName().Compare(swFieldName) != 0)
   2113       continue;
   2114 
   2115     switch (pFormField->GetFieldType()) {
   2116       case FormFieldType::kTextField:
   2117       case FormFieldType::kComboBox:
   2118         if (pFormField->GetValue() != strArray[0]) {
   2119           pFormField->SetValue(strArray[0], true);
   2120           UpdateFormField(pFormFillEnv, pFormField, true, false, true);
   2121         }
   2122         break;
   2123       case FormFieldType::kCheckBox:
   2124       case FormFieldType::kRadioButton:
   2125         if (pFormField->GetValue() != strArray[0]) {
   2126           pFormField->SetValue(strArray[0], true);
   2127           UpdateFormField(pFormFillEnv, pFormField, true, false, true);
   2128         }
   2129         break;
   2130       case FormFieldType::kListBox: {
   2131         bool bModified = false;
   2132         for (const auto& str : strArray) {
   2133           if (!pFormField->IsItemSelected(pFormField->FindOption(str))) {
   2134             bModified = true;
   2135             break;
   2136           }
   2137         }
   2138         if (bModified) {
   2139           pFormField->ClearSelection(true);
   2140           for (const auto& str : strArray) {
   2141             int index = pFormField->FindOption(str);
   2142             if (!pFormField->IsItemSelected(index))
   2143               pFormField->SetItemSelection(index, true, true);
   2144           }
   2145           UpdateFormField(pFormFillEnv, pFormField, true, false, true);
   2146         }
   2147         break;
   2148       }
   2149       default:
   2150         break;
   2151     }
   2152   }
   2153 }
   2154 
   2155 CJS_Return Field::get_value_as_string(CJS_Runtime* pRuntime) {
   2156   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2157   if (FieldArray.empty())
   2158     return CJS_Return(false);
   2159 
   2160   CPDF_FormField* pFormField = FieldArray[0];
   2161   if (pFormField->GetFieldType() == FormFieldType::kPushButton)
   2162     return CJS_Return(false);
   2163 
   2164   if (pFormField->GetFieldType() == FormFieldType::kCheckBox) {
   2165     if (!pFormField->CountControls())
   2166       return CJS_Return(false);
   2167     return CJS_Return(pRuntime->NewString(
   2168         pFormField->GetControl(0)->IsChecked() ? L"Yes" : L"Off"));
   2169   }
   2170 
   2171   if (pFormField->GetFieldType() == FormFieldType::kRadioButton &&
   2172       !(pFormField->GetFieldFlags() & FIELDFLAG_RADIOSINUNISON)) {
   2173     for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
   2174       if (pFormField->GetControl(i)->IsChecked()) {
   2175         return CJS_Return(pRuntime->NewString(
   2176             pFormField->GetControl(i)->GetExportValue().c_str()));
   2177       }
   2178     }
   2179     return CJS_Return(pRuntime->NewString(L"Off"));
   2180   }
   2181 
   2182   if (pFormField->GetFieldType() == FormFieldType::kListBox &&
   2183       (pFormField->CountSelectedItems() > 1)) {
   2184     return CJS_Return(pRuntime->NewString(L""));
   2185   }
   2186   return CJS_Return(pRuntime->NewString(pFormField->GetValue().c_str()));
   2187 }
   2188 
   2189 CJS_Return Field::set_value_as_string(CJS_Runtime* pRuntime,
   2190                                       v8::Local<v8::Value> vp) {
   2191   return CJS_Return(false);
   2192 }
   2193 
   2194 CJS_Return Field::browseForFileToSubmit(
   2195     CJS_Runtime* pRuntime,
   2196     const std::vector<v8::Local<v8::Value>>& params) {
   2197   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2198   if (FieldArray.empty())
   2199     return CJS_Return(false);
   2200 
   2201   CPDF_FormField* pFormField = FieldArray[0];
   2202   if ((pFormField->GetFieldFlags() & FIELDFLAG_FILESELECT) &&
   2203       (pFormField->GetFieldType() == FormFieldType::kTextField)) {
   2204     WideString wsFileName = m_pFormFillEnv->JS_fieldBrowse();
   2205     if (!wsFileName.IsEmpty()) {
   2206       pFormField->SetValue(wsFileName);
   2207       UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true);
   2208     }
   2209     return CJS_Return(true);
   2210   }
   2211   return CJS_Return(false);
   2212 }
   2213 
   2214 CJS_Return Field::buttonGetCaption(
   2215     CJS_Runtime* pRuntime,
   2216     const std::vector<v8::Local<v8::Value>>& params) {
   2217   int nface = 0;
   2218   int iSize = params.size();
   2219   if (iSize >= 1)
   2220     nface = pRuntime->ToInt32(params[0]);
   2221 
   2222   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2223   if (FieldArray.empty())
   2224     return CJS_Return(false);
   2225 
   2226   CPDF_FormField* pFormField = FieldArray[0];
   2227   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
   2228     return CJS_Return(false);
   2229 
   2230   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   2231   if (!pFormControl)
   2232     return CJS_Return(false);
   2233 
   2234   if (nface == 0) {
   2235     return CJS_Return(
   2236         pRuntime->NewString(pFormControl->GetNormalCaption().c_str()));
   2237   } else if (nface == 1) {
   2238     return CJS_Return(
   2239         pRuntime->NewString(pFormControl->GetDownCaption().c_str()));
   2240   } else if (nface == 2) {
   2241     return CJS_Return(
   2242         pRuntime->NewString(pFormControl->GetRolloverCaption().c_str()));
   2243   }
   2244   return CJS_Return(false);
   2245 }
   2246 
   2247 CJS_Return Field::buttonGetIcon(
   2248     CJS_Runtime* pRuntime,
   2249     const std::vector<v8::Local<v8::Value>>& params) {
   2250   if (params.size() >= 1) {
   2251     int nFace = pRuntime->ToInt32(params[0]);
   2252     if (nFace < 0 || nFace > 2)
   2253       return CJS_Return(false);
   2254   }
   2255 
   2256   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2257   if (FieldArray.empty())
   2258     return CJS_Return(false);
   2259 
   2260   CPDF_FormField* pFormField = FieldArray[0];
   2261   if (pFormField->GetFieldType() != FormFieldType::kPushButton)
   2262     return CJS_Return(false);
   2263 
   2264   CPDF_FormControl* pFormControl = GetSmartFieldControl(pFormField);
   2265   if (!pFormControl)
   2266     return CJS_Return(false);
   2267 
   2268   v8::Local<v8::Object> pObj =
   2269       pRuntime->NewFxDynamicObj(CJS_Icon::GetObjDefnID());
   2270   if (pObj.IsEmpty())
   2271     return CJS_Return(false);
   2272 
   2273   CJS_Icon* pJS_Icon = static_cast<CJS_Icon*>(pRuntime->GetObjectPrivate(pObj));
   2274   if (!pJS_Icon)
   2275     return CJS_Return(false);
   2276   return CJS_Return(pJS_Icon->ToV8Object());
   2277 }
   2278 
   2279 CJS_Return Field::buttonImportIcon(
   2280     CJS_Runtime* pRuntime,
   2281     const std::vector<v8::Local<v8::Value>>& params) {
   2282   return CJS_Return(true);
   2283 }
   2284 
   2285 CJS_Return Field::buttonSetCaption(
   2286     CJS_Runtime* pRuntime,
   2287     const std::vector<v8::Local<v8::Value>>& params) {
   2288   return CJS_Return(false);
   2289 }
   2290 
   2291 CJS_Return Field::buttonSetIcon(
   2292     CJS_Runtime* pRuntime,
   2293     const std::vector<v8::Local<v8::Value>>& params) {
   2294   return CJS_Return(false);
   2295 }
   2296 
   2297 CJS_Return Field::checkThisBox(
   2298     CJS_Runtime* pRuntime,
   2299     const std::vector<v8::Local<v8::Value>>& params) {
   2300   int iSize = params.size();
   2301   if (iSize < 1)
   2302     return CJS_Return(false);
   2303 
   2304   if (!m_bCanSet)
   2305     return CJS_Return(false);
   2306 
   2307   int nWidget = pRuntime->ToInt32(params[0]);
   2308   bool bCheckit = true;
   2309   if (iSize >= 2)
   2310     bCheckit = pRuntime->ToBoolean(params[1]);
   2311 
   2312   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2313   if (FieldArray.empty())
   2314     return CJS_Return(false);
   2315 
   2316   CPDF_FormField* pFormField = FieldArray[0];
   2317   if (pFormField->GetFieldType() != FormFieldType::kCheckBox &&
   2318       pFormField->GetFieldType() != FormFieldType::kRadioButton) {
   2319     return CJS_Return(false);
   2320   }
   2321   if (nWidget < 0 || nWidget >= pFormField->CountControls())
   2322     return CJS_Return(false);
   2323   // TODO(weili): Check whether anything special needed for radio button,
   2324   // otherwise merge these branches.
   2325   if (pFormField->GetFieldType() == FormFieldType::kRadioButton)
   2326     pFormField->CheckControl(nWidget, bCheckit, true);
   2327   else
   2328     pFormField->CheckControl(nWidget, bCheckit, true);
   2329 
   2330   UpdateFormField(m_pFormFillEnv.Get(), pFormField, true, true, true);
   2331   return CJS_Return(true);
   2332 }
   2333 
   2334 CJS_Return Field::clearItems(CJS_Runtime* pRuntime,
   2335                              const std::vector<v8::Local<v8::Value>>& params) {
   2336   return CJS_Return(true);
   2337 }
   2338 
   2339 CJS_Return Field::defaultIsChecked(
   2340     CJS_Runtime* pRuntime,
   2341     const std::vector<v8::Local<v8::Value>>& params) {
   2342   if (!m_bCanSet)
   2343     return CJS_Return(false);
   2344 
   2345   int iSize = params.size();
   2346   if (iSize < 1)
   2347     return CJS_Return(false);
   2348 
   2349   int nWidget = pRuntime->ToInt32(params[0]);
   2350   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2351   if (FieldArray.empty())
   2352     return CJS_Return(false);
   2353 
   2354   CPDF_FormField* pFormField = FieldArray[0];
   2355   if (nWidget < 0 || nWidget >= pFormField->CountControls())
   2356     return CJS_Return(false);
   2357 
   2358   return CJS_Return(pRuntime->NewBoolean(
   2359       pFormField->GetFieldType() == FormFieldType::kCheckBox ||
   2360       pFormField->GetFieldType() == FormFieldType::kRadioButton));
   2361 }
   2362 
   2363 CJS_Return Field::deleteItemAt(
   2364     CJS_Runtime* pRuntime,
   2365     const std::vector<v8::Local<v8::Value>>& params) {
   2366   return CJS_Return(true);
   2367 }
   2368 
   2369 CJS_Return Field::getArray(CJS_Runtime* pRuntime,
   2370                            const std::vector<v8::Local<v8::Value>>& params) {
   2371   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2372   if (FieldArray.empty())
   2373     return CJS_Return(false);
   2374 
   2375   std::vector<std::unique_ptr<WideString>> swSort;
   2376   for (CPDF_FormField* pFormField : FieldArray) {
   2377     swSort.push_back(
   2378         std::unique_ptr<WideString>(new WideString(pFormField->GetFullName())));
   2379   }
   2380 
   2381   std::sort(swSort.begin(), swSort.end(),
   2382             [](const std::unique_ptr<WideString>& p1,
   2383                const std::unique_ptr<WideString>& p2) { return *p1 < *p2; });
   2384 
   2385   v8::Local<v8::Array> FormFieldArray = pRuntime->NewArray();
   2386   int j = 0;
   2387   for (const auto& pStr : swSort) {
   2388     v8::Local<v8::Object> pObj =
   2389         pRuntime->NewFxDynamicObj(CJS_Field::GetObjDefnID());
   2390     if (pObj.IsEmpty())
   2391       return CJS_Return(false);
   2392 
   2393     CJS_Field* pJSField =
   2394         static_cast<CJS_Field*>(pRuntime->GetObjectPrivate(pObj));
   2395     Field* pField = static_cast<Field*>(pJSField->GetEmbedObject());
   2396     pField->AttachField(m_pJSDoc, *pStr);
   2397     pRuntime->PutArrayElement(FormFieldArray, j++,
   2398                               pJSField
   2399                                   ? v8::Local<v8::Value>(pJSField->ToV8Object())
   2400                                   : v8::Local<v8::Value>());
   2401   }
   2402   return CJS_Return(FormFieldArray);
   2403 }
   2404 
   2405 CJS_Return Field::getItemAt(CJS_Runtime* pRuntime,
   2406                             const std::vector<v8::Local<v8::Value>>& params) {
   2407   int iSize = params.size();
   2408   int nIdx = -1;
   2409   if (iSize >= 1)
   2410     nIdx = pRuntime->ToInt32(params[0]);
   2411 
   2412   bool bExport = true;
   2413   if (iSize >= 2)
   2414     bExport = pRuntime->ToBoolean(params[1]);
   2415 
   2416   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2417   if (FieldArray.empty())
   2418     return CJS_Return(false);
   2419 
   2420   CPDF_FormField* pFormField = FieldArray[0];
   2421   if ((pFormField->GetFieldType() == FormFieldType::kListBox) ||
   2422       (pFormField->GetFieldType() == FormFieldType::kComboBox)) {
   2423     if (nIdx == -1 || nIdx > pFormField->CountOptions())
   2424       nIdx = pFormField->CountOptions() - 1;
   2425     if (bExport) {
   2426       WideString strval = pFormField->GetOptionValue(nIdx);
   2427       if (strval.IsEmpty()) {
   2428         return CJS_Return(
   2429             pRuntime->NewString(pFormField->GetOptionLabel(nIdx).c_str()));
   2430       }
   2431       return CJS_Return(pRuntime->NewString(strval.c_str()));
   2432     }
   2433     return CJS_Return(
   2434         pRuntime->NewString(pFormField->GetOptionLabel(nIdx).c_str()));
   2435   }
   2436   return CJS_Return(false);
   2437 }
   2438 
   2439 CJS_Return Field::getLock(CJS_Runtime* pRuntime,
   2440                           const std::vector<v8::Local<v8::Value>>& params) {
   2441   return CJS_Return(false);
   2442 }
   2443 
   2444 CJS_Return Field::insertItemAt(
   2445     CJS_Runtime* pRuntime,
   2446     const std::vector<v8::Local<v8::Value>>& params) {
   2447   return CJS_Return(true);
   2448 }
   2449 
   2450 CJS_Return Field::isBoxChecked(
   2451     CJS_Runtime* pRuntime,
   2452     const std::vector<v8::Local<v8::Value>>& params) {
   2453   int nIndex = -1;
   2454   if (params.size() >= 1)
   2455     nIndex = pRuntime->ToInt32(params[0]);
   2456 
   2457   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2458   if (FieldArray.empty())
   2459     return CJS_Return(false);
   2460 
   2461   CPDF_FormField* pFormField = FieldArray[0];
   2462   if (nIndex < 0 || nIndex >= pFormField->CountControls())
   2463     return CJS_Return(false);
   2464 
   2465   return CJS_Return(pRuntime->NewBoolean(
   2466       ((pFormField->GetFieldType() == FormFieldType::kCheckBox ||
   2467         pFormField->GetFieldType() == FormFieldType::kRadioButton) &&
   2468        pFormField->GetControl(nIndex)->IsChecked() != 0)));
   2469 }
   2470 
   2471 CJS_Return Field::isDefaultChecked(
   2472     CJS_Runtime* pRuntime,
   2473     const std::vector<v8::Local<v8::Value>>& params) {
   2474   int nIndex = -1;
   2475   if (params.size() >= 1)
   2476     nIndex = pRuntime->ToInt32(params[0]);
   2477 
   2478   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2479   if (FieldArray.empty())
   2480     return CJS_Return(false);
   2481 
   2482   CPDF_FormField* pFormField = FieldArray[0];
   2483   if (nIndex < 0 || nIndex >= pFormField->CountControls())
   2484     return CJS_Return(false);
   2485 
   2486   return CJS_Return(pRuntime->NewBoolean(
   2487       ((pFormField->GetFieldType() == FormFieldType::kCheckBox ||
   2488         pFormField->GetFieldType() == FormFieldType::kRadioButton) &&
   2489        pFormField->GetControl(nIndex)->IsDefaultChecked() != 0)));
   2490 }
   2491 
   2492 CJS_Return Field::setAction(CJS_Runtime* pRuntime,
   2493                             const std::vector<v8::Local<v8::Value>>& params) {
   2494   return CJS_Return(true);
   2495 }
   2496 
   2497 CJS_Return Field::setFocus(CJS_Runtime* pRuntime,
   2498                            const std::vector<v8::Local<v8::Value>>& params) {
   2499   std::vector<CPDF_FormField*> FieldArray = GetFormFields(m_FieldName);
   2500   if (FieldArray.empty())
   2501     return CJS_Return(false);
   2502 
   2503   CPDF_FormField* pFormField = FieldArray[0];
   2504   int32_t nCount = pFormField->CountControls();
   2505   if (nCount < 1)
   2506     return CJS_Return(false);
   2507 
   2508   CPDFSDK_InterForm* pInterForm = m_pFormFillEnv->GetInterForm();
   2509   CPDFSDK_Widget* pWidget = nullptr;
   2510   if (nCount == 1) {
   2511     pWidget = pInterForm->GetWidget(pFormField->GetControl(0));
   2512   } else {
   2513     UnderlyingPageType* pPage =
   2514         UnderlyingFromFPDFPage(m_pFormFillEnv->GetCurrentPage(
   2515             m_pFormFillEnv->GetUnderlyingDocument()));
   2516     if (!pPage)
   2517       return CJS_Return(false);
   2518     if (CPDFSDK_PageView* pCurPageView =
   2519             m_pFormFillEnv->GetPageView(pPage, true)) {
   2520       for (int32_t i = 0; i < nCount; i++) {
   2521         if (CPDFSDK_Widget* pTempWidget =
   2522                 pInterForm->GetWidget(pFormField->GetControl(i))) {
   2523           if (pTempWidget->GetPDFPage() == pCurPageView->GetPDFPage()) {
   2524             pWidget = pTempWidget;
   2525             break;
   2526           }
   2527         }
   2528       }
   2529     }
   2530   }
   2531 
   2532   if (pWidget) {
   2533     CPDFSDK_Annot::ObservedPtr pObserved(pWidget);
   2534     m_pFormFillEnv->SetFocusAnnot(&pObserved);
   2535   }
   2536 
   2537   return CJS_Return(true);
   2538 }
   2539 
   2540 CJS_Return Field::setItems(CJS_Runtime* pRuntime,
   2541                            const std::vector<v8::Local<v8::Value>>& params) {
   2542   return CJS_Return(true);
   2543 }
   2544 
   2545 CJS_Return Field::setLock(CJS_Runtime* pRuntime,
   2546                           const std::vector<v8::Local<v8::Value>>& params) {
   2547   return CJS_Return(false);
   2548 }
   2549 
   2550 CJS_Return Field::signatureGetModifications(
   2551     CJS_Runtime* pRuntime,
   2552     const std::vector<v8::Local<v8::Value>>& params) {
   2553   return CJS_Return(false);
   2554 }
   2555 
   2556 CJS_Return Field::signatureGetSeedValue(
   2557     CJS_Runtime* pRuntime,
   2558     const std::vector<v8::Local<v8::Value>>& params) {
   2559   return CJS_Return(false);
   2560 }
   2561 
   2562 CJS_Return Field::signatureInfo(
   2563     CJS_Runtime* pRuntime,
   2564     const std::vector<v8::Local<v8::Value>>& params) {
   2565   return CJS_Return(false);
   2566 }
   2567 
   2568 CJS_Return Field::signatureSetSeedValue(
   2569     CJS_Runtime* pRuntime,
   2570     const std::vector<v8::Local<v8::Value>>& params) {
   2571   return CJS_Return(false);
   2572 }
   2573 
   2574 CJS_Return Field::signatureSign(
   2575     CJS_Runtime* pRuntime,
   2576     const std::vector<v8::Local<v8::Value>>& params) {
   2577   return CJS_Return(false);
   2578 }
   2579 
   2580 CJS_Return Field::signatureValidate(
   2581     CJS_Runtime* pRuntime,
   2582     const std::vector<v8::Local<v8::Value>>& params) {
   2583   return CJS_Return(false);
   2584 }
   2585 
   2586 CJS_Return Field::get_source(CJS_Runtime* pRuntime) {
   2587   return CJS_Return(true);
   2588 }
   2589 
   2590 CJS_Return Field::set_source(CJS_Runtime* pRuntime, v8::Local<v8::Value> vp) {
   2591   return CJS_Return(true);
   2592 }
   2593 
   2594 void Field::AddDelay_Int(FIELD_PROP prop, int32_t n) {
   2595   CJS_DelayData* pNewData =
   2596       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2597   pNewData->num = n;
   2598   m_pJSDoc->AddDelayData(pNewData);
   2599 }
   2600 
   2601 void Field::AddDelay_Bool(FIELD_PROP prop, bool b) {
   2602   CJS_DelayData* pNewData =
   2603       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2604   pNewData->b = b;
   2605   m_pJSDoc->AddDelayData(pNewData);
   2606 }
   2607 
   2608 void Field::AddDelay_String(FIELD_PROP prop, const ByteString& string) {
   2609   CJS_DelayData* pNewData =
   2610       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2611   pNewData->string = string;
   2612   m_pJSDoc->AddDelayData(pNewData);
   2613 }
   2614 
   2615 void Field::AddDelay_Rect(FIELD_PROP prop, const CFX_FloatRect& rect) {
   2616   CJS_DelayData* pNewData =
   2617       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2618   pNewData->rect = rect;
   2619   m_pJSDoc->AddDelayData(pNewData);
   2620 }
   2621 
   2622 void Field::AddDelay_WordArray(FIELD_PROP prop,
   2623                                const std::vector<uint32_t>& array) {
   2624   CJS_DelayData* pNewData =
   2625       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2626   pNewData->wordarray = array;
   2627   m_pJSDoc->AddDelayData(pNewData);
   2628 }
   2629 
   2630 void Field::AddDelay_WideStringArray(FIELD_PROP prop,
   2631                                      const std::vector<WideString>& array) {
   2632   CJS_DelayData* pNewData =
   2633       new CJS_DelayData(prop, m_nFormControlIndex, m_FieldName);
   2634   pNewData->widestringarray = array;
   2635   m_pJSDoc->AddDelayData(pNewData);
   2636 }
   2637 
   2638 void Field::DoDelay(CPDFSDK_FormFillEnvironment* pFormFillEnv,
   2639                     CJS_DelayData* pData) {
   2640   ASSERT(pFormFillEnv);
   2641   switch (pData->eProp) {
   2642     case FP_BORDERSTYLE:
   2643       Field::SetBorderStyle(pFormFillEnv, pData->sFieldName,
   2644                             pData->nControlIndex, pData->string);
   2645       break;
   2646     case FP_CURRENTVALUEINDICES:
   2647       Field::SetCurrentValueIndices(pFormFillEnv, pData->sFieldName,
   2648                                     pData->nControlIndex, pData->wordarray);
   2649       break;
   2650     case FP_DISPLAY:
   2651       Field::SetDisplay(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
   2652                         pData->num);
   2653       break;
   2654     case FP_HIDDEN:
   2655       Field::SetHidden(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
   2656                        pData->b);
   2657       break;
   2658     case FP_LINEWIDTH:
   2659       Field::SetLineWidth(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
   2660                           pData->num);
   2661       break;
   2662     case FP_RECT:
   2663       Field::SetRect(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
   2664                      pData->rect);
   2665       break;
   2666     case FP_VALUE:
   2667       Field::SetValue(pFormFillEnv, pData->sFieldName, pData->nControlIndex,
   2668                       pData->widestringarray);
   2669       break;
   2670     default:
   2671       NOTREACHED();
   2672   }
   2673 }
   2674