// Copyright 2014 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 "xfa/fxfa/cxfa_fffield.h"

#include <algorithm>
#include <utility>

#include "third_party/base/check.h"
#include "xfa/fgas/graphics/cfgas_gecolor.h"
#include "xfa/fgas/graphics/cfgas_gepath.h"
#include "xfa/fwl/cfwl_edit.h"
#include "xfa/fwl/cfwl_eventmouse.h"
#include "xfa/fwl/cfwl_messagekey.h"
#include "xfa/fwl/cfwl_messagekillfocus.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_messagemousewheel.h"
#include "xfa/fwl/cfwl_messagesetfocus.h"
#include "xfa/fwl/cfwl_picturebox.h"
#include "xfa/fwl/cfwl_widgetmgr.h"
#include "xfa/fwl/fwl_widgetdef.h"
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/cxfa_ffdocview.h"
#include "xfa/fxfa/cxfa_ffpageview.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/cxfa_fwltheme.h"
#include "xfa/fxfa/cxfa_textlayout.h"
#include "xfa/fxfa/parser/cxfa_border.h"
#include "xfa/fxfa/parser/cxfa_calculate.h"
#include "xfa/fxfa/parser/cxfa_caption.h"
#include "xfa/fxfa/parser/cxfa_margin.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/cxfa_script.h"

CXFA_FFField::CXFA_FFField(CXFA_Node* pNode) : CXFA_FFWidget(pNode) {}

CXFA_FFField::~CXFA_FFField() = default;

CXFA_FFDropDown* CXFA_FFField::AsDropDown() {
  return nullptr;
}

CXFA_FFField* CXFA_FFField::AsField() {
  return this;
}

void CXFA_FFField::Trace(cppgc::Visitor* visitor) const {
  CXFA_FFWidget::Trace(visitor);
  visitor->Trace(m_pNormalWidget);
}

CFX_RectF CXFA_FFField::GetBBox(FocusOption focus) {
  if (focus == kDoNotDrawFocus)
    return CXFA_FFWidget::GetBBox(kDoNotDrawFocus);

  switch (m_pNode->GetFFWidgetType()) {
    case XFA_FFWidgetType::kButton:
    case XFA_FFWidgetType::kCheckButton:
    case XFA_FFWidgetType::kImageEdit:
    case XFA_FFWidgetType::kSignature:
    case XFA_FFWidgetType::kChoiceList:
      return GetRotateMatrix().TransformRect(m_UIRect);
    default:
      return CFX_RectF();
  }
}

void CXFA_FFField::RenderWidget(CFGAS_GEGraphics* pGS,
                                const CFX_Matrix& matrix,
                                HighlightOption highlight) {
  if (!HasVisibleStatus())
    return;

  CFX_Matrix mtRotate = GetRotateMatrix();
  mtRotate.Concat(matrix);

  CXFA_FFWidget::RenderWidget(pGS, mtRotate, highlight);
  DrawBorder(pGS, m_pNode->GetUIBorder(), m_UIRect, mtRotate);
  RenderCaption(pGS, &mtRotate);
  DrawHighlight(pGS, &mtRotate, highlight, kSquareShape);

  CFX_RectF rtWidget = GetNormalWidget()->GetWidgetRect();
  CFX_Matrix mt(1, 0, 0, 1, rtWidget.left, rtWidget.top);
  mt.Concat(mtRotate);
  GetApp()->GetFWLWidgetMgr()->OnDrawWidget(GetNormalWidget(), pGS, mt);
}

void CXFA_FFField::DrawHighlight(CFGAS_GEGraphics* pGS,
                                 CFX_Matrix* pMatrix,
                                 HighlightOption highlight,
                                 ShapeOption shape) {
  if (highlight == kNoHighlight)
    return;

  if (m_UIRect.IsEmpty() || !GetDoc()->GetXFADoc()->IsInteractive() ||
      !m_pNode->IsOpenAccess()) {
    return;
  }
  pGS->SetFillColor(CFGAS_GEColor(GetDoc()->GetHighlightColor()));
  CFGAS_GEPath path;
  if (shape == kRoundShape)
    path.AddEllipse(m_UIRect);
  else
    path.AddRectangle(m_UIRect.left, m_UIRect.top, m_UIRect.width,
                      m_UIRect.height);

  pGS->FillPath(&path, CFX_FillRenderOptions::FillType::kWinding, pMatrix);
}

