// 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 <map>

#include "fpdfsdk/include/pdfwindow/PWL_ScrollBar.h"
#include "fpdfsdk/include/pdfwindow/PWL_Utils.h"
#include "fpdfsdk/include/pdfwindow/PWL_Wnd.h"

static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
  // Leak the object at shutdown.
  static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
  return *timeMap;
}

CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
                       IFX_SystemHandler* pSystemHandler)
    : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
  ASSERT(m_pAttached);
  ASSERT(m_pSystemHandler);
}

CPWL_Timer::~CPWL_Timer() {
  KillPWLTimer();
}

int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
  if (m_nTimerID != 0)
    KillPWLTimer();
  m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);

  GetPWLTimeMap()[m_nTimerID] = this;
  return m_nTimerID;
}

void CPWL_Timer::KillPWLTimer() {
  if (m_nTimerID == 0)
    return;

  m_pSystemHandler->KillTimer(m_nTimerID);
  GetPWLTimeMap().erase(m_nTimerID);
  m_nTimerID = 0;
}

void CPWL_Timer::TimerProc(int32_t idEvent) {
  auto it = GetPWLTimeMap().find(idEvent);
  if (it == GetPWLTimeMap().end())
    return;

  CPWL_Timer* pTimer = it->second;
  if (pTimer->m_pAttached)
    pTimer->m_pAttached->TimerProc();
}

CPWL_TimerHandler::CPWL_TimerHandler() : m_pTimer(NULL) {}

CPWL_TimerHandler::~CPWL_TimerHandler() {
  delete m_pTimer;
}

void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
  if (!m_pTimer)
    m_pTimer = new CPWL_Timer(this, GetSystemHandler());

  if (m_pTimer)
    m_pTimer->SetPWLTimer(nElapse);
}

void CPWL_TimerHandler::EndTimer() {
  if (m_pTimer)
    m_pTimer->KillPWLTimer();
}

void CPWL_TimerHandler::TimerProc() {}

class CPWL_MsgControl {
  friend class CPWL_Wnd;

 public:
  explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
    m_pCreatedWnd = pWnd;
    Default();
  }

  ~CPWL_MsgControl() {
    Default();
  }

  void Default() {
    m_aMousePath.RemoveAll();
    m_aKeyboardPath.RemoveAll();
    m_pMainMouseWnd = NULL;
    m_pMainKeyboardWnd = NULL;
  }

  FX_BOOL IsWndCreated(const CPWL_Wnd* pWnd) const {
    return m_pCreatedWnd == pWnd;
  }

  FX_BOOL IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
    return pWnd == m_pMainMouseWnd;
  }

  FX_BOOL IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
    if (pWnd) {
      for (int32_t i = 0, sz = m_aMousePath.GetSize(); i < sz; i++) {
        if (m_aMousePath.GetAt(i) == pWnd)
          return TRUE;
      }
    }

    return FALSE;
  }

  FX_BOOL IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    return pWnd == m_pMainKeyboardWnd;
  }

  FX_BOOL IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
    if (pWnd) {
      for (int32_t i = 0, sz = m_aKeyboardPath.GetSize(); i < sz; i++) {
        if (m_aKeyboardPath.GetAt(i) == pWnd)
          return TRUE;
      }
    }

    return FALSE;
  }

  void SetFocus(CPWL_Wnd* pWnd) {
    m_aKeyboardPath.RemoveAll();

    if (pWnd) {
      m_pMainKeyboardWnd = pWnd;

      CPWL_Wnd* pParent = pWnd;
      while (pParent) {
        m_aKeyboardPath.Add(pParent);
        pParent = pParent->GetParentWindow();
      }

      pWnd->OnSetFocus();
    }
  }

  void KillFocus() {
    if (m_aKeyboardPath.GetSize() > 0)
      if (CPWL_Wnd* pWnd = m_aKeyboardPath.GetAt(0))
        pWnd->OnKillFocus();

    m_pMainKeyboardWnd = NULL;
    m_aKeyboardPath.RemoveAll();
  }

  void SetCapture(CPWL_Wnd* pWnd) {
    m_aMousePath.RemoveAll();

    if (pWnd) {
      m_pMainMouseWnd = pWnd;

      CPWL_Wnd* pParent = pWnd;
      while (pParent) {
        m_aMousePath.Add(pParent);
        pParent = pParent->GetParentWindow();
      }
    }
  }

  void ReleaseCapture() {
    m_pMainMouseWnd = NULL;
    m_aMousePath.RemoveAll();
  }

 private:
  CFX_ArrayTemplate<CPWL_Wnd*> m_aMousePath;
  CFX_ArrayTemplate<CPWL_Wnd*> m_aKeyboardPath;
  CPWL_Wnd* m_pCreatedWnd;
  CPWL_Wnd* m_pMainMouseWnd;
  CPWL_Wnd* m_pMainKeyboardWnd;
};

