// Copyright 2016 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "fpdfsdk/cpdfsdk_interform.h"

#include <algorithm>
#include <memory>
#include <sstream>
#include <string>
#include <vector>

#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/parser/cfdf_document.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfdoc/cpdf_actionfields.h"
#include "core/fpdfdoc/cpdf_interform.h"
#include "core/fxge/cfx_graphstatedata.h"
#include "core/fxge/cfx_pathdata.h"
#include "core/fxge/cfx_renderdevice.h"
#include "fpdfsdk/cba_annotiterator.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
#include "fpdfsdk/cpdfsdk_pageview.h"
#include "fpdfsdk/cpdfsdk_widget.h"
#include "fpdfsdk/formfiller/cffl_formfiller.h"
#include "fpdfsdk/fsdk_actionhandler.h"
#include "fpdfsdk/fsdk_define.h"
#include "fpdfsdk/ipdfsdk_annothandler.h"
#include "fxjs/ijs_event_context.h"
#include "fxjs/ijs_runtime.h"
#include "third_party/base/stl_util.h"

#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/cpdfsdk_xfawidget.h"
#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_ffwidgethandler.h"
#endif  // PDF_ENABLE_XFA

CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment* pFormFillEnv)
    : m_pFormFillEnv(pFormFillEnv),
      m_pInterForm(
          pdfium::MakeUnique<CPDF_InterForm>(m_pFormFillEnv->GetPDFDocument())),
#ifdef PDF_ENABLE_XFA
      m_bXfaCalculate(true),
      m_bXfaValidationsEnabled(true),
#endif  // PDF_ENABLE_XFA
      m_bCalculate(true),
      m_bBusy(false),
      m_iHighlightAlpha(0) {
  m_pInterForm->SetFormNotify(this);
  for (int i = 0; i < kNumFieldTypes; ++i)
    m_bNeedHightlight[i] = false;
}

CPDFSDK_InterForm::~CPDFSDK_InterForm() {
  m_Map.clear();
#ifdef PDF_ENABLE_XFA
  m_XFAMap.clear();
#endif  // PDF_ENABLE_XFA
}

bool CPDFSDK_InterForm::HighlightWidgets() {
  return false;
}

CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget,
                                              bool bNext) const {
  auto pIterator = pdfium::MakeUnique<CBA_AnnotIterator>(
      pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET);

  if (bNext)
    return static_cast<CPDFSDK_Widget*>(pIterator->GetNextAnnot(pWidget));

  return static_cast<CPDFSDK_Widget*>(pIterator->GetPrevAnnot(pWidget));
}

CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const {
  if (!pControl || !m_pInterForm)
    return nullptr;

  CPDFSDK_Widget* pWidget = nullptr;
  const auto it = m_Map.find(pControl);
  if (it != m_Map.end())
    pWidget = it->second;
  if (pWidget)
    return pWidget;

  CPDF_Dictionary* pControlDict = pControl->GetWidget();
  CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
  CPDFSDK_PageView* pPage = nullptr;

  if (CPDF_Dictionary* pPageDict = pControlDict->GetDictFor("P")) {
    int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum());
    if (nPageIndex >= 0)
      pPage = m_pFormFillEnv->GetPageView(nPageIndex);
  }

  if (!pPage) {
    int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict);
    if (nPageIndex >= 0)
      pPage = m_pFormFillEnv->GetPageView(nPageIndex);
  }

  if (!pPage)
    return nullptr;

  return static_cast<CPDFSDK_Widget*>(pPage->GetAnnotByDict(pControlDict));
}

void CPDFSDK_InterForm::GetWidgets(
    const WideString& sFieldName,
    std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
  for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) {
    CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName);
    ASSERT(pFormField);
    GetWidgets(pFormField, widgets);
  }
}

void CPDFSDK_InterForm::GetWidgets(
    CPDF_FormField* pField,
    std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const {
  for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
    CPDF_FormControl* pFormCtrl = pField->GetControl(i);
    ASSERT(pFormCtrl);
    CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
    if (pWidget)
      widgets->emplace_back(pWidget);
  }
}