void CXFA_FFField::DrawFocus(CFGAS_GEGraphics* pGS, CFX_Matrix* pMatrix) {
  if (!GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Focused))
    return;

  pGS->SetStrokeColor(CFGAS_GEColor(0xFF000000));

  static constexpr float kDashPattern[2] = {1, 1};
  pGS->SetLineDash(0.0f, kDashPattern);
  pGS->SetLineWidth(0);

  CFGAS_GEPath path;
  path.AddRectangle(m_UIRect.left, m_UIRect.top, m_UIRect.width,
                    m_UIRect.height);
  pGS->StrokePath(&path, pMatrix);
}

CFWL_Widget* CXFA_FFField::GetNormalWidget() {
  return m_pNormalWidget;
}

const CFWL_Widget* CXFA_FFField::GetNormalWidget() const {
  return m_pNormalWidget;
}

void CXFA_FFField::SetNormalWidget(CFWL_Widget* widget) {
  m_pNormalWidget = widget;
}

bool CXFA_FFField::IsLoaded() {
  return GetNormalWidget() && CXFA_FFWidget::IsLoaded();
}

bool CXFA_FFField::LoadWidget() {
  m_pNode->LoadCaption(GetDoc());
  PerformLayout();
  return true;
}

void CXFA_FFField::SetEditScrollOffset() {
  XFA_FFWidgetType eType = m_pNode->GetFFWidgetType();
  if (eType != XFA_FFWidgetType::kTextEdit &&
      eType != XFA_FFWidgetType::kNumericEdit &&
      eType != XFA_FFWidgetType::kPasswordEdit) {
    return;
  }

  float fScrollOffset = 0;
  CXFA_ContentLayoutItem* pItem = GetLayoutItem()->GetPrev();
  CXFA_FFField* pPrev = pItem ? ToField(pItem->GetFFWidget()) : nullptr;
  if (pPrev)
    fScrollOffset = -(m_pNode->GetUIMargin().top);

  while (pPrev) {
    fScrollOffset += pPrev->m_UIRect.height;
    pItem = pPrev->GetLayoutItem()->GetPrev();
    pPrev = pItem ? ToField(pItem->GetFFWidget()) : nullptr;
  }
  static_cast<CFWL_Edit*>(GetNormalWidget())->SetScrollOffset(fScrollOffset);
}

bool CXFA_FFField::PerformLayout() {
  CXFA_FFWidget::PerformLayout();
  CapPlacement();
  LayoutCaption();
  SetFWLRect();
  SetEditScrollOffset();
  if (GetNormalWidget())
    GetNormalWidget()->Update();
  return true;
}