CPWL_Wnd::CPWL_Wnd()
    : m_pVScrollBar(NULL),
      m_rcWindow(),
      m_rcClip(),
      m_bCreated(FALSE),
      m_bVisible(FALSE),
      m_bNotifying(FALSE),
      m_bEnabled(TRUE) {}

CPWL_Wnd::~CPWL_Wnd() {
  ASSERT(m_bCreated == FALSE);
}

CFX_ByteString CPWL_Wnd::GetClassName() const {
  return "CPWL_Wnd";
}

void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
  if (!IsValid()) {
    m_sPrivateParam = cp;

    OnCreate(m_sPrivateParam);

    m_sPrivateParam.rcRectWnd.Normalize();
    m_rcWindow = m_sPrivateParam.rcRectWnd;
    m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);

    CreateMsgControl();

    if (m_sPrivateParam.pParentWnd)
      m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);

    PWL_CREATEPARAM ccp = m_sPrivateParam;

    ccp.dwFlags &= 0xFFFF0000L;  // remove sub styles
    ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0);

    CreateScrollBar(ccp);
    CreateChildWnd(ccp);

    m_bVisible = HasFlag(PWS_VISIBLE);

    OnCreated();

    RePosChildWnd();
    m_bCreated = TRUE;
  }
}

void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}

void CPWL_Wnd::OnCreated() {}

void CPWL_Wnd::OnDestroy() {}

void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
  if (m_sPrivateParam.pFocusHandler == handler)
    m_sPrivateParam.pFocusHandler = nullptr;
}

void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
  if (m_sPrivateParam.pProvider == provider)
    m_sPrivateParam.pProvider = nullptr;
}

void CPWL_Wnd::Destroy() {
  KillFocus();

  OnDestroy();

  if (m_bCreated) {
    for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
      if (CPWL_Wnd* pChild = m_aChildren[i]) {
        pChild->Destroy();
        delete pChild;
        pChild = NULL;
      }
    }

    if (m_sPrivateParam.pParentWnd)
      m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
    m_bCreated = FALSE;
  }

  DestroyMsgControl();

  FXSYS_memset(&m_sPrivateParam, 0, sizeof(PWL_CREATEPARAM));
  m_aChildren.RemoveAll();
  m_pVScrollBar = NULL;
}

void CPWL_Wnd::Move(const CPDF_Rect& rcNew, FX_BOOL bReset, FX_BOOL bRefresh) {
  if (IsValid()) {
    CPDF_Rect rcOld = GetWindowRect();

    m_rcWindow = rcNew;
    m_rcWindow.Normalize();

    if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
        rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
      if (bReset) {
        RePosChildWnd();
      }
    }
    if (bRefresh) {
      InvalidateRectMove(rcOld, rcNew);
    }

    m_sPrivateParam.rcRectWnd = m_rcWindow;
  }
}

void CPWL_Wnd::InvalidateRectMove(const CPDF_Rect& rcOld,
                                  const CPDF_Rect& rcNew) {
  CPDF_Rect rcUnion = rcOld;
  rcUnion.Union(rcNew);

  InvalidateRect(&rcUnion);
}

void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  if (IsValid() && IsVisible()) {
    GetThisAppearanceStream(sAppStream);
    GetChildAppearanceStream(sAppStream);
  }
}

// if don't set,Get default apperance stream
void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  CPDF_Rect rectWnd = GetWindowRect();
  if (!rectWnd.IsEmpty()) {
    CFX_ByteTextBuf sThis;

    if (HasFlag(PWS_BACKGROUND))
      sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());

    if (HasFlag(PWS_BORDER)) {
      sThis << CPWL_Utils::GetBorderAppStream(
          rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
          GetBorderLeftTopColor(GetBorderStyle()),
          GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
          GetBorderDash());
    }

    sAppStream << sThis;
  }
}

void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      pChild->GetAppearanceStream(sAppStream);
    }
  }
}

void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
                              CFX_Matrix* pUser2Device) {
  if (IsValid() && IsVisible()) {
    DrawThisAppearance(pDevice, pUser2Device);
    DrawChildAppearance(pDevice, pUser2Device);
  }
}

