// 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/fwl/cfwl_edit.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "build/build_config.h"
#include "core/fxge/cfx_renderdevice.h"
#include "core/fxge/text_char_pos.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
#include "xfa/fde/cfde_textout.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_caret.h"
#include "xfa/fwl/cfwl_event.h"
#include "xfa/fwl/cfwl_eventtextwillchange.h"
#include "xfa/fwl/cfwl_eventvalidate.h"
#include "xfa/fwl/cfwl_messagekey.h"
#include "xfa/fwl/cfwl_messagemouse.h"
#include "xfa/fwl/cfwl_themebackground.h"
#include "xfa/fwl/cfwl_themepart.h"
#include "xfa/fwl/cfwl_widgetmgr.h"
#include "xfa/fwl/fwl_widgetdef.h"
#include "xfa/fwl/ifwl_themeprovider.h"
#include "xfa/fwl/theme/cfwl_utils.h"
#include "xfa/fxgraphics/cxfa_gepath.h"

namespace {

constexpr int kEditMargin = 3;

#if defined(OS_MACOSX)
constexpr int kEditingModifier = FWL_KEYFLAG_Command;
#else
constexpr int kEditingModifier = FWL_KEYFLAG_Ctrl;
#endif

}  // namespace

CFWL_Edit::CFWL_Edit(const CFWL_App* app,
                     std::unique_ptr<CFWL_WidgetProperties> properties,
                     CFWL_Widget* pOuter)
    : CFWL_Widget(app, std::move(properties), pOuter),
      m_pEditEngine(pdfium::MakeUnique<CFDE_TextEditEngine>()) {
  m_pEditEngine->SetDelegate(this);
}

CFWL_Edit::~CFWL_Edit() {
  m_pEditEngine->SetDelegate(nullptr);
  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
    HideCaret(nullptr);
}

FWL_Type CFWL_Edit::GetClassID() const {
  return FWL_Type::Edit;
}

CFX_RectF CFWL_Edit::GetWidgetRect() {
  CFX_RectF rect = m_pProperties->m_rtWidget;
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
    IFWL_ThemeProvider* theme = GetAvailableTheme();
    float scrollbarWidth = theme ? theme->GetScrollBarWidth() : 0.0f;
    if (IsShowScrollBar(true)) {
      rect.width += scrollbarWidth;
      rect.width += kEditMargin;
    }
    if (IsShowScrollBar(false)) {
      rect.height += scrollbarWidth;
      rect.height += kEditMargin;
    }
  }
  return rect;
}

CFX_RectF CFWL_Edit::GetAutosizedWidgetRect() {
  CFX_RectF rect;

  if (m_pEditEngine->GetLength() > 0) {
    CFX_SizeF size = CalcTextSize(
        m_pEditEngine->GetText(), m_pProperties->m_pThemeProvider.Get(),
        !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine));
    rect = CFX_RectF(0, 0, size);
  }

  InflateWidgetRect(rect);
  return rect;
}

void CFWL_Edit::SetStates(uint32_t dwStates) {
  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
    HideCaret(nullptr);
  }
  CFWL_Widget::SetStates(dwStates);
}

void CFWL_Edit::Update() {
  if (IsLocked())
    return;
  if (!m_pProperties->m_pThemeProvider)
    m_pProperties->m_pThemeProvider = GetAvailableTheme();

  Layout();
  if (m_rtClient.IsEmpty())
    return;

  UpdateEditEngine();
  UpdateVAlignment();
  UpdateScroll();
  InitCaret();
}

FWL_WidgetHit CFWL_Edit::HitTest(const CFX_PointF& point) {
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
    if (IsShowScrollBar(true)) {
      if (m_pVertScrollBar->GetWidgetRect().Contains(point))
        return FWL_WidgetHit::VScrollBar;
    }
    if (IsShowScrollBar(false)) {
      if (m_pHorzScrollBar->GetWidgetRect().Contains(point))
        return FWL_WidgetHit::HScrollBar;
    }
  }
  if (m_rtClient.Contains(point))
    return FWL_WidgetHit::Edit;
  return FWL_WidgetHit::Unknown;
}

void CFWL_Edit::DrawWidget(CXFA_Graphics* pGraphics, const CFX_Matrix& matrix) {
  if (!pGraphics)
    return;

  if (m_rtClient.IsEmpty())
    return;

  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider.Get();
  if (!pTheme)
    return;

  DrawContent(pGraphics, pTheme, &matrix);
  if (HasBorder())
    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, matrix);
}

void CFWL_Edit::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
  if (!pThemeProvider)
    return;
  if (m_pHorzScrollBar)
    m_pHorzScrollBar->SetThemeProvider(pThemeProvider);
  if (m_pVertScrollBar)
    m_pVertScrollBar->SetThemeProvider(pThemeProvider);
  if (m_pCaret)
    m_pCaret->SetThemeProvider(pThemeProvider);
  m_pProperties->m_pThemeProvider = pThemeProvider;
}

void CFWL_Edit::SetText(const WideString& wsText) {
  m_pEditEngine->Clear();
  m_pEditEngine->Insert(0, wsText,
                        CFDE_TextEditEngine::RecordOperation::kInsertRecord);
}

void CFWL_Edit::SetTextSkipNotify(const WideString& wsText) {
  m_pEditEngine->Clear();
  m_pEditEngine->Insert(0, wsText,
                        CFDE_TextEditEngine::RecordOperation::kSkipNotify);
}