void CXFA_FFField::CapPlacement() {
  CFX_RectF rtWidget = GetRectWithoutRotate();
  CXFA_Margin* margin = m_pNode->GetMarginIfExists();
  if (margin) {
    CXFA_ContentLayoutItem* pItem = GetLayoutItem();
    float fLeftInset = margin->GetLeftInset();
    float fRightInset = margin->GetRightInset();
    float fTopInset = margin->GetTopInset();
    float fBottomInset = margin->GetBottomInset();
    if (!pItem->GetPrev() && !pItem->GetNext()) {
      rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
    } else {
      if (!pItem->GetPrev())
        rtWidget.Deflate(fLeftInset, fTopInset, fRightInset, 0);
      else if (!pItem->GetNext())
        rtWidget.Deflate(fLeftInset, 0, fRightInset, fBottomInset);
      else
        rtWidget.Deflate(fLeftInset, 0, fRightInset, 0);
    }
  }

  XFA_AttributeValue iCapPlacement = XFA_AttributeValue::Unknown;
  float fCapReserve = 0;
  CXFA_Caption* caption = m_pNode->GetCaptionIfExists();
  if (caption && !caption->IsHidden()) {
    iCapPlacement = caption->GetPlacementType();
    if ((iCapPlacement == XFA_AttributeValue::Top &&
         GetLayoutItem()->GetPrev()) ||
        (iCapPlacement == XFA_AttributeValue::Bottom &&
         GetLayoutItem()->GetNext())) {
      m_CaptionRect = CFX_RectF();
    } else {
      fCapReserve = caption->GetReserve();
      if (iCapPlacement == XFA_AttributeValue::Top ||
          iCapPlacement == XFA_AttributeValue::Bottom) {
        fCapReserve = std::min(fCapReserve, rtWidget.height);
      } else {
        fCapReserve = std::min(fCapReserve, rtWidget.width);
      }
      CXFA_ContentLayoutItem* pItem = GetLayoutItem();
      if (!pItem->GetPrev() && !pItem->GetNext()) {
        m_CaptionRect = rtWidget;
      } else {
        pItem = pItem->GetFirst();
        m_CaptionRect = pItem->GetRect(false);
        pItem = pItem->GetNext();
        while (pItem) {
          m_CaptionRect.height += pItem->GetRect(false).Height();
          pItem = pItem->GetNext();
        }
        XFA_RectWithoutMargin(&m_CaptionRect, margin);
      }

      CXFA_TextLayout* pCapTextLayout = m_pNode->GetCaptionTextLayout();
      if (fCapReserve <= 0 && pCapTextLayout) {
        CFX_SizeF minSize;
        CFX_SizeF maxSize;
        CFX_SizeF size = pCapTextLayout->CalcSize(minSize, maxSize);
        if (iCapPlacement == XFA_AttributeValue::Top ||
            iCapPlacement == XFA_AttributeValue::Bottom) {
          fCapReserve = size.height;
        } else {
          fCapReserve = size.width;
        }
      }
    }
  }

  m_UIRect = rtWidget;
  CXFA_Margin* capMargin = caption ? caption->GetMarginIfExists() : nullptr;
  switch (iCapPlacement) {
    case XFA_AttributeValue::Left: {
      m_CaptionRect.width = fCapReserve;
      CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement);
      m_UIRect.width -= fCapReserve;
      m_UIRect.left += fCapReserve;
      break;
    }
    case XFA_AttributeValue::Top: {
      m_CaptionRect.height = fCapReserve;
      CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement);
      m_UIRect.top += fCapReserve;
      m_UIRect.height -= fCapReserve;
      break;
    }
    case XFA_AttributeValue::Right: {
      m_CaptionRect.left = m_CaptionRect.right() - fCapReserve;
      m_CaptionRect.width = fCapReserve;
      CapLeftRightPlacement(capMargin, rtWidget, iCapPlacement);
      m_UIRect.width -= fCapReserve;
      break;
    }
    case XFA_AttributeValue::Bottom: {
      m_CaptionRect.top = m_CaptionRect.bottom() - fCapReserve;
      m_CaptionRect.height = fCapReserve;
      CapTopBottomPlacement(capMargin, rtWidget, iCapPlacement);
      m_UIRect.height -= fCapReserve;
      break;
    }
    case XFA_AttributeValue::Inline:
      break;
    default:
      break;
  }

  CXFA_Border* borderUI = m_pNode->GetUIBorder();
  if (borderUI) {
    CXFA_Margin* borderMargin = borderUI->GetMarginIfExists();
    XFA_RectWithoutMargin(&m_UIRect, borderMargin);
  }
  m_UIRect.Normalize();
}

void CXFA_FFField::CapTopBottomPlacement(const CXFA_Margin* margin,
                                         const CFX_RectF& rtWidget,
                                         XFA_AttributeValue iCapPlacement) {
  CFX_RectF rtUIMargin = m_pNode->GetUIMargin();
  m_CaptionRect.left += rtUIMargin.left;
  if (margin) {
    XFA_RectWithoutMargin(&m_CaptionRect, margin);
    if (m_CaptionRect.height < 0)
      m_CaptionRect.top += m_CaptionRect.height;
  }

  float fWidth = rtUIMargin.left + rtUIMargin.width;
  float fHeight = m_CaptionRect.height + rtUIMargin.top + rtUIMargin.height;
  if (fWidth > rtWidget.width)
    m_UIRect.width += fWidth - rtWidget.width;

  if (fHeight == XFA_DEFAULTUI_HEIGHT && m_UIRect.height < XFA_MINUI_HEIGHT) {
    m_UIRect.height = XFA_MINUI_HEIGHT;
    m_CaptionRect.top += rtUIMargin.top + rtUIMargin.height;
  } else if (fHeight > rtWidget.height) {
    m_UIRect.height += fHeight - rtWidget.height;
    if (iCapPlacement == XFA_AttributeValue::Bottom)
      m_CaptionRect.top += fHeight - rtWidget.height;
  }
}