void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                  CFX_Matrix* pUser2Device) {
  CPDF_Rect rectWnd = GetWindowRect();
  if (!rectWnd.IsEmpty()) {
    if (HasFlag(PWS_BACKGROUND)) {
      CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
          rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
      CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
                               GetBackgroundColor(), GetTransparency());
    }

    if (HasFlag(PWS_BORDER))
      CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd,
                             (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
                             GetBorderLeftTopColor(GetBorderStyle()),
                             GetBorderRightBottomColor(GetBorderStyle()),
                             GetBorderStyle(), GetTransparency());
  }
}

void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
                                   CFX_Matrix* pUser2Device) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      CFX_Matrix mt = pChild->GetChildMatrix();
      if (mt.IsIdentity()) {
        pChild->DrawAppearance(pDevice, pUser2Device);
      } else {
        mt.Concat(*pUser2Device);
        pChild->DrawAppearance(pDevice, &mt);
      }
    }
  }
}

void CPWL_Wnd::InvalidateRect(CPDF_Rect* pRect) {
  if (IsValid()) {
    CPDF_Rect rcRefresh = pRect ? *pRect : GetWindowRect();

    if (!HasFlag(PWS_NOREFRESHCLIP)) {
      CPDF_Rect rcClip = GetClipRect();
      if (!rcClip.IsEmpty()) {
        rcRefresh.Intersect(rcClip);
      }
    }

    FX_RECT rcWin = PWLtoWnd(rcRefresh);
    rcWin.left -= PWL_INVALIDATE_INFLATE;
    rcWin.top -= PWL_INVALIDATE_INFLATE;
    rcWin.right += PWL_INVALIDATE_INFLATE;
    rcWin.bottom += PWL_INVALIDATE_INFLATE;

    if (IFX_SystemHandler* pSH = GetSystemHandler()) {
      if (FX_HWND hWnd = GetAttachedHWnd()) {
        pSH->InvalidateRect(hWnd, rcWin);
      }
    }
  }
}

#define PWL_IMPLEMENT_KEY_METHOD(key_method_name)                      \
  FX_BOOL CPWL_Wnd::key_method_name(FX_WORD nChar, FX_DWORD nFlag) {   \
    if (IsValid() && IsVisible() && IsEnabled()) {                     \
      if (IsWndCaptureKeyboard(this)) {                                \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) { \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {               \
            if (IsWndCaptureKeyboard(pChild)) {                        \
              return pChild->key_method_name(nChar, nFlag);            \
            }                                                          \
          }                                                            \
        }                                                              \
      }                                                                \
    }                                                                  \
    return FALSE;                                                      \
  }

#define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)                        \
  FX_BOOL CPWL_Wnd::mouse_method_name(const CPDF_Point& point,               \
                                      FX_DWORD nFlag) {                      \
    if (IsValid() && IsVisible() && IsEnabled()) {                           \
      if (IsWndCaptureMouse(this)) {                                         \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
            if (IsWndCaptureMouse(pChild)) {                                 \
              return pChild->mouse_method_name(pChild->ParentToChild(point), \
                                               nFlag);                       \
            }                                                                \
          }                                                                  \
        }                                                                    \
        SetCursor();                                                         \
      } else {                                                               \
        for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {       \
          if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {                     \
            if (pChild->WndHitTest(pChild->ParentToChild(point))) {          \
              return pChild->mouse_method_name(pChild->ParentToChild(point), \
                                               nFlag);                       \
            }                                                                \
          }                                                                  \
        }                                                                    \
        if (WndHitTest(point))                                               \
          SetCursor();                                                       \
      }                                                                      \
    }                                                                        \
    return FALSE;                                                            \
  }

PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
PWL_IMPLEMENT_KEY_METHOD(OnKeyUp)
PWL_IMPLEMENT_KEY_METHOD(OnChar)

PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnMButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)

FX_BOOL CPWL_Wnd::OnMouseWheel(short zDelta,
                               const CPDF_Point& point,
                               FX_DWORD nFlag) {
  if (IsValid() && IsVisible() && IsEnabled()) {
    SetCursor();
    if (IsWndCaptureKeyboard(this)) {
      for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
        if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
          if (IsWndCaptureKeyboard(pChild)) {
            return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point),
                                        nFlag);
          }
        }
      }
    }
  }
  return FALSE;
}

void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
  m_aChildren.Add(pWnd);
}

void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
  for (int32_t i = m_aChildren.GetSize() - 1; i >= 0; i--) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      if (pChild == pWnd) {
        m_aChildren.RemoveAt(i);
        break;
      }
    }
  }
}