int32_t CFWL_Edit::GetTextLength() const {
  return m_pEditEngine->GetLength();
}

WideString CFWL_Edit::GetText() const {
  return m_pEditEngine->GetText();
}

void CFWL_Edit::ClearText() {
  m_pEditEngine->Clear();
}

void CFWL_Edit::SelectAll() {
  m_pEditEngine->SelectAll();
}

bool CFWL_Edit::HasSelection() const {
  return m_pEditEngine->HasSelection();
}

std::pair<size_t, size_t> CFWL_Edit::GetSelection() const {
  return m_pEditEngine->GetSelection();
}

void CFWL_Edit::ClearSelection() {
  return m_pEditEngine->ClearSelection();
}

int32_t CFWL_Edit::GetLimit() const {
  return m_nLimit;
}

void CFWL_Edit::SetLimit(int32_t nLimit) {
  m_nLimit = nLimit;

  if (m_nLimit > 0) {
    m_pEditEngine->SetHasCharacterLimit(true);
    m_pEditEngine->SetCharacterLimit(nLimit);
  } else {
    m_pEditEngine->SetHasCharacterLimit(false);
  }
}

void CFWL_Edit::SetAliasChar(wchar_t wAlias) {
  m_pEditEngine->SetAliasChar(wAlias);
}

Optional<WideString> CFWL_Edit::Copy() {
  if (!m_pEditEngine->HasSelection())
    return {};

  return {m_pEditEngine->GetSelectedText()};
}

Optional<WideString> CFWL_Edit::Cut() {
  if (!m_pEditEngine->HasSelection())
    return {};

  WideString cut_text = m_pEditEngine->DeleteSelectedText();
  UpdateCaret();
  return {cut_text};
}

bool CFWL_Edit::Paste(const WideString& wsPaste) {
  if (m_pEditEngine->HasSelection())
    m_pEditEngine->ReplaceSelectedText(wsPaste);
  else
    m_pEditEngine->Insert(m_CursorPosition, wsPaste);

  return true;
}

bool CFWL_Edit::Undo() {
  return CanUndo() ? m_pEditEngine->Undo() : false;
}

bool CFWL_Edit::Redo() {
  return CanRedo() ? m_pEditEngine->Redo() : false;
}

bool CFWL_Edit::CanUndo() {
  return m_pEditEngine->CanUndo();
}

bool CFWL_Edit::CanRedo() {
  return m_pEditEngine->CanRedo();
}

void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) {
  m_pOuter = pOuter;
}

void CFWL_Edit::NotifyTextFull() {
  CFWL_Event evt(CFWL_Event::Type::TextFull, this);
  DispatchEvent(&evt);
}

void CFWL_Edit::OnCaretChanged() {
  if (m_rtEngine.IsEmpty())
    return;
  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
    return;

  bool bRepaintContent = UpdateOffset();
  UpdateCaret();
  CFX_RectF rtInvalid;
  bool bRepaintScroll = false;
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
    CFWL_ScrollBar* pScroll = UpdateScroll();
    if (pScroll) {
      rtInvalid = pScroll->GetWidgetRect();
      bRepaintScroll = true;
    }
  }
  if (bRepaintContent || bRepaintScroll) {
    if (bRepaintContent)
      rtInvalid.Union(m_rtEngine);
    RepaintRect(rtInvalid);
  }
}

void CFWL_Edit::OnTextWillChange(CFDE_TextEditEngine::TextChange* change) {
  CFWL_EventTextWillChange event(this);
  event.previous_text = change->previous_text;
  event.change_text = change->text;
  event.selection_start = change->selection_start;
  event.selection_end = change->selection_end;
  event.cancelled = false;

  DispatchEvent(&event);

  change->text = event.change_text;
  change->selection_start = event.selection_start;
  change->selection_end = event.selection_end;
  change->cancelled = event.cancelled;
}

void CFWL_Edit::OnTextChanged() {
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask)
    UpdateVAlignment();

  LayoutScrollBar();
  RepaintRect(GetClientRect());
}

void CFWL_Edit::OnSelChanged() {
  RepaintRect(GetClientRect());
}

bool CFWL_Edit::OnValidate(const WideString& wsText) {
  CFWL_EventValidate event(this);
  event.wsInsert = wsText;
  event.bValidate = true;
  DispatchEvent(&event);
  return event.bValidate;
}

void CFWL_Edit::SetScrollOffset(float fScrollOffset) {
  m_fScrollOffsetY = fScrollOffset;
}

void CFWL_Edit::DrawTextBk(CXFA_Graphics* pGraphics,
                           IFWL_ThemeProvider* pTheme,
                           const CFX_Matrix* pMatrix) {
  CFWL_ThemeBackground param;
  param.m_pWidget = this;
  param.m_iPart = CFWL_Part::Background;
  param.m_bStaticBackground = false;
  param.m_dwStates = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly
                         ? CFWL_PartState_ReadOnly
                         : CFWL_PartState_Normal;
  uint32_t dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled);
  if (dwStates)
    param.m_dwStates = CFWL_PartState_Disabled;
  param.m_pGraphics = pGraphics;
  param.m_matrix = *pMatrix;
  param.m_rtPart = m_rtClient;
  pTheme->DrawBackground(param);

  if (!IsShowScrollBar(true) || !IsShowScrollBar(false))
    return;

  CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect();

  CFX_RectF rtStatic(m_rtClient.right() - rtScroll.height,
                     m_rtClient.bottom() - rtScroll.height, rtScroll.height,
                     rtScroll.height);
  param.m_bStaticBackground = true;
  param.m_bMaximize = true;
  param.m_rtPart = rtStatic;
  pTheme->DrawBackground(param);
}