int CPDFSDK_InterForm::GetPageIndexByAnnotDict(
    CPDF_Document* pDocument,
    CPDF_Dictionary* pAnnotDict) const {
  ASSERT(pAnnotDict);

  for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) {
    if (CPDF_Dictionary* pPageDict = pDocument->GetPage(i)) {
      if (CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots")) {
        for (int j = 0, jsz = pAnnots->GetCount(); j < jsz; j++) {
          CPDF_Object* pDict = pAnnots->GetDirectObjectAt(j);
          if (pAnnotDict == pDict)
            return i;
        }
      }
    }
  }

  return -1;
}

void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl,
                               CPDFSDK_Widget* pWidget) {
  m_Map[pControl] = pWidget;
}

void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) {
  m_Map.erase(pControl);
}

void CPDFSDK_InterForm::EnableCalculate(bool bEnabled) {
  m_bCalculate = bEnabled;
}

bool CPDFSDK_InterForm::IsCalculateEnabled() const {
  return m_bCalculate;
}

#ifdef PDF_ENABLE_XFA
void CPDFSDK_InterForm::AddXFAMap(CXFA_FFWidget* hWidget,
                                  CPDFSDK_XFAWidget* pWidget) {
  ASSERT(hWidget);
  m_XFAMap[hWidget] = pWidget;
}

void CPDFSDK_InterForm::RemoveXFAMap(CXFA_FFWidget* hWidget) {
  ASSERT(hWidget);
  m_XFAMap.erase(hWidget);
}

CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(CXFA_FFWidget* hWidget) {
  ASSERT(hWidget);
  auto it = m_XFAMap.find(hWidget);
  return it != m_XFAMap.end() ? it->second : nullptr;
}

void CPDFSDK_InterForm::XfaEnableCalculate(bool bEnabled) {
  m_bXfaCalculate = bEnabled;
}
bool CPDFSDK_InterForm::IsXfaCalculateEnabled() const {
  return m_bXfaCalculate;
}

bool CPDFSDK_InterForm::IsXfaValidationsEnabled() {
  return m_bXfaValidationsEnabled;
}
void CPDFSDK_InterForm::XfaSetValidationsEnabled(bool bEnabled) {
  m_bXfaValidationsEnabled = bEnabled;
}

void CPDFSDK_InterForm::SynchronizeField(CPDF_FormField* pFormField,
                                         bool bSynchronizeElse) {
  for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
    CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
    if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
      pWidget->Synchronize(bSynchronizeElse);
  }
}
#endif  // PDF_ENABLE_XFA

void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) {
  if (!m_pFormFillEnv->IsJSInitiated())
    return;

  if (m_bBusy)
    return;

  m_bBusy = true;

  if (!IsCalculateEnabled()) {
    m_bBusy = false;
    return;
  }

  IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime();
  int nSize = m_pInterForm->CountFieldsInCalculationOrder();
  for (int i = 0; i < nSize; i++) {
    CPDF_FormField* pField = m_pInterForm->GetFieldInCalculationOrder(i);
    if (!pField)
      continue;

    int nType = pField->GetFieldType();
    if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD)
      continue;

    CPDF_AAction aAction = pField->GetAdditionalAction();
    if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Calculate))
      continue;

    CPDF_Action action = aAction.GetAction(CPDF_AAction::Calculate);
    if (!action.GetDict())
      continue;

    WideString csJS = action.GetJavaScript();
    if (csJS.IsEmpty())
      continue;

    IJS_EventContext* pContext = pRuntime->NewEventContext();
    WideString sOldValue = pField->GetValue();
    WideString sValue = sOldValue;
    bool bRC = true;
    pContext->OnField_Calculate(pFormField, pField, sValue, bRC);

    WideString sInfo;
    bool bRet = pContext->RunScript(csJS, &sInfo);
    pRuntime->ReleaseEventContext(pContext);
    if (bRet && bRC && sValue.Compare(sOldValue) != 0)
      pField->SetValue(sValue, true);
  }
  m_bBusy = false;
}

WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField,
                                       bool& bFormatted) {
  WideString sValue = pFormField->GetValue();
  if (!m_pFormFillEnv->IsJSInitiated()) {
    bFormatted = false;
    return sValue;
  }

  IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime();
  if (pFormField->GetFieldType() == FIELDTYPE_COMBOBOX &&
      pFormField->CountSelectedItems() > 0) {
    int index = pFormField->GetSelectedIndex(0);
    if (index >= 0)
      sValue = pFormField->GetOptionLabel(index);
  }

  bFormatted = false;

  CPDF_AAction aAction = pFormField->GetAdditionalAction();
  if (aAction.GetDict() && aAction.ActionExist(CPDF_AAction::Format)) {
    CPDF_Action action = aAction.GetAction(CPDF_AAction::Format);
    if (action.GetDict()) {
      WideString script = action.GetJavaScript();
      if (!script.IsEmpty()) {
        WideString Value = sValue;

        IJS_EventContext* pContext = pRuntime->NewEventContext();
        pContext->OnField_Format(pFormField, Value, true);
        WideString sInfo;
        bool bRet = pContext->RunScript(script, &sInfo);
        pRuntime->ReleaseEventContext(pContext);
        if (bRet) {
          sValue = Value;
          bFormatted = true;
        }
      }
    }
  }
  return sValue;
}

void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField,
                                             const WideString* sValue,
                                             bool bValueChanged) {
  for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
    CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
    ASSERT(pFormCtrl);
    if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
      pWidget->ResetAppearance(sValue, bValueChanged);
  }
}

void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) {
  auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller();
  for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
    CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
    ASSERT(pFormCtrl);

    CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
    if (!pWidget)
      continue;

    UnderlyingPageType* pPage = pWidget->GetUnderlyingPage();
    FX_RECT rect = formfiller->GetViewBBox(
        m_pFormFillEnv->GetPageView(pPage, false), pWidget);
    m_pFormFillEnv->Invalidate(pPage, rect);
  }
}

bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
                                          const WideString& csValue) {
  CPDF_AAction aAction = pFormField->GetAdditionalAction();
  if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::KeyStroke))
    return true;

  CPDF_Action action = aAction.GetAction(CPDF_AAction::KeyStroke);
  if (!action.GetDict())
    return true;

  CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
  PDFSDK_FieldAction fa;
  fa.bModifier = false;
  fa.bShift = false;
  fa.sValue = csValue;
  pActionHandler->DoAction_FieldJavaScript(
      action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa);
  return fa.bRC;
}

bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField,
                                   const WideString& csValue) {
  CPDF_AAction aAction = pFormField->GetAdditionalAction();
  if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Validate))
    return true;

  CPDF_Action action = aAction.GetAction(CPDF_AAction::Validate);
  if (!action.GetDict())
    return true;

  CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler();
  PDFSDK_FieldAction fa;
  fa.bModifier = false;
  fa.bShift = false;
  fa.sValue = csValue;
  pActionHandler->DoAction_FieldJavaScript(
      action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa);
  return fa.bRC;
}

bool CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) {
  ASSERT(action.GetDict());

  CPDF_ActionFields af(&action);
  std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
  std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);

  bool bHide = action.GetHideStatus();
  bool bChanged = false;

  for (CPDF_FormField* pField : fields) {
    for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
      CPDF_FormControl* pControl = pField->GetControl(i);
      ASSERT(pControl);

      if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) {
        uint32_t nFlags = pWidget->GetFlags();
        nFlags &= ~ANNOTFLAG_INVISIBLE;
        nFlags &= ~ANNOTFLAG_NOVIEW;
        if (bHide)
          nFlags |= ANNOTFLAG_HIDDEN;
        else
          nFlags &= ~ANNOTFLAG_HIDDEN;
        pWidget->SetFlags(nFlags);
        pWidget->GetPageView()->UpdateView(pWidget);
        bChanged = true;
      }
    }
  }

  return bChanged;
}

bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) {
  WideString sDestination = action.GetFilePath();
  if (sDestination.IsEmpty())
    return false;

  CPDF_Dictionary* pActionDict = action.GetDict();
  if (pActionDict->KeyExist("Fields")) {
    CPDF_ActionFields af(&action);
    uint32_t dwFlags = action.GetFlags();
    std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
    std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
    if (!fields.empty()) {
      bool bIncludeOrExclude = !(dwFlags & 0x01);
      if (!m_pInterForm->CheckRequiredFields(&fields, bIncludeOrExclude))
        return false;

      return SubmitFields(sDestination, fields, bIncludeOrExclude, false);
    }
  }
  if (!m_pInterForm->CheckRequiredFields(nullptr, true))
    return false;

  return SubmitForm(sDestination, false);
}