void CXFA_FFField::CapLeftRightPlacement(const CXFA_Margin* margin,
                                         const CFX_RectF& rtWidget,
                                         XFA_AttributeValue iCapPlacement) {
  CFX_RectF rtUIMargin = m_pNode->GetUIMargin();
  m_CaptionRect.top += rtUIMargin.top;
  m_CaptionRect.height -= rtUIMargin.top;
  if (margin) {
    XFA_RectWithoutMargin(&m_CaptionRect, margin);
    if (m_CaptionRect.height < 0)
      m_CaptionRect.top += m_CaptionRect.height;
  }

  float fWidth = m_CaptionRect.width + rtUIMargin.left + rtUIMargin.width;
  float fHeight = rtUIMargin.top + rtUIMargin.height;
  if (fWidth > rtWidget.width) {
    m_UIRect.width += fWidth - rtWidget.width;
    if (iCapPlacement == XFA_AttributeValue::Right)
      m_CaptionRect.left += fWidth - rtWidget.width;
  }

  if (fHeight == XFA_DEFAULTUI_HEIGHT && m_UIRect.height < XFA_MINUI_HEIGHT) {
    m_UIRect.height = XFA_MINUI_HEIGHT;
    m_CaptionRect.top += rtUIMargin.top + rtUIMargin.height;
  } else if (fHeight > rtWidget.height) {
    m_UIRect.height += fHeight - rtWidget.height;
  }
}

void CXFA_FFField::UpdateFWL() {
  if (GetNormalWidget())
    GetNormalWidget()->Update();
}

uint32_t CXFA_FFField::UpdateUIProperty() {
  CXFA_Node* pUiNode = m_pNode->GetUIChildNode();
  if (pUiNode && pUiNode->GetElementType() == XFA_Element::DefaultUi)
    return FWL_STYLEEXT_EDT_ReadOnly;
  return 0;
}

void CXFA_FFField::SetFWLRect() {
  if (!GetNormalWidget())
    return;

  CFX_RectF rtUi = m_UIRect;
  rtUi.width = std::max(rtUi.width, 1.0f);
  if (!GetDoc()->GetXFADoc()->IsInteractive()) {
    float fFontSize = m_pNode->GetFontSize();
    rtUi.height = std::max(rtUi.height, fFontSize);
  }
  GetNormalWidget()->SetWidgetRect(rtUi);
}

bool CXFA_FFField::OnMouseEnter() {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::Enter);
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnMouseExit() {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::Leave);
  SendMessageToFWLWidget(&msg);
  return true;
}

CFX_PointF CXFA_FFField::FWLToClient(const CFX_PointF& point) {
  return GetNormalWidget()
             ? point - GetNormalWidget()->GetWidgetRect().TopLeft()
             : point;
}

bool CXFA_FFField::AcceptsFocusOnButtonDown(uint32_t dwFlags,
                                            const CFX_PointF& point,
                                            FWL_MouseCommand command) {
  if (!GetNormalWidget())
    return false;
  if (!m_pNode->IsOpenAccess() || !GetDoc()->GetXFADoc()->IsInteractive())
    return false;
  if (!PtInActiveRect(point))
    return false;

  return true;
}

bool CXFA_FFField::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
  SetButtonDown(true);
  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::LeftButtonDown,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetNormalWidget())
    return false;
  if (!IsButtonDown())
    return false;

  SetButtonDown(false);

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::LeftButtonUp,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::LeftButtonDblClk,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::Move, dwFlags,
                        FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnMouseWheel(uint32_t dwFlags,
                                const CFX_PointF& point,
                                const CFX_Vector& delta) {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouseWheel msg(GetNormalWidget(), FWLToClient(point), delta);
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
  SetButtonDown(true);

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::RightButtonDown,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetNormalWidget())
    return false;
  if (!IsButtonDown())
    return false;

  SetButtonDown(false);
  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::RightButtonUp,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
  if (!GetNormalWidget())
    return false;

  CFWL_MessageMouse msg(GetNormalWidget(), FWL_MouseCommand::RightButtonDblClk,
                        dwFlags, FWLToClient(point));
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnSetFocus(CXFA_FFWidget* pOldWidget) {
  if (!CXFA_FFWidget::OnSetFocus(pOldWidget))
    return false;

  if (!GetNormalWidget())
    return false;

  CFWL_MessageSetFocus msg(nullptr, GetNormalWidget());
  SendMessageToFWLWidget(&msg);
  GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused);
  InvalidateRect();

  return true;
}

bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) {
  if (GetNormalWidget()) {
    CFWL_MessageKillFocus msg(nullptr, GetNormalWidget());
    SendMessageToFWLWidget(&msg);
    GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
    InvalidateRect();
  }
  return pNewWidget && CXFA_FFWidget::OnKillFocus(pNewWidget);
}

bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
  if (!GetNormalWidget() || !GetDoc()->GetXFADoc()->IsInteractive())
    return false;

  CFWL_MessageKey msg(GetNormalWidget(), CFWL_MessageKey::Type::kKeyDown,
                      dwFlags, dwKeyCode);
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
  if (!GetNormalWidget() || !GetDoc()->GetXFADoc()->IsInteractive())
    return false;

  CFWL_MessageKey msg(GetNormalWidget(), CFWL_MessageKey::Type::kKeyUp, dwFlags,
                      dwKeyCode);
  SendMessageToFWLWidget(&msg);
  return true;
}

bool CXFA_FFField::OnChar(uint32_t dwChar, uint32_t dwFlags) {
  if (!GetDoc()->GetXFADoc()->IsInteractive())
    return false;
  if (dwChar == XFA_FWL_VKEY_Tab)
    return true;
  if (!GetNormalWidget())
    return false;
  if (!m_pNode->IsOpenAccess())
    return false;

  CFWL_MessageKey msg(GetNormalWidget(), CFWL_MessageKey::Type::kChar, dwFlags,
                      dwChar);
  SendMessageToFWLWidget(&msg);
  return true;
}

FWL_WidgetHit CXFA_FFField::HitTest(const CFX_PointF& point) {
  auto* pNorm = GetNormalWidget();
  if (pNorm && pNorm->HitTest(FWLToClient(point)) != FWL_WidgetHit::Unknown)
    return FWL_WidgetHit::Client;
  if (!GetRectWithoutRotate().Contains(point))
    return FWL_WidgetHit::Unknown;
  if (m_CaptionRect.Contains(point))
    return FWL_WidgetHit::Titlebar;
  return FWL_WidgetHit::Border;
}

bool CXFA_FFField::PtInActiveRect(const CFX_PointF& point) {
  return GetNormalWidget() &&
         GetNormalWidget()->GetWidgetRect().Contains(point);
}

void CXFA_FFField::LayoutCaption() {
  CXFA_TextLayout* pCapTextLayout = m_pNode->GetCaptionTextLayout();
  if (!pCapTextLayout)
    return;

  float fHeight = pCapTextLayout->Layout(m_CaptionRect.Size());
  m_CaptionRect.height = std::max(m_CaptionRect.height, fHeight);
}

void CXFA_FFField::RenderCaption(CFGAS_GEGraphics* pGS, CFX_Matrix* pMatrix) {
  CXFA_TextLayout* pCapTextLayout = m_pNode->GetCaptionTextLayout();
  if (!pCapTextLayout)
    return;

  CXFA_Caption* caption = m_pNode->GetCaptionIfExists();
  if (!caption || !caption->IsVisible())
    return;

  if (!pCapTextLayout->IsLoaded())
    pCapTextLayout->Layout(m_CaptionRect.Size());

  CFX_RectF rtClip = m_CaptionRect;
  rtClip.Intersect(GetRectWithoutRotate());
  CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
  CFX_Matrix mt(1, 0, 0, 1, m_CaptionRect.left, m_CaptionRect.top);
  if (pMatrix) {
    rtClip = pMatrix->TransformRect(rtClip);
    mt.Concat(*pMatrix);
  }
  pCapTextLayout->DrawString(pRenderDevice, mt, rtClip, 0);
}

bool CXFA_FFField::ProcessCommittedData() {
  if (!m_pNode->IsOpenAccess())
    return false;
  if (!IsDataChanged())
    return false;

  m_pDocView->SetChangeMark();
  m_pDocView->AddValidateNode(m_pNode.Get());

  if (CalculateOverride() != 1)
    return false;
  return CommitData();
}

int32_t CXFA_FFField::CalculateOverride() {
  CXFA_Node* exclNode = m_pNode->GetExclGroupIfExists();
  if (!exclNode || !exclNode->IsWidgetReady())
    return CalculateNode(m_pNode.Get());
  if (CalculateNode(exclNode) == 0)
    return 0;

  CXFA_Node* pNode = exclNode->GetExclGroupFirstMember();
  if (!pNode)
    return 1;

  while (pNode) {
    if (!pNode->IsWidgetReady())
      return 1;
    if (CalculateNode(pNode) == 0)
      return 0;

    pNode = pNode->GetExclGroupNextMember(pNode);
  }
  return 1;
}