void CFWL_Edit::DrawContent(CXFA_Graphics* pGraphics,
                            IFWL_ThemeProvider* pTheme,
                            const CFX_Matrix* pMatrix) {
  pGraphics->SaveGraphState();

  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
    pGraphics->SaveGraphState();

  CFX_RectF rtClip = m_rtEngine;
  float fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
  float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;

  CFX_Matrix mt(1, 0, 0, 1, fOffSetX, fOffSetY);
  if (pMatrix) {
    rtClip = pMatrix->TransformRect(rtClip);
    mt.Concat(*pMatrix);
  }

  bool bShowSel = !!(m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
  if (bShowSel && m_pEditEngine->HasSelection()) {
    size_t sel_start;
    size_t count;
    std::tie(sel_start, count) = m_pEditEngine->GetSelection();
    std::vector<CFX_RectF> rects =
        m_pEditEngine->GetCharacterRectsInRange(sel_start, count);

    CXFA_GEPath path;
    for (auto& rect : rects) {
      rect.left += fOffSetX;
      rect.top += fOffSetY;
      path.AddRectangle(rect.left, rect.top, rect.width, rect.height);
    }
    pGraphics->SetClipRect(rtClip);

    CFWL_ThemeBackground param;
    param.m_pGraphics = pGraphics;
    param.m_matrix = *pMatrix;
    param.m_pWidget = this;
    param.m_iPart = CFWL_Part::Background;
    param.m_pPath = &path;
    pTheme->DrawBackground(param);
  }

  CFX_RenderDevice* pRenderDev = pGraphics->GetRenderDevice();
  RenderText(pRenderDev, rtClip, mt);

  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
    pGraphics->RestoreGraphState();

    CXFA_GEPath path;
    int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
    float fStep = m_rtEngine.width / iLimit;
    float fLeft = m_rtEngine.left + 1;
    for (int32_t i = 1; i < iLimit; i++) {
      fLeft += fStep;
      path.AddLine(CFX_PointF(fLeft, m_rtClient.top),
                   CFX_PointF(fLeft, m_rtClient.bottom()));
    }

    CFWL_ThemeBackground param;
    param.m_pGraphics = pGraphics;
    param.m_matrix = *pMatrix;
    param.m_pWidget = this;
    param.m_iPart = CFWL_Part::CombTextLine;
    param.m_pPath = &path;
    pTheme->DrawBackground(param);
  }
  pGraphics->RestoreGraphState();
}

void CFWL_Edit::RenderText(CFX_RenderDevice* pRenderDev,
                           const CFX_RectF& clipRect,
                           const CFX_Matrix& mt) {
  ASSERT(pRenderDev);

  RetainPtr<CFGAS_GEFont> font = m_pEditEngine->GetFont();
  if (!font)
    return;

  pRenderDev->SetClip_Rect(clipRect.GetOuterRect());

  CFX_RectF rtDocClip = clipRect;
  if (rtDocClip.IsEmpty()) {
    rtDocClip.left = 0;
    rtDocClip.top = 0;
    rtDocClip.width = static_cast<float>(pRenderDev->GetWidth());
    rtDocClip.height = static_cast<float>(pRenderDev->GetHeight());
  }
  rtDocClip = mt.GetInverse().TransformRect(rtDocClip);

  for (const FDE_TEXTEDITPIECE& info : m_pEditEngine->GetTextPieces()) {
    // If this character is outside the clip, skip it.
    if (!rtDocClip.IntersectWith(info.rtPiece))
      continue;

    std::vector<TextCharPos> char_pos = m_pEditEngine->GetDisplayPos(info);
    if (char_pos.empty())
      continue;

    CFDE_TextOut::DrawString(pRenderDev, m_pEditEngine->GetFontColor(), font,
                             char_pos, m_pEditEngine->GetFontSize(), mt);
  }
}

void CFWL_Edit::UpdateEditEngine() {
  UpdateEditParams();
  UpdateEditLayout();
}

void CFWL_Edit::UpdateEditParams() {
  m_pEditEngine->SetAvailableWidth(m_rtEngine.width);
  m_pEditEngine->SetCombText(
      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText));

  m_pEditEngine->EnableValidation(
      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate));
  m_pEditEngine->EnablePasswordMode(
      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password));

  uint32_t alignment = 0;
  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
    case FWL_STYLEEXT_EDT_HNear: {
      alignment |= CFX_TxtLineAlignment_Left;
      break;
    }
    case FWL_STYLEEXT_EDT_HCenter: {
      alignment |= CFX_TxtLineAlignment_Center;
      break;
    }
    case FWL_STYLEEXT_EDT_HFar: {
      alignment |= CFX_TxtLineAlignment_Right;
      break;
    }
    default:
      break;
  }
  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
    case FWL_STYLEEXT_EDT_Justified: {
      alignment |= CFX_TxtLineAlignment_Justified;
      break;
    }
    default:
      break;
  }
  m_pEditEngine->SetAlignment(alignment);

  bool auto_hscroll =
      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll);
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
    m_pEditEngine->EnableMultiLine(true);
    m_pEditEngine->EnableLineWrap(!auto_hscroll);
    m_pEditEngine->LimitVerticalScroll(
        (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
        (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0);
  } else {
    m_pEditEngine->EnableMultiLine(false);
    m_pEditEngine->EnableLineWrap(false);
    m_pEditEngine->LimitVerticalScroll(false);
  }
  m_pEditEngine->LimitHorizontalScroll(!auto_hscroll);

  IFWL_ThemeProvider* theme = GetAvailableTheme();
  CFWL_ThemePart part;
  part.m_pWidget = this;

  if (!theme) {
    m_fFontSize = FWLTHEME_CAPACITY_FontSize;
    return;
  }
  m_fFontSize = theme->GetFontSize(part);

  RetainPtr<CFGAS_GEFont> pFont = theme->GetFont(part);
  if (!pFont)
    return;

  m_pEditEngine->SetFont(pFont);
  m_pEditEngine->SetFontColor(theme->GetTextColor(part));
  m_pEditEngine->SetFontSize(m_fFontSize);
  m_pEditEngine->SetLineSpace(theme->GetLineHeight(part));
  m_pEditEngine->SetTabWidth(m_fFontSize);
  m_pEditEngine->SetVisibleLineCount(m_rtEngine.height /
                                     theme->GetLineHeight(part));
}