void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
                        FX_DWORD msg,
                        intptr_t wParam,
                        intptr_t lParam) {
  switch (msg) {
    case PNM_ADDCHILD:
      AddChild(pWnd);
      break;
    case PNM_REMOVECHILD:
      RemoveChild(pWnd);
      break;
    default:
      break;
  }
}

FX_BOOL CPWL_Wnd::IsValid() const {
  return m_bCreated;
}

const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
  return m_sPrivateParam;
}

CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
  return m_sPrivateParam.pParentWnd;
}

CPDF_Rect CPWL_Wnd::GetWindowRect() const {
  return m_rcWindow;
}

CPDF_Rect CPWL_Wnd::GetClientRect() const {
  CPDF_Rect rcWindow = GetWindowRect();
  CPDF_Rect rcClient = CPWL_Utils::DeflateRect(
      rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
  if (CPWL_ScrollBar* pVSB = GetVScrollBar())
    rcClient.right -= pVSB->GetScrollBarWidth();

  rcClient.Normalize();
  return rcWindow.Contains(rcClient) ? rcClient : CPDF_Rect();
}

CPDF_Point CPWL_Wnd::GetCenterPoint() const {
  CPDF_Rect rcClient = GetClientRect();
  return CPDF_Point((rcClient.left + rcClient.right) * 0.5f,
                    (rcClient.top + rcClient.bottom) * 0.5f);
}

FX_BOOL CPWL_Wnd::HasFlag(FX_DWORD dwFlags) const {
  return (m_sPrivateParam.dwFlags & dwFlags) != 0;
}

void CPWL_Wnd::RemoveFlag(FX_DWORD dwFlags) {
  m_sPrivateParam.dwFlags &= ~dwFlags;
}

void CPWL_Wnd::AddFlag(FX_DWORD dwFlags) {
  m_sPrivateParam.dwFlags |= dwFlags;
}

CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
  return m_sPrivateParam.sBackgroundColor;
}

void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
  m_sPrivateParam.sBackgroundColor = color;
}

void CPWL_Wnd::SetTextColor(const CPWL_Color& color) {
  m_sPrivateParam.sTextColor = color;
}

void CPWL_Wnd::SetTextStrokeColor(const CPWL_Color& color) {
  m_sPrivateParam.sTextStrokeColor = color;
}

CPWL_Color CPWL_Wnd::GetTextColor() const {
  return m_sPrivateParam.sTextColor;
}

CPWL_Color CPWL_Wnd::GetTextStrokeColor() const {
  return m_sPrivateParam.sTextStrokeColor;
}

int32_t CPWL_Wnd::GetBorderStyle() const {
  return m_sPrivateParam.nBorderStyle;
}

void CPWL_Wnd::SetBorderStyle(int32_t nBorderStyle) {
  if (HasFlag(PWS_BORDER))
    m_sPrivateParam.nBorderStyle = nBorderStyle;
}

int32_t CPWL_Wnd::GetBorderWidth() const {
  if (HasFlag(PWS_BORDER))
    return m_sPrivateParam.dwBorderWidth;

  return 0;
}

int32_t CPWL_Wnd::GetInnerBorderWidth() const {
  return 0;
}

CPWL_Color CPWL_Wnd::GetBorderColor() const {
  if (HasFlag(PWS_BORDER))
    return m_sPrivateParam.sBorderColor;

  return CPWL_Color();
}

const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
  return m_sPrivateParam.sDash;
}

void* CPWL_Wnd::GetAttachedData() const {
  return m_sPrivateParam.pAttachedData;
}

CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
  if (HasFlag(PWS_VSCROLL))
    return m_pVScrollBar;

  return NULL;
}

void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
  CreateVScrollBar(cp);
}

void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
  if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
    PWL_CREATEPARAM scp = cp;

    // flags
    scp.dwFlags =
        PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;

    scp.pParentWnd = this;
    scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
    scp.eCursorType = FXCT_ARROW;
    scp.nTransparency = PWL_SCROLLBAR_TRANSPARANCY;

    m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
    m_pVScrollBar->Create(scp);
  }
}

void CPWL_Wnd::SetCapture() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    pMsgCtrl->SetCapture(this);
}

void CPWL_Wnd::ReleaseCapture() {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++)
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i))
      pChild->ReleaseCapture();

  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
    pMsgCtrl->ReleaseCapture();
}