int32_t CXFA_FFField::CalculateNode(CXFA_Node* pNode) {
  CXFA_Calculate* calc = pNode->GetCalculateIfExists();
  if (!calc)
    return 1;

  XFA_VERSION version = GetDoc()->GetXFADoc()->GetCurVersionMode();
  switch (calc->GetOverride()) {
    case XFA_AttributeValue::Error: {
      if (version <= XFA_VERSION_204)
        return 1;

      IXFA_AppProvider* pAppProvider = GetAppProvider();
      if (pAppProvider) {
        pAppProvider->MsgBox(
            WideString::FromASCII("You are not allowed to modify this field."),
            WideString::FromASCII("Calculate Override"),
            static_cast<uint32_t>(AlertIcon::kWarning),
            static_cast<uint32_t>(AlertButton::kOK));
      }
      return 0;
    }
    case XFA_AttributeValue::Warning: {
      if (version <= XFA_VERSION_204) {
        CXFA_Script* script = calc->GetScriptIfExists();
        if (!script || script->GetExpression().IsEmpty())
          return 1;
      }

      if (pNode->IsUserInteractive())
        return 1;

      IXFA_AppProvider* pAppProvider = GetAppProvider();
      if (!pAppProvider)
        return 0;

      WideString wsMessage = calc->GetMessageText();
      if (!wsMessage.IsEmpty())
        wsMessage += L"\r\n";
      wsMessage +=
          WideString::FromASCII("Are you sure you want to modify this field?");

      if (pAppProvider->MsgBox(wsMessage,
                               WideString::FromASCII("Calculate Override"),
                               static_cast<uint32_t>(AlertIcon::kWarning),
                               static_cast<uint32_t>(AlertButton::kYesNo)) ==
          static_cast<uint32_t>(AlertReturn::kYes)) {
        pNode->SetFlag(XFA_NodeFlag_UserInteractive);
        return 1;
      }
      return 0;
    }
    case XFA_AttributeValue::Ignore:
      return 0;
    case XFA_AttributeValue::Disabled:
      pNode->SetFlag(XFA_NodeFlag_UserInteractive);
      return 1;
    default:
      return 1;
  }
}

bool CXFA_FFField::CommitData() {
  return false;
}

bool CXFA_FFField::IsDataChanged() {
  return false;
}

void CXFA_FFField::SendMessageToFWLWidget(CFWL_Message* pMessage) {
  DCHECK(pMessage);
  GetApp()->GetFWLWidgetMgr()->OnProcessMessageToForm(pMessage);
}

void CXFA_FFField::OnProcessMessage(CFWL_Message* pMessage) {}

void CXFA_FFField::OnProcessEvent(CFWL_Event* pEvent) {
  switch (pEvent->GetType()) {
    case CFWL_Event::Type::Mouse: {
      CFWL_EventMouse* event = static_cast<CFWL_EventMouse*>(pEvent);
      if (event->m_dwCmd == FWL_MouseCommand::Enter) {
        CXFA_EventParam eParam;
        eParam.m_eType = XFA_EVENT_MouseEnter;
        eParam.m_pTarget = m_pNode.Get();
        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::MouseEnter,
                              &eParam);
      } else if (event->m_dwCmd == FWL_MouseCommand::Leave) {
        CXFA_EventParam eParam;
        eParam.m_eType = XFA_EVENT_MouseExit;
        eParam.m_pTarget = m_pNode.Get();
        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::MouseExit,
                              &eParam);
      } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonDown) {
        CXFA_EventParam eParam;
        eParam.m_eType = XFA_EVENT_MouseDown;
        eParam.m_pTarget = m_pNode.Get();
        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::MouseDown,
                              &eParam);
      } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonUp) {
        CXFA_EventParam eParam;
        eParam.m_eType = XFA_EVENT_MouseUp;
        eParam.m_pTarget = m_pNode.Get();
        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::MouseUp,
                              &eParam);
      }
      break;
    }
    case CFWL_Event::Type::Click: {
      CXFA_EventParam eParam;
      eParam.m_eType = XFA_EVENT_Click;
      eParam.m_pTarget = m_pNode.Get();
      m_pNode->ProcessEvent(GetDocView(), XFA_AttributeValue::Click, &eParam);
      break;
    }
    default:
      break;
  }
}

void CXFA_FFField::OnDrawWidget(CFGAS_GEGraphics* pGraphics,
                                const CFX_Matrix& matrix) {}