void CFWL_Edit::UpdateEditLayout() {
  m_pEditEngine->Layout();
}

bool CFWL_Edit::UpdateOffset() {
  CFX_RectF rtCaret = m_rtCaret;

  float fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
  float fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
  rtCaret.Offset(fOffSetX, fOffSetY);

  const CFX_RectF& edit_bounds = m_rtEngine;
  if (edit_bounds.Contains(rtCaret)) {
    CFX_RectF contents_bounds = m_pEditEngine->GetContentsBoundingBox();
    contents_bounds.Offset(fOffSetX, fOffSetY);
    if (contents_bounds.right() < edit_bounds.right() && m_fScrollOffsetX > 0) {
      m_fScrollOffsetX += contents_bounds.right() - edit_bounds.right();
      m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f);
    }
    if (contents_bounds.bottom() < edit_bounds.bottom() &&
        m_fScrollOffsetY > 0) {
      m_fScrollOffsetY += contents_bounds.bottom() - edit_bounds.bottom();
      m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f);
    }
    return false;
  }

  float offsetX = 0.0;
  float offsetY = 0.0;
  if (rtCaret.left < edit_bounds.left)
    offsetX = rtCaret.left - edit_bounds.left;
  if (rtCaret.right() > edit_bounds.right())
    offsetX = rtCaret.right() - edit_bounds.right();
  if (rtCaret.top < edit_bounds.top)
    offsetY = rtCaret.top - edit_bounds.top;
  if (rtCaret.bottom() > edit_bounds.bottom())
    offsetY = rtCaret.bottom() - edit_bounds.bottom();

  m_fScrollOffsetX += offsetX;
  m_fScrollOffsetY += offsetY;
  if (m_fFontSize > m_rtEngine.height)
    m_fScrollOffsetY = 0;

  return true;
}

bool CFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, float fPosChanged) {
  if (pScrollBar == m_pHorzScrollBar.get())
    m_fScrollOffsetX += fPosChanged;
  else
    m_fScrollOffsetY += fPosChanged;
  return true;
}

void CFWL_Edit::UpdateVAlignment() {
  float fSpaceAbove = 0.0f;
  float fSpaceBelow = 0.0f;
  IFWL_ThemeProvider* theme = GetAvailableTheme();
  if (theme) {
    CFWL_ThemePart part;
    part.m_pWidget = this;

    CFX_SizeF pSpace = theme->GetSpaceAboveBelow(part);
    fSpaceAbove = pSpace.width >= 0.1f ? pSpace.width : 0.0f;
    fSpaceBelow = pSpace.height >= 0.1f ? pSpace.height : 0.0f;
  }

  float fOffsetY = 0.0f;
  CFX_RectF contents_bounds = m_pEditEngine->GetContentsBoundingBox();
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
    fOffsetY = (m_rtEngine.height - contents_bounds.height) / 2.0f;
    if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2.0f &&
        fSpaceAbove < fSpaceBelow) {
      return;
    }
    fOffsetY += (fSpaceAbove - fSpaceBelow) / 2.0f;
  } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
    fOffsetY = (m_rtEngine.height - contents_bounds.height);
    fOffsetY -= fSpaceBelow;
  } else {
    fOffsetY += fSpaceAbove;
  }
  m_fVAlignOffset = std::max(fOffsetY, 0.0f);
}

void CFWL_Edit::UpdateCaret() {
  CFX_RectF rtCaret = m_rtCaret;
  rtCaret.Offset(m_rtEngine.left - m_fScrollOffsetX,
                 m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);

  CFX_RectF rtClient = GetClientRect();
  rtCaret.Intersect(rtClient);
  if (rtCaret.left > rtClient.right()) {
    float right = rtCaret.right();
    rtCaret.left = rtClient.right() - 1;
    rtCaret.width = right - rtCaret.left;
  }

  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty())
    ShowCaret(&rtCaret);
  else
    HideCaret(&rtCaret);
}