void CPWL_Wnd::SetFocus() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    if (!pMsgCtrl->IsMainCaptureKeyboard(this))
      pMsgCtrl->KillFocus();
    pMsgCtrl->SetFocus(this);
  }
}

void CPWL_Wnd::KillFocus() {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    if (pMsgCtrl->IsWndCaptureKeyboard(this))
      pMsgCtrl->KillFocus();
  }
}

void CPWL_Wnd::OnSetFocus() {}

void CPWL_Wnd::OnKillFocus() {}

FX_BOOL CPWL_Wnd::WndHitTest(const CPDF_Point& point) const {
  return IsValid() && IsVisible() && GetWindowRect().Contains(point.x, point.y);
}

FX_BOOL CPWL_Wnd::ClientHitTest(const CPDF_Point& point) const {
  return IsValid() && IsVisible() && GetClientRect().Contains(point.x, point.y);
}

const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
  if (m_sPrivateParam.pParentWnd)
    return m_sPrivateParam.pParentWnd->GetRootWnd();

  return this;
}

void CPWL_Wnd::SetVisible(FX_BOOL bVisible) {
  if (IsValid()) {
    for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
      if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
        pChild->SetVisible(bVisible);
      }
    }

    if (bVisible != m_bVisible) {
      m_bVisible = bVisible;
      RePosChildWnd();
      InvalidateRect();
    }
  }
}

void CPWL_Wnd::SetClipRect(const CPDF_Rect& rect) {
  m_rcClip = rect;
  m_rcClip.Normalize();
}

const CPDF_Rect& CPWL_Wnd::GetClipRect() const {
  return m_rcClip;
}

FX_BOOL CPWL_Wnd::IsReadOnly() const {
  return HasFlag(PWS_READONLY);
}

void CPWL_Wnd::RePosChildWnd() {
  CPDF_Rect rcContent = CPWL_Utils::DeflateRect(
      GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));

  CPWL_ScrollBar* pVSB = GetVScrollBar();

  CPDF_Rect rcVScroll =
      CPDF_Rect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
                rcContent.right - 1.0f, rcContent.top);

  if (pVSB)
    pVSB->Move(rcVScroll, TRUE, FALSE);
}

void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}

void CPWL_Wnd::SetCursor() {
  if (IsValid()) {
    if (IFX_SystemHandler* pSH = GetSystemHandler()) {
      int32_t nCursorType = GetCreationParam().eCursorType;
      pSH->SetCursor(nCursorType);
    }
  }
}

void CPWL_Wnd::CreateMsgControl() {
  if (!m_sPrivateParam.pMsgControl)
    m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
}

void CPWL_Wnd::DestroyMsgControl() {
  if (CPWL_MsgControl* pMsgControl = GetMsgControl())
    if (pMsgControl->IsWndCreated(this))
      delete pMsgControl;
}

CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
  return m_sPrivateParam.pMsgControl;
}

FX_BOOL CPWL_Wnd::IsCaptureMouse() const {
  return IsWndCaptureMouse(this);
}

FX_BOOL CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsWndCaptureMouse(pWnd);

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsWndCaptureKeyboard(pWnd);

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsFocused() const {
  if (CPWL_MsgControl* pCtrl = GetMsgControl())
    return pCtrl->IsMainCaptureKeyboard(this);

  return FALSE;
}

CPDF_Rect CPWL_Wnd::GetFocusRect() const {
  return CPWL_Utils::InflateRect(GetWindowRect(), 1);
}

FX_FLOAT CPWL_Wnd::GetFontSize() const {
  return m_sPrivateParam.fFontSize;
}

void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
  m_sPrivateParam.fFontSize = fFontSize;
}

IFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
  return m_sPrivateParam.pSystemHandler;
}

IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
  return m_sPrivateParam.pFocusHandler;
}

IPWL_Provider* CPWL_Wnd::GetProvider() const {
  return m_sPrivateParam.pProvider;
}

IFX_Edit_FontMap* CPWL_Wnd::GetFontMap() const {
  return m_sPrivateParam.pFontMap;
}

CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(int32_t nBorderStyle) const {
  CPWL_Color color;

  switch (nBorderStyle) {
    case PBS_SOLID:
      break;
    case PBS_DASH:
      break;
    case PBS_BEVELED:
      color = CPWL_Color(COLORTYPE_GRAY, 1);
      break;
    case PBS_INSET:
      color = CPWL_Color(COLORTYPE_GRAY, 0.5f);
      break;
    case PBS_UNDERLINED:
      break;
  }

  return color;
}

CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(int32_t nBorderStyle) const {
  CPWL_Color color;

  switch (nBorderStyle) {
    case PBS_SOLID:
      break;
    case PBS_DASH:
      break;
    case PBS_BEVELED:
      color = CPWL_Utils::DevideColor(GetBackgroundColor(), 2);
      break;
    case PBS_INSET:
      color = CPWL_Color(COLORTYPE_GRAY, 0.75f);
      break;
    case PBS_UNDERLINED:
      break;
  }

  return color;
}

int32_t CPWL_Wnd::GetTransparency() {
  return m_sPrivateParam.nTransparency;
}

void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
  for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
    if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
      pChild->SetTransparency(nTransparency);
    }
  }

  m_sPrivateParam.nTransparency = nTransparency;
}

CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
  CFX_Matrix mt = GetChildToRoot();

  if (IPWL_Provider* pProvider = GetProvider()) {
    mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
    return mt;
  }

  return mt;
}

void CPWL_Wnd::PWLtoWnd(const CPDF_Point& point, int32_t& x, int32_t& y) const {
  CFX_Matrix mt = GetWindowMatrix();
  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  x = (int32_t)(pt.x + 0.5);
  y = (int32_t)(pt.y + 0.5);
}

FX_RECT CPWL_Wnd::PWLtoWnd(const CPDF_Rect& rect) const {
  CPDF_Rect rcTemp = rect;
  CFX_Matrix mt = GetWindowMatrix();
  mt.TransformRect(rcTemp);
  return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
                 (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
}

FX_HWND CPWL_Wnd::GetAttachedHWnd() const {
  return m_sPrivateParam.hAttachedWnd;
}

CPDF_Point CPWL_Wnd::ChildToParent(const CPDF_Point& point) const {
  CFX_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return point;

  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  return pt;
}

CPDF_Rect CPWL_Wnd::ChildToParent(const CPDF_Rect& rect) const {
  CFX_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return rect;

  CPDF_Rect rc = rect;
  mt.TransformRect(rc);
  return rc;
}

CPDF_Point CPWL_Wnd::ParentToChild(const CPDF_Point& point) const {
  CFX_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return point;

  mt.SetReverse(mt);
  CPDF_Point pt = point;
  mt.Transform(pt.x, pt.y);
  return pt;
}

CPDF_Rect CPWL_Wnd::ParentToChild(const CPDF_Rect& rect) const {
  CFX_Matrix mt = GetChildMatrix();
  if (mt.IsIdentity())
    return rect;

  mt.SetReverse(mt);
  CPDF_Rect rc = rect;
  mt.TransformRect(rc);
  return rc;
}

CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
  CFX_Matrix mt(1, 0, 0, 1, 0, 0);
  if (HasFlag(PWS_CHILD)) {
    const CPWL_Wnd* pParent = this;
    while (pParent) {
      mt.Concat(pParent->GetChildMatrix());
      pParent = pParent->GetParentWindow();
    }
  }
  return mt;
}

CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
  if (HasFlag(PWS_CHILD))
    return m_sPrivateParam.mtChild;

  return CFX_Matrix(1, 0, 0, 1, 0, 0);
}

void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
  m_sPrivateParam.mtChild = mt;
}

const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
  if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
    return pMsgCtrl->m_pMainKeyboardWnd;
  }

  return NULL;
}

void CPWL_Wnd::EnableWindow(FX_BOOL bEnable) {
  if (m_bEnabled != bEnable) {
    for (int32_t i = 0, sz = m_aChildren.GetSize(); i < sz; i++) {
      if (CPWL_Wnd* pChild = m_aChildren.GetAt(i)) {
        pChild->EnableWindow(bEnable);
      }
    }

    m_bEnabled = bEnable;

    if (bEnable)
      OnEnabled();
    else
      OnDisabled();
  }
}

FX_BOOL CPWL_Wnd::IsEnabled() {
  return m_bEnabled;
}

void CPWL_Wnd::OnEnabled() {}

void CPWL_Wnd::OnDisabled() {}

FX_BOOL CPWL_Wnd::IsCTRLpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsCTRLKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsSHIFTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsSHIFTKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsALTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsALTKeyDown(nFlag);
  }

  return FALSE;
}

FX_BOOL CPWL_Wnd::IsINSERTpressed(FX_DWORD nFlag) const {
  if (IFX_SystemHandler* pSystemHandler = GetSystemHandler()) {
    return pSystemHandler->IsINSERTKeyDown(nFlag);
  }

  return FALSE;
}