bool CPDFSDK_InterForm::SubmitFields(const WideString& csDestination,
                                     const std::vector<CPDF_FormField*>& fields,
                                     bool bIncludeOrExclude,
                                     bool bUrlEncoded) {
  ByteString textBuf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude);

  size_t nBufSize = textBuf.GetLength();
  if (nBufSize == 0)
    return false;

  uint8_t* pLocalBuffer = FX_Alloc(uint8_t, nBufSize);
  memcpy(pLocalBuffer, textBuf.c_str(), nBufSize);
  uint8_t* pBuffer = pLocalBuffer;

  if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
    FX_Free(pLocalBuffer);
    return false;
  }

  m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str());

  if (pBuffer != pLocalBuffer)
    FX_Free(pBuffer);

  FX_Free(pLocalBuffer);

  return true;
}

bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize) {
  std::unique_ptr<CFDF_Document> pFDF =
      CFDF_Document::ParseMemory(pBuf, nBufSize);
  if (!pFDF)
    return true;

  CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDictFor("FDF");
  if (!pMainDict)
    return false;

  CPDF_Array* pFields = pMainDict->GetArrayFor("Fields");
  if (!pFields)
    return false;

  std::ostringstream fdfEncodedData;
  for (uint32_t i = 0; i < pFields->GetCount(); i++) {
    CPDF_Dictionary* pField = pFields->GetDictAt(i);
    if (!pField)
      continue;
    WideString name;
    name = pField->GetUnicodeTextFor("T");
    ByteString name_b = ByteString::FromUnicode(name);
    ByteString csBValue = pField->GetStringFor("V");
    WideString csWValue = PDF_DecodeText(csBValue);
    ByteString csValue_b = ByteString::FromUnicode(csWValue);

    fdfEncodedData << name_b.GetBuffer(name_b.GetLength());
    name_b.ReleaseBuffer(name_b.GetStringLength());
    fdfEncodedData << "=";
    fdfEncodedData << csValue_b.GetBuffer(csValue_b.GetLength());
    csValue_b.ReleaseBuffer(csValue_b.GetStringLength());
    if (i != pFields->GetCount() - 1)
      fdfEncodedData << "&";
  }

  nBufSize = fdfEncodedData.tellp();
  if (nBufSize == 0)
    return false;

  pBuf = FX_Alloc(uint8_t, nBufSize);
  memcpy(pBuf, fdfEncodedData.str().c_str(), nBufSize);
  return true;
}

ByteString CPDFSDK_InterForm::ExportFieldsToFDFTextBuf(
    const std::vector<CPDF_FormField*>& fields,
    bool bIncludeOrExclude) {
  std::unique_ptr<CFDF_Document> pFDF = m_pInterForm->ExportToFDF(
      m_pFormFillEnv->JS_docGetFilePath(), fields, bIncludeOrExclude, false);

  return pFDF ? pFDF->WriteToString() : ByteString();
}

WideString CPDFSDK_InterForm::GetTemporaryFileName(const WideString& sFileExt) {
  return L"";
}

bool CPDFSDK_InterForm::SubmitForm(const WideString& sDestination,
                                   bool bUrlEncoded) {
  if (sDestination.IsEmpty())
    return false;

  if (!m_pFormFillEnv || !m_pInterForm)
    return false;

  std::unique_ptr<CFDF_Document> pFDFDoc =
      m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);
  if (!pFDFDoc)
    return false;

  ByteString fdfBuffer = pFDFDoc->WriteToString();

  if (fdfBuffer.IsEmpty())
    return false;

  uint8_t* pLocalBuffer = FX_Alloc(uint8_t, fdfBuffer.GetLength());
  memcpy(pLocalBuffer, fdfBuffer.c_str(), fdfBuffer.GetLength());
  uint8_t* pBuffer = pLocalBuffer;

  size_t nBufSize = fdfBuffer.GetLength();
  if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) {
    FX_Free(pLocalBuffer);
    return false;
  }

  m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str());

  if (pBuffer != pLocalBuffer)
    FX_Free(pBuffer);

  FX_Free(pLocalBuffer);

  return true;
}

ByteString CPDFSDK_InterForm::ExportFormToFDFTextBuf() {
  std::unique_ptr<CFDF_Document> pFDF =
      m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false);

  return pFDF ? pFDF->WriteToString() : ByteString();
}