CFWL_ScrollBar* CFWL_Edit::UpdateScroll() {
  bool bShowHorz = m_pHorzScrollBar && m_pHorzScrollBar->IsVisible();
  bool bShowVert = m_pVertScrollBar && m_pVertScrollBar->IsVisible();
  if (!bShowHorz && !bShowVert)
    return nullptr;

  CFX_RectF contents_bounds = m_pEditEngine->GetContentsBoundingBox();
  CFWL_ScrollBar* pRepaint = nullptr;
  if (bShowHorz) {
    CFX_RectF rtScroll = m_pHorzScrollBar->GetWidgetRect();
    if (rtScroll.width < contents_bounds.width) {
      {
        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
        float fRange = contents_bounds.width - rtScroll.width;
        m_pHorzScrollBar->SetRange(0.0f, fRange);

        float fPos = pdfium::clamp(m_fScrollOffsetX, 0.0f, fRange);
        m_pHorzScrollBar->SetPos(fPos);
        m_pHorzScrollBar->SetTrackPos(fPos);
        m_pHorzScrollBar->SetPageSize(rtScroll.width);
        m_pHorzScrollBar->SetStepSize(rtScroll.width / 10);
        m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
      }
      m_pHorzScrollBar->Update();
      pRepaint = m_pHorzScrollBar.get();
    } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
      {
        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
        m_pHorzScrollBar->SetRange(0, -1);
        m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled);
      }
      m_pHorzScrollBar->Update();
      pRepaint = m_pHorzScrollBar.get();
    }
  }

  if (bShowVert) {
    CFX_RectF rtScroll = m_pVertScrollBar->GetWidgetRect();
    if (rtScroll.height < contents_bounds.height) {
      {
        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
        float fStep = m_pEditEngine->GetLineSpace();
        float fRange =
            std::max(contents_bounds.height - m_rtEngine.height, fStep);

        m_pVertScrollBar->SetRange(0.0f, fRange);
        float fPos = pdfium::clamp(m_fScrollOffsetY, 0.0f, fRange);
        m_pVertScrollBar->SetPos(fPos);
        m_pVertScrollBar->SetTrackPos(fPos);
        m_pVertScrollBar->SetPageSize(rtScroll.height);
        m_pVertScrollBar->SetStepSize(fStep);
        m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Disabled);
      }
      m_pVertScrollBar->Update();
      pRepaint = m_pVertScrollBar.get();
    } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
      {
        ScopedUpdateLock update_lock(m_pHorzScrollBar.get());
        m_pVertScrollBar->SetRange(0, -1);
        m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled);
      }
      m_pVertScrollBar->Update();
      pRepaint = m_pVertScrollBar.get();
    }
  }
  return pRepaint;
}

bool CFWL_Edit::IsShowScrollBar(bool bVert) {
  if (!bVert)
    return false;
  bool bShow =
      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
          ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
                FWL_WGTSTATE_Focused
          : true;
  return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
         IsContentHeightOverflow();
}

bool CFWL_Edit::IsContentHeightOverflow() {
  return m_pEditEngine->GetContentsBoundingBox().height >
         m_rtEngine.height + 1.0f;
}

void CFWL_Edit::Layout() {
  m_rtClient = GetClientRect();
  m_rtEngine = m_rtClient;
  IFWL_ThemeProvider* theme = GetAvailableTheme();
  if (!theme)
    return;

  float fWidth = theme->GetScrollBarWidth();
  CFWL_ThemePart part;
  if (!m_pOuter) {
    part.m_pWidget = this;
    CFX_RectF pUIMargin = theme->GetUIMargin(part);
    m_rtEngine.Deflate(pUIMargin.left, pUIMargin.top, pUIMargin.width,
                       pUIMargin.height);
  } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) {
    part.m_pWidget = m_pOuter;
    CFX_RectF pUIMargin = theme->GetUIMargin(part);
    m_rtEngine.Deflate(pUIMargin.left, pUIMargin.top, pUIMargin.width,
                       pUIMargin.height);
  }

  bool bShowVertScrollbar = IsShowScrollBar(true);
  bool bShowHorzScrollbar = IsShowScrollBar(false);
  if (bShowVertScrollbar) {
    InitVerticalScrollBar();

    CFX_RectF rtVertScr;
    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
      rtVertScr = CFX_RectF(m_rtClient.right() + kEditMargin, m_rtClient.top,
                            fWidth, m_rtClient.height);
    } else {
      rtVertScr = CFX_RectF(m_rtClient.right() - fWidth, m_rtClient.top, fWidth,
                            m_rtClient.height);
      if (bShowHorzScrollbar)
        rtVertScr.height -= fWidth;
      m_rtEngine.width -= fWidth;
    }

    m_pVertScrollBar->SetWidgetRect(rtVertScr);
    m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
    m_pVertScrollBar->Update();
  } else if (m_pVertScrollBar) {
    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible);
  }

  if (bShowHorzScrollbar) {
    InitHorizontalScrollBar();

    CFX_RectF rtHoriScr;
    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
      rtHoriScr = CFX_RectF(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
                            m_rtClient.width, fWidth);
    } else {
      rtHoriScr = CFX_RectF(m_rtClient.left, m_rtClient.bottom() - fWidth,
                            m_rtClient.width, fWidth);
      if (bShowVertScrollbar)
        rtHoriScr.width -= fWidth;
      m_rtEngine.height -= fWidth;
    }
    m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
    m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
    m_pHorzScrollBar->Update();
  } else if (m_pHorzScrollBar) {
    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible);
  }
}

void CFWL_Edit::LayoutScrollBar() {
  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
      0) {
    return;
  }

  bool bShowVertScrollbar = IsShowScrollBar(true);
  bool bShowHorzScrollbar = IsShowScrollBar(false);

  IFWL_ThemeProvider* theme = GetAvailableTheme();
  float fWidth = theme ? theme->GetScrollBarWidth() : 0;
  if (bShowVertScrollbar) {
    if (!m_pVertScrollBar) {
      InitVerticalScrollBar();
      CFX_RectF rtVertScr;
      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
        rtVertScr = CFX_RectF(m_rtClient.right() + kEditMargin, m_rtClient.top,
                              fWidth, m_rtClient.height);
      } else {
        rtVertScr = CFX_RectF(m_rtClient.right() - fWidth, m_rtClient.top,
                              fWidth, m_rtClient.height);
        if (bShowHorzScrollbar)
          rtVertScr.height -= fWidth;
      }
      m_pVertScrollBar->SetWidgetRect(rtVertScr);
      m_pVertScrollBar->Update();
    }
    m_pVertScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
  } else if (m_pVertScrollBar) {
    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible);
  }

  if (bShowHorzScrollbar) {
    if (!m_pHorzScrollBar) {
      InitHorizontalScrollBar();
      CFX_RectF rtHoriScr;
      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
        rtHoriScr =
            CFX_RectF(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
                      m_rtClient.width, fWidth);
      } else {
        rtHoriScr = CFX_RectF(m_rtClient.left, m_rtClient.bottom() - fWidth,
                              m_rtClient.width, fWidth);
        if (bShowVertScrollbar)
          rtHoriScr.width -= (fWidth);
      }
      m_pHorzScrollBar->SetWidgetRect(rtHoriScr);
      m_pHorzScrollBar->Update();
    }
    m_pHorzScrollBar->RemoveStates(FWL_WGTSTATE_Invisible);
  } else if (m_pHorzScrollBar) {
    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible);
  }
  if (bShowVertScrollbar || bShowHorzScrollbar)
    UpdateScroll();
}

CFX_PointF CFWL_Edit::DeviceToEngine(const CFX_PointF& pt) {
  return pt + CFX_PointF(m_fScrollOffsetX - m_rtEngine.left,
                         m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset);
}

void CFWL_Edit::InitVerticalScrollBar() {
  if (m_pVertScrollBar)
    return;

  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
  prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Vert;
  prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
  prop->m_pParent = this;
  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
  m_pVertScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(),
                                                        std::move(prop), this);
}

void CFWL_Edit::InitHorizontalScrollBar() {
  if (m_pHorzScrollBar)
    return;

  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
  prop->m_dwStyleExes = FWL_STYLEEXT_SCB_Horz;
  prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
  prop->m_pParent = this;
  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
  m_pHorzScrollBar = pdfium::MakeUnique<CFWL_ScrollBar>(m_pOwnerApp.Get(),
                                                        std::move(prop), this);
}

void CFWL_Edit::ShowCaret(CFX_RectF* pRect) {
  if (m_pCaret) {
    m_pCaret->ShowCaret();
    if (!pRect->IsEmpty())
      m_pCaret->SetWidgetRect(*pRect);
    RepaintRect(m_rtEngine);
    return;
  }

  CFWL_Widget* pOuter = this;
  pRect->Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
  while (pOuter->GetOuter()) {
    pOuter = pOuter->GetOuter();

    CFX_RectF rtOuter = pOuter->GetWidgetRect();
    pRect->Offset(rtOuter.left, rtOuter.top);
  }

  CFWL_Widget::AdapterIface* pXFAWidget = pOuter->GetFFWidget();
  if (!pXFAWidget)
    return;

  CFX_RectF rt = pXFAWidget->GetRotateMatrix().TransformRect(*pRect);
  pXFAWidget->DisplayCaret(true, &rt);
}

void CFWL_Edit::HideCaret(CFX_RectF* pRect) {
  if (m_pCaret) {
    m_pCaret->HideCaret();
    RepaintRect(m_rtEngine);
    return;
  }

  CFWL_Widget* pOuter = this;
  while (pOuter->GetOuter())
    pOuter = pOuter->GetOuter();

  CFWL_Widget::AdapterIface* pXFAWidget = pOuter->GetFFWidget();
  if (!pXFAWidget)
    return;

  pXFAWidget->DisplayCaret(false, pRect);
}

bool CFWL_Edit::ValidateNumberChar(wchar_t cNum) {
  if (!m_bSetRange)
    return true;

  WideString wsText = m_pEditEngine->GetText();
  if (wsText.IsEmpty())
    return cNum != L'0';

  if (HasSelection())
    return wsText.GetInteger() <= m_iMax;
  if (cNum == L'0' && m_CursorPosition == 0)
    return false;

  int32_t nLen = wsText.GetLength();
  WideString l = wsText.Left(m_CursorPosition);
  WideString r = wsText.Right(nLen - m_CursorPosition);
  WideString wsNew = l + cNum + r;
  return wsNew.GetInteger() <= m_iMax;
}

void CFWL_Edit::InitCaret() {
  if (m_pCaret)
    return;

  m_pCaret = pdfium::MakeUnique<CFWL_Caret>(
      m_pOwnerApp.Get(), pdfium::MakeUnique<CFWL_WidgetProperties>(), this);
  m_pCaret->SetParent(this);
  m_pCaret->SetStates(m_pProperties->m_dwStates);
  UpdateCursorRect();
}