bool CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) {
  ASSERT(action.GetDict());

  CPDF_Dictionary* pActionDict = action.GetDict();
  if (!pActionDict->KeyExist("Fields"))
    return m_pInterForm->ResetForm(true);

  CPDF_ActionFields af(&action);
  uint32_t dwFlags = action.GetFlags();

  std::vector<CPDF_Object*> fieldObjects = af.GetAllFields();
  std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects);
  return m_pInterForm->ResetForm(fields, !(dwFlags & 0x01), true);
}

bool CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) {
  return false;
}

std::vector<CPDF_FormField*> CPDFSDK_InterForm::GetFieldFromObjects(
    const std::vector<CPDF_Object*>& objects) const {
  std::vector<CPDF_FormField*> fields;
  for (CPDF_Object* pObject : objects) {
    if (pObject && pObject->IsString()) {
      WideString csName = pObject->GetUnicodeText();
      CPDF_FormField* pField = m_pInterForm->GetField(0, csName);
      if (pField)
        fields.push_back(pField);
    }
  }
  return fields;
}

int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField,
                                         const WideString& csValue) {
  int nType = pField->GetFieldType();
  if (nType != FIELDTYPE_COMBOBOX && nType != FIELDTYPE_TEXTFIELD)
    return 0;

  if (!OnKeyStrokeCommit(pField, csValue))
    return -1;

  if (!OnValidate(pField, csValue))
    return -1;

  return 1;
}

void CPDFSDK_InterForm::AfterValueChange(CPDF_FormField* pField) {
#ifdef PDF_ENABLE_XFA
  SynchronizeField(pField, false);
#endif  // PDF_ENABLE_XFA
  int nType = pField->GetFieldType();
  if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
    OnCalculate(pField);
    bool bFormatted = false;
    WideString sValue = OnFormat(pField, bFormatted);
    ResetFieldAppearance(pField, bFormatted ? &sValue : nullptr, true);
    UpdateField(pField);
  }
}

int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField,
                                             const WideString& csValue) {
  if (pField->GetFieldType() != FIELDTYPE_LISTBOX)
    return 0;

  if (!OnKeyStrokeCommit(pField, csValue))
    return -1;

  if (!OnValidate(pField, csValue))
    return -1;

  return 1;
}

void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) {
  if (pField->GetFieldType() != FIELDTYPE_LISTBOX)
    return;

  OnCalculate(pField);
  ResetFieldAppearance(pField, nullptr, true);
  UpdateField(pField);
}

void CPDFSDK_InterForm::AfterCheckedStatusChange(CPDF_FormField* pField) {
  int nType = pField->GetFieldType();
  if (nType != FIELDTYPE_CHECKBOX && nType != FIELDTYPE_RADIOBUTTON)
    return;

  OnCalculate(pField);
  UpdateField(pField);
}

int CPDFSDK_InterForm::BeforeFormReset(CPDF_InterForm* pForm) {
  return 0;
}

void CPDFSDK_InterForm::AfterFormReset(CPDF_InterForm* pForm) {
  OnCalculate(nullptr);
}

int CPDFSDK_InterForm::BeforeFormImportData(CPDF_InterForm* pForm) {
  return 0;
}

void CPDFSDK_InterForm::AfterFormImportData(CPDF_InterForm* pForm) {
  OnCalculate(nullptr);
}

bool CPDFSDK_InterForm::IsNeedHighLight(int nFieldType) {
  if (nFieldType < 1 || nFieldType > kNumFieldTypes)
    return false;
  return m_bNeedHightlight[nFieldType - 1];
}

void CPDFSDK_InterForm::RemoveAllHighLight() {
  for (int i = 0; i < kNumFieldTypes; ++i)
    m_bNeedHightlight[i] = false;
}

void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, int nFieldType) {
  if (nFieldType < 0 || nFieldType > kNumFieldTypes)
    return;
  switch (nFieldType) {
    case 0: {
      for (int i = 0; i < kNumFieldTypes; ++i) {
        m_aHighlightColor[i] = clr;
        m_bNeedHightlight[i] = true;
      }
      break;
    }
    default: {
      m_aHighlightColor[nFieldType - 1] = clr;
      m_bNeedHightlight[nFieldType - 1] = true;
      break;
    }
  }
}

FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(int nFieldType) {
  if (nFieldType < 0 || nFieldType > kNumFieldTypes)
    return FXSYS_RGB(255, 255, 255);
  if (nFieldType == 0)
    return m_aHighlightColor[0];
  return m_aHighlightColor[nFieldType - 1];
}