void CFWL_Edit::UpdateCursorRect() {
  int32_t bidi_level;
  if (m_pEditEngine->GetLength() > 0) {
    std::tie(bidi_level, m_rtCaret) =
        m_pEditEngine->GetCharacterInfo(m_CursorPosition);
  } else {
    bidi_level = 0;
    m_rtCaret = CFX_RectF();
  }

  // TODO(dsinclair): This should handle bidi level  ...

  m_rtCaret.width = 1.0f;

  // TODO(hnakashima): Handle correctly edits with empty text instead of using
  // these defaults.
  if (m_rtCaret.height == 0)
    m_rtCaret.height = 8.0f;
}

void CFWL_Edit::SetCursorPosition(size_t position) {
  if (m_CursorPosition == position)
    return;

  m_CursorPosition = std::min(position, m_pEditEngine->GetLength());
  UpdateCursorRect();
  OnCaretChanged();
}

void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) {
  if (!pMessage)
    return;

  switch (pMessage->GetType()) {
    case CFWL_Message::Type::SetFocus:
      OnFocusChanged(pMessage, true);
      break;
    case CFWL_Message::Type::KillFocus:
      OnFocusChanged(pMessage, false);
      break;
    case CFWL_Message::Type::Mouse: {
      CFWL_MessageMouse* pMsg = static_cast<CFWL_MessageMouse*>(pMessage);
      switch (pMsg->m_dwCmd) {
        case FWL_MouseCommand::LeftButtonDown:
          OnLButtonDown(pMsg);
          break;
        case FWL_MouseCommand::LeftButtonUp:
          OnLButtonUp(pMsg);
          break;
        case FWL_MouseCommand::LeftButtonDblClk:
          OnButtonDoubleClick(pMsg);
          break;
        case FWL_MouseCommand::Move:
          OnMouseMove(pMsg);
          break;
        case FWL_MouseCommand::RightButtonDown:
          DoRButtonDown(pMsg);
          break;
        default:
          break;
      }
      break;
    }
    case CFWL_Message::Type::Key: {
      CFWL_MessageKey* pKey = static_cast<CFWL_MessageKey*>(pMessage);
      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
        OnKeyDown(pKey);
      else if (pKey->m_dwCmd == FWL_KeyCommand::Char)
        OnChar(pKey);
      break;
    }
    default:
      break;
  }
  // Dst target could be |this|, continue only if not destroyed by above.
  if (pMessage->GetDstTarget())
    CFWL_Widget::OnProcessMessage(pMessage);
}

void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) {
  if (!pEvent || pEvent->GetType() != CFWL_Event::Type::Scroll)
    return;

  CFWL_Widget* pSrcTarget = pEvent->GetSrcTarget();
  if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
      (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
    CFWL_EventScroll* pScrollEvent = static_cast<CFWL_EventScroll*>(pEvent);
    OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
             pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
  }
}

void CFWL_Edit::OnDrawWidget(CXFA_Graphics* pGraphics,
                             const CFX_Matrix& matrix) {
  DrawWidget(pGraphics, matrix);
}

void CFWL_Edit::DoRButtonDown(CFWL_MessageMouse* pMsg) {
  SetCursorPosition(
      m_pEditEngine->GetIndexForPoint(DeviceToEngine(pMsg->m_pos)));
}

void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
  bool bRepaint = false;
  if (bSet) {
    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;

    UpdateVAlignment();
    UpdateOffset();
    UpdateCaret();
  } else if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) {
    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    HideCaret(nullptr);

    if (HasSelection()) {
      ClearSelection();
      bRepaint = true;
    }
    UpdateOffset();
  }

  LayoutScrollBar();
  if (!bRepaint)
    return;

  CFX_RectF rtInvalidate(0, 0, m_pProperties->m_rtWidget.width,
                         m_pProperties->m_rtWidget.height);
  RepaintRect(rtInvalidate);
}

void CFWL_Edit::OnLButtonDown(CFWL_MessageMouse* pMsg) {
  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
    return;

  m_bLButtonDown = true;
  SetGrab(true);

  bool bRepaint = false;
  if (m_pEditEngine->HasSelection()) {
    m_pEditEngine->ClearSelection();
    bRepaint = true;
  }

  size_t index_at_click =
      m_pEditEngine->GetIndexForPoint(DeviceToEngine(pMsg->m_pos));

  if (index_at_click != m_CursorPosition &&
      !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift)) {
    size_t start = std::min(m_CursorPosition, index_at_click);
    size_t end = std::max(m_CursorPosition, index_at_click);

    m_pEditEngine->SetSelection(start, end - start);
    bRepaint = true;
  } else {
    SetCursorPosition(index_at_click);
  }

  if (bRepaint)
    RepaintRect(m_rtEngine);
}

void CFWL_Edit::OnLButtonUp(CFWL_MessageMouse* pMsg) {
  m_bLButtonDown = false;
  SetGrab(false);
}

void CFWL_Edit::OnButtonDoubleClick(CFWL_MessageMouse* pMsg) {
  size_t click_idx =
      m_pEditEngine->GetIndexForPoint(DeviceToEngine(pMsg->m_pos));
  size_t start_idx;
  size_t count;
  std::tie(start_idx, count) = m_pEditEngine->BoundsForWordAt(click_idx);

  m_pEditEngine->SetSelection(start_idx, count);
  m_CursorPosition = start_idx + count;
  RepaintRect(m_rtEngine);
}

void CFWL_Edit::OnMouseMove(CFWL_MessageMouse* pMsg) {
  bool shift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
  if (!m_bLButtonDown || !shift)
    return;

  size_t old_cursor_pos = m_CursorPosition;
  SetCursorPosition(
      m_pEditEngine->GetIndexForPoint(DeviceToEngine(pMsg->m_pos)));
  if (old_cursor_pos == m_CursorPosition)
    return;

  size_t length = m_pEditEngine->GetLength();
  if (m_CursorPosition > length)
    SetCursorPosition(length);

  size_t sel_start = 0;
  size_t count = 0;
  if (m_pEditEngine->HasSelection())
    std::tie(sel_start, count) = m_pEditEngine->GetSelection();
  else
    sel_start = old_cursor_pos;

  size_t start_pos = std::min(sel_start, m_CursorPosition);
  size_t end_pos = std::max(sel_start, m_CursorPosition);
  m_pEditEngine->SetSelection(start_pos, end_pos - start_pos);
}

void CFWL_Edit::OnKeyDown(CFWL_MessageKey* pMsg) {
  bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
  bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);

  size_t sel_start = m_CursorPosition;
  if (m_pEditEngine->HasSelection()) {
    size_t start_idx;
    size_t count;
    std::tie(start_idx, count) = m_pEditEngine->GetSelection();
    sel_start = start_idx;
  }

  switch (pMsg->m_dwKeyCode) {
    case XFA_FWL_VKEY_Left:
      SetCursorPosition(m_pEditEngine->GetIndexLeft(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_Right:
      SetCursorPosition(m_pEditEngine->GetIndexRight(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_Up:
      SetCursorPosition(m_pEditEngine->GetIndexUp(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_Down:
      SetCursorPosition(m_pEditEngine->GetIndexDown(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_Home:
      SetCursorPosition(
          bCtrl ? 0 : m_pEditEngine->GetIndexAtStartOfLine(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_End:
      SetCursorPosition(
          bCtrl ? m_pEditEngine->GetLength()
                : m_pEditEngine->GetIndexAtEndOfLine(m_CursorPosition));
      break;
    case XFA_FWL_VKEY_Delete: {
      if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
          (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
        break;
      }

      m_pEditEngine->Delete(m_CursorPosition, 1);
      UpdateCaret();
      break;
    }
    case XFA_FWL_VKEY_Insert:
    case XFA_FWL_VKEY_F2:
    case XFA_FWL_VKEY_Tab:
    default:
      break;
  }

  // Update the selection.
  if (bShift && sel_start != m_CursorPosition) {
    m_pEditEngine->SetSelection(std::min(sel_start, m_CursorPosition),
                                std::max(sel_start, m_CursorPosition));
    RepaintRect(m_rtEngine);
  }
}

void CFWL_Edit::OnChar(CFWL_MessageKey* pMsg) {
  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
    return;
  }

  wchar_t c = static_cast<wchar_t>(pMsg->m_dwKeyCode);
  switch (c) {
    case L'\b':
      if (m_CursorPosition > 0) {
        SetCursorPosition(m_CursorPosition - 1);
        m_pEditEngine->Delete(m_CursorPosition, 1);
        UpdateCaret();
      }
      break;
    case L'\n':
    case 27:   // Esc
    case 127:  // Delete
      break;
    case L'\t':
      m_pEditEngine->Insert(m_CursorPosition, L"\t");
      SetCursorPosition(m_CursorPosition + 1);
      break;
    case L'\r':
      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) {
        m_pEditEngine->Insert(m_CursorPosition, L"\n");
        SetCursorPosition(m_CursorPosition + 1);
      }
      break;
    default: {
      if (pMsg->m_dwFlags & kEditingModifier)
        break;

      m_pEditEngine->Insert(m_CursorPosition, WideString(c));
      SetCursorPosition(m_CursorPosition + 1);
      break;
    }
  }
}

bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar,
                         CFWL_EventScroll::Code dwCode,
                         float fPos) {
  CFX_SizeF fs;
  pScrollBar->GetRange(&fs.width, &fs.height);
  float iCurPos = pScrollBar->GetPos();
  float fStep = pScrollBar->GetStepSize();
  switch (dwCode) {
    case CFWL_EventScroll::Code::Min: {
      fPos = fs.width;
      break;
    }
    case CFWL_EventScroll::Code::Max: {
      fPos = fs.height;
      break;
    }
    case CFWL_EventScroll::Code::StepBackward: {
      fPos -= fStep;
      if (fPos < fs.width + fStep / 2) {
        fPos = fs.width;
      }
      break;
    }
    case CFWL_EventScroll::Code::StepForward: {
      fPos += fStep;
      if (fPos > fs.height - fStep / 2) {
        fPos = fs.height;
      }
      break;
    }
    case CFWL_EventScroll::Code::PageBackward: {
      fPos -= pScrollBar->GetPageSize();
      if (fPos < fs.width) {
        fPos = fs.width;
      }
      break;
    }
    case CFWL_EventScroll::Code::PageForward: {
      fPos += pScrollBar->GetPageSize();
      if (fPos > fs.height) {
        fPos = fs.height;
      }
      break;
    }
    case CFWL_EventScroll::Code::Pos:
    case CFWL_EventScroll::Code::TrackPos:
    case CFWL_EventScroll::Code::None:
      break;
    case CFWL_EventScroll::Code::EndScroll:
      return false;
  }
  if (iCurPos == fPos)
    return true;

  pScrollBar->SetPos(fPos);
  pScrollBar->SetTrackPos(fPos);
  UpdateOffset(pScrollBar, fPos - iCurPos);
  UpdateCaret();

  CFX_RectF rect = GetWidgetRect();
  RepaintRect(CFX_RectF(0, 0, rect.width + 2, rect.height + 2));
  return true;
}
