Merge IFWL and CFWL classes.

This CL merges the IFWL hierarchy into the CFWL hierachy. All CFWL proxy methods
have been replaced by the IFWL implementations.

Review-Url: https://codereview.chromium.org/2524173002
diff --git a/BUILD.gn b/BUILD.gn
index 00a22f0..46768fc 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1303,25 +1303,7 @@
       "xfa/fwl/core/fwl_widgetdef.h",
       "xfa/fwl/core/fwl_widgethit.h",
       "xfa/fwl/core/ifwl_adaptertimermgr.h",
-      "xfa/fwl/core/ifwl_barcode.cpp",
-      "xfa/fwl/core/ifwl_barcode.h",
-      "xfa/fwl/core/ifwl_checkbox.cpp",
-      "xfa/fwl/core/ifwl_checkbox.h",
-      "xfa/fwl/core/ifwl_combobox.cpp",
-      "xfa/fwl/core/ifwl_combobox.h",
-      "xfa/fwl/core/ifwl_datetimepicker.cpp",
-      "xfa/fwl/core/ifwl_datetimepicker.h",
-      "xfa/fwl/core/ifwl_edit.cpp",
-      "xfa/fwl/core/ifwl_edit.h",
-      "xfa/fwl/core/ifwl_listbox.cpp",
-      "xfa/fwl/core/ifwl_listbox.h",
-      "xfa/fwl/core/ifwl_picturebox.cpp",
-      "xfa/fwl/core/ifwl_picturebox.h",
-      "xfa/fwl/core/ifwl_pushbutton.cpp",
-      "xfa/fwl/core/ifwl_pushbutton.h",
       "xfa/fwl/core/ifwl_themeprovider.h",
-      "xfa/fwl/core/ifwl_widget.cpp",
-      "xfa/fwl/core/ifwl_widget.h",
       "xfa/fwl/core/ifwl_widgetdelegate.h",
       "xfa/fwl/core/ifwl_widgetmgrdelegate.h",
       "xfa/fwl/theme/cfwl_arrowdata.cpp",
diff --git a/xfa/fde/cfde_txtedtdorecord_deleterange.cpp b/xfa/fde/cfde_txtedtdorecord_deleterange.cpp
index 3045927..12ab203 100644
--- a/xfa/fde/cfde_txtedtdorecord_deleterange.cpp
+++ b/xfa/fde/cfde_txtedtdorecord_deleterange.cpp
@@ -7,7 +7,7 @@
 #include "xfa/fde/cfde_txtedtdorecord_deleterange.h"
 
 #include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fwl/core/ifwl_edit.h"
+#include "xfa/fwl/core/cfwl_edit.h"
 
 CFDE_TxtEdtDoRecord_DeleteRange::CFDE_TxtEdtDoRecord_DeleteRange(
     CFDE_TxtEdtEngine* pEngine,
diff --git a/xfa/fde/cfde_txtedtdorecord_insert.cpp b/xfa/fde/cfde_txtedtdorecord_insert.cpp
index 1fa3bbc..3ea9269 100644
--- a/xfa/fde/cfde_txtedtdorecord_insert.cpp
+++ b/xfa/fde/cfde_txtedtdorecord_insert.cpp
@@ -7,7 +7,7 @@
 #include "xfa/fde/cfde_txtedtdorecord_insert.h"
 
 #include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fwl/core/ifwl_edit.h"
+#include "xfa/fwl/core/cfwl_edit.h"
 
 CFDE_TxtEdtDoRecord_Insert::CFDE_TxtEdtDoRecord_Insert(
     CFDE_TxtEdtEngine* pEngine,
diff --git a/xfa/fde/cfde_txtedtengine.cpp b/xfa/fde/cfde_txtedtengine.cpp
index ad20b04..3b3caf6 100644
--- a/xfa/fde/cfde_txtedtengine.cpp
+++ b/xfa/fde/cfde_txtedtengine.cpp
@@ -17,7 +17,7 @@
 #include "xfa/fde/ifx_chariter.h"
 #include "xfa/fde/tto/fde_textout.h"
 #include "xfa/fgas/layout/fgas_textbreak.h"
-#include "xfa/fwl/core/ifwl_edit.h"
+#include "xfa/fwl/core/cfwl_edit.h"
 
 namespace {
 
diff --git a/xfa/fde/ifde_txtedtengine.h b/xfa/fde/ifde_txtedtengine.h
index 391449c..56b8daa 100644
--- a/xfa/fde/ifde_txtedtengine.h
+++ b/xfa/fde/ifde_txtedtengine.h
@@ -12,7 +12,7 @@
 
 class CFDE_TxtEdtEngine;
 class IFDE_TxtEdtPage;
-class IFWL_Edit;
+class CFWL_Edit;
 
 #define FDE_TEXTEDITMODE_MultiLines (1L << 0)
 #define FDE_TEXTEDITMODE_AutoLineWrap (1L << 1)
@@ -102,7 +102,7 @@
   int32_t nLineEnd;
   int32_t nHorzScale;
   FX_FLOAT fCharSpace;
-  IFWL_Edit* pEventSink;
+  CFWL_Edit* pEventSink;
 };
 
 enum FDE_TXTEDT_TEXTCHANGE_TYPE {
diff --git a/xfa/fwl/core/cfwl_app.cpp b/xfa/fwl/core/cfwl_app.cpp
index 4905e23..fd4bb08 100644
--- a/xfa/fwl/core/cfwl_app.cpp
+++ b/xfa/fwl/core/cfwl_app.cpp
@@ -8,8 +8,8 @@
 
 #include "third_party/base/ptr_util.h"
 #include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxfa/app/xfa_fwladapter.h"
 
 CFWL_App::CFWL_App(CXFA_FFApp* pAdapter)
diff --git a/xfa/fwl/core/cfwl_app.h b/xfa/fwl/core/cfwl_app.h
index 28ed8a4..26b514a 100644
--- a/xfa/fwl/core/cfwl_app.h
+++ b/xfa/fwl/core/cfwl_app.h
@@ -15,7 +15,7 @@
 class CFWL_WidgetMgr;
 class CXFA_FFApp;
 class CXFA_FWLAdapterWidgetMgr;
-class IFWL_Widget;
+class CFWL_Widget;
 
 enum FWL_KeyFlag {
   FWL_KEYFLAG_Ctrl = 1 << 0,
diff --git a/xfa/fwl/core/cfwl_barcode.cpp b/xfa/fwl/core/cfwl_barcode.cpp
index 49e417e..18cf71e 100644
--- a/xfa/fwl/core/cfwl_barcode.cpp
+++ b/xfa/fwl/core/cfwl_barcode.cpp
@@ -6,33 +6,93 @@
 
 #include "xfa/fwl/core/cfwl_barcode.h"
 
-#include <memory>
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
-
-namespace {
-
-IFWL_Barcode* ToBarcode(IFWL_Widget* widget) {
-  return static_cast<IFWL_Barcode*>(widget);
-}
-
-}  // namespace
+#include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
+#include "xfa/fwl/core/cfx_barcode.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
 
 CFWL_Barcode::CFWL_Barcode(const CFWL_App* app)
-    : CFWL_Edit(app), m_dwAttributeMask(FWL_BCDATTRIBUTE_NONE) {}
+    : CFWL_Edit(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
+      m_dwStatus(0),
+      m_type(BC_UNKNOWN),
+      m_dwAttributeMask(FWL_BCDATTRIBUTE_NONE) {}
 
 CFWL_Barcode::~CFWL_Barcode() {}
 
-void CFWL_Barcode::Initialize() {
-  ASSERT(!m_pIface);
+FWL_Type CFWL_Barcode::GetClassID() const {
+  return FWL_Type::Barcode;
+}
 
-  auto iface = pdfium::MakeUnique<IFWL_Barcode>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
-  iface->SetDataProvider(this);
-  m_pIface = std::move(iface);
+void CFWL_Barcode::Update() {
+  if (IsLocked())
+    return;
 
-  CFWL_Widget::Initialize();
+  CFWL_Edit::Update();
+  GenerateBarcodeImageCache();
+}
+
+void CFWL_Barcode::DrawWidget(CFX_Graphics* pGraphics,
+                              const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
+    GenerateBarcodeImageCache();
+    if (!m_pBarcodeEngine || (m_dwStatus & XFA_BCS_EncodeSuccess) == 0)
+      return;
+
+    CFX_Matrix mt;
+    mt.e = GetRTClient().left;
+    mt.f = GetRTClient().top;
+    if (pMatrix)
+      mt.Concat(*pMatrix);
+
+    int32_t errorCode = 0;
+    m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), pMatrix,
+                                   errorCode);
+    return;
+  }
+  CFWL_Edit::DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_Barcode::SetType(BC_TYPE type) {
+  if (m_type == type)
+    return;
+
+  m_pBarcodeEngine.reset();
+  m_type = type;
+  m_dwStatus = XFA_BCS_NeedUpdate;
+}
+
+void CFWL_Barcode::SetText(const CFX_WideString& wsText) {
+  m_pBarcodeEngine.reset();
+  m_dwStatus = XFA_BCS_NeedUpdate;
+  CFWL_Edit::SetText(wsText);
+}
+
+bool CFWL_Barcode::IsProtectedType() const {
+  if (!m_pBarcodeEngine)
+    return true;
+
+  BC_TYPE tEngineType = m_pBarcodeEngine->GetType();
+  if (tEngineType == BC_QR_CODE || tEngineType == BC_PDF417 ||
+      tEngineType == BC_DATAMATRIX) {
+    return true;
+  }
+  return false;
+}
+
+void CFWL_Barcode::OnProcessEvent(CFWL_Event* pEvent) {
+  if (pEvent->GetClassID() == CFWL_EventType::TextChanged) {
+    m_pBarcodeEngine.reset();
+    m_dwStatus = XFA_BCS_NeedUpdate;
+  }
+  CFWL_Edit::OnProcessEvent(pEvent);
 }
 
 void CFWL_Barcode::SetCharEncoding(BC_CHAR_ENCODING encoding) {
@@ -53,7 +113,7 @@
 void CFWL_Barcode::SetDataLength(int32_t dataLength) {
   m_dwAttributeMask |= FWL_BCDATTRIBUTE_DATALENGTH;
   m_nDataLength = dataLength;
-  ToBarcode(GetWidget())->SetLimit(dataLength);
+  SetLimit(dataLength);
 }
 
 void CFWL_Barcode::SetCalChecksum(bool calChecksum) {
@@ -96,67 +156,78 @@
   m_bTruncated = truncated;
 }
 
-void CFWL_Barcode::SetType(BC_TYPE type) {
-  if (GetWidget())
-    ToBarcode(GetWidget())->SetType(type);
+void CFWL_Barcode::GenerateBarcodeImageCache() {
+  if ((m_dwStatus & XFA_BCS_NeedUpdate) == 0)
+    return;
+
+  m_dwStatus = 0;
+  CreateBarcodeEngine();
+  if (!m_pBarcodeEngine)
+    return;
+
+  CFX_WideString wsText;
+  GetText(wsText);
+
+  CFWL_ThemePart part;
+  part.m_pWidget = this;
+
+  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
+  CFGAS_GEFont* pFont = static_cast<CFGAS_GEFont*>(
+      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::Font));
+  CFX_Font* pCXFont = pFont ? pFont->GetDevFont() : nullptr;
+  if (pCXFont)
+    m_pBarcodeEngine->SetFont(pCXFont);
+
+  FX_FLOAT* pFontSize = static_cast<FX_FLOAT*>(
+      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::FontSize));
+  if (pFontSize)
+    m_pBarcodeEngine->SetFontSize(*pFontSize);
+
+  FX_ARGB* pFontColor = static_cast<FX_ARGB*>(
+      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::TextColor));
+  if (pFontColor)
+    m_pBarcodeEngine->SetFontColor(*pFontColor);
+
+  m_pBarcodeEngine->SetHeight(int32_t(GetRTClient().height));
+  m_pBarcodeEngine->SetWidth(int32_t(GetRTClient().width));
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_CHARENCODING)
+    m_pBarcodeEngine->SetCharEncoding(m_eCharEncoding);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_MODULEHEIGHT)
+    m_pBarcodeEngine->SetModuleHeight(m_nModuleHeight);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_MODULEWIDTH)
+    m_pBarcodeEngine->SetModuleWidth(m_nModuleWidth);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_DATALENGTH)
+    m_pBarcodeEngine->SetDataLength(m_nDataLength);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_CALCHECKSUM)
+    m_pBarcodeEngine->SetCalChecksum(m_bCalChecksum);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_PRINTCHECKSUM)
+    m_pBarcodeEngine->SetPrintChecksum(m_bPrintChecksum);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_TEXTLOCATION)
+    m_pBarcodeEngine->SetTextLocation(m_eTextLocation);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_WIDENARROWRATIO)
+    m_pBarcodeEngine->SetWideNarrowRatio(m_nWideNarrowRatio);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_STARTCHAR)
+    m_pBarcodeEngine->SetStartChar(m_cStartChar);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_ENDCHAR)
+    m_pBarcodeEngine->SetEndChar(m_cEndChar);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_VERSION)
+    m_pBarcodeEngine->SetVersion(0);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_ECLEVEL)
+    m_pBarcodeEngine->SetErrorCorrectionLevel(m_nECLevel);
+  if (m_dwAttributeMask & FWL_BCDATTRIBUTE_TRUNCATED)
+    m_pBarcodeEngine->SetTruncated(m_bTruncated);
+
+  int32_t errorCode = 0;
+  m_dwStatus = m_pBarcodeEngine->Encode(wsText.AsStringC(), true, errorCode)
+                   ? XFA_BCS_EncodeSuccess
+                   : 0;
 }
 
-bool CFWL_Barcode::IsProtectedType() {
-  return GetWidget() ? ToBarcode(GetWidget())->IsProtectedType() : false;
-}
+void CFWL_Barcode::CreateBarcodeEngine() {
+  if (m_pBarcodeEngine || m_type == BC_UNKNOWN)
+    return;
 
-BC_CHAR_ENCODING CFWL_Barcode::GetCharEncoding() const {
-  return m_eCharEncoding;
-}
-
-int32_t CFWL_Barcode::GetModuleHeight() const {
-  return m_nModuleHeight;
-}
-
-int32_t CFWL_Barcode::GetModuleWidth() const {
-  return m_nModuleWidth;
-}
-
-int32_t CFWL_Barcode::GetDataLength() const {
-  return m_nDataLength;
-}
-
-bool CFWL_Barcode::GetCalChecksum() const {
-  return m_bCalChecksum;
-}
-
-bool CFWL_Barcode::GetPrintChecksum() const {
-  return m_bPrintChecksum;
-}
-
-BC_TEXT_LOC CFWL_Barcode::GetTextLocation() const {
-  return m_eTextLocation;
-}
-
-int32_t CFWL_Barcode::GetWideNarrowRatio() const {
-  return m_nWideNarrowRatio;
-}
-
-FX_CHAR CFWL_Barcode::GetStartChar() const {
-  return m_cStartChar;
-}
-
-FX_CHAR CFWL_Barcode::GetEndChar() const {
-  return m_cEndChar;
-}
-
-int32_t CFWL_Barcode::GetVersion() const {
-  return 0;
-}
-
-int32_t CFWL_Barcode::GetErrorCorrectionLevel() const {
-  return m_nECLevel;
-}
-
-bool CFWL_Barcode::GetTruncated() const {
-  return m_bTruncated;
-}
-
-uint32_t CFWL_Barcode::GetBarcodeAttributeMask() const {
-  return m_dwAttributeMask;
+  std::unique_ptr<CFX_Barcode> pBarcode(new CFX_Barcode);
+  if (pBarcode->Create(m_type))
+    m_pBarcodeEngine = std::move(pBarcode);
 }
diff --git a/xfa/fwl/core/cfwl_barcode.h b/xfa/fwl/core/cfwl_barcode.h
index 90dfdca..05c2375 100644
--- a/xfa/fwl/core/cfwl_barcode.h
+++ b/xfa/fwl/core/cfwl_barcode.h
@@ -7,35 +7,54 @@
 #ifndef XFA_FWL_CORE_CFWL_BARCODE_H_
 #define XFA_FWL_CORE_CFWL_BARCODE_H_
 
-#include "xfa/fwl/core/cfwl_edit.h"
-#include "xfa/fwl/core/fwl_error.h"
-#include "xfa/fwl/core/ifwl_barcode.h"
+#include <memory>
 
-class CFWL_Barcode : public CFWL_Edit, public IFWL_Barcode::DataProvider {
+#include "xfa/fwl/core/cfwl_edit.h"
+#include "xfa/fwl/core/cfwl_scrollbar.h"
+#include "xfa/fwl/core/cfwl_widget.h"
+#include "xfa/fxbarcode/BC_Library.h"
+
+class CFWL_WidgetProperties;
+class CFX_Barcode;
+class CFWL_Widget;
+
+#define XFA_BCS_NeedUpdate 0x0001
+#define XFA_BCS_EncodeSuccess 0x0002
+
+enum FWL_BCDAttribute {
+  FWL_BCDATTRIBUTE_NONE = 0,
+  FWL_BCDATTRIBUTE_CHARENCODING = 1 << 0,
+  FWL_BCDATTRIBUTE_MODULEHEIGHT = 1 << 1,
+  FWL_BCDATTRIBUTE_MODULEWIDTH = 1 << 2,
+  FWL_BCDATTRIBUTE_DATALENGTH = 1 << 3,
+  FWL_BCDATTRIBUTE_CALCHECKSUM = 1 << 4,
+  FWL_BCDATTRIBUTE_PRINTCHECKSUM = 1 << 5,
+  FWL_BCDATTRIBUTE_TEXTLOCATION = 1 << 6,
+  FWL_BCDATTRIBUTE_WIDENARROWRATIO = 1 << 7,
+  FWL_BCDATTRIBUTE_STARTCHAR = 1 << 8,
+  FWL_BCDATTRIBUTE_ENDCHAR = 1 << 9,
+  FWL_BCDATTRIBUTE_VERSION = 1 << 10,
+  FWL_BCDATTRIBUTE_ECLEVEL = 1 << 11,
+  FWL_BCDATTRIBUTE_TRUNCATED = 1 << 12
+};
+
+class CFWL_Barcode : public CFWL_Edit {
  public:
   explicit CFWL_Barcode(const CFWL_App* pApp);
   ~CFWL_Barcode() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void Update() override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void OnProcessEvent(CFWL_Event* pEvent) override;
 
-  // IFWL_Barcode::DataProvider
-  BC_CHAR_ENCODING GetCharEncoding() const override;
-  int32_t GetModuleHeight() const override;
-  int32_t GetModuleWidth() const override;
-  int32_t GetDataLength() const override;
-  bool GetCalChecksum() const override;
-  bool GetPrintChecksum() const override;
-  BC_TEXT_LOC GetTextLocation() const override;
-  int32_t GetWideNarrowRatio() const override;
-  FX_CHAR GetStartChar() const override;
-  FX_CHAR GetEndChar() const override;
-  int32_t GetVersion() const override;
-  int32_t GetErrorCorrectionLevel() const override;
-  bool GetTruncated() const override;
-  uint32_t GetBarcodeAttributeMask() const override;
+  // CFWL_Edit
+  void SetText(const CFX_WideString& wsText) override;
 
   void SetType(BC_TYPE type);
-  bool IsProtectedType();
+  bool IsProtectedType() const;
 
   void SetCharEncoding(BC_CHAR_ENCODING encoding);
   void SetModuleHeight(int32_t height);
@@ -51,6 +70,12 @@
   void SetTruncated(bool truncated);
 
  private:
+  void GenerateBarcodeImageCache();
+  void CreateBarcodeEngine();
+
+  std::unique_ptr<CFX_Barcode> m_pBarcodeEngine;
+  uint32_t m_dwStatus;
+  BC_TYPE m_type;
   BC_CHAR_ENCODING m_eCharEncoding;
   int32_t m_nModuleHeight;
   int32_t m_nModuleWidth;
diff --git a/xfa/fwl/core/cfwl_caret.cpp b/xfa/fwl/core/cfwl_caret.cpp
index 97cf1e9..b4ebf2c 100644
--- a/xfa/fwl/core/cfwl_caret.cpp
+++ b/xfa/fwl/core/cfwl_caret.cpp
@@ -23,8 +23,8 @@
 
 CFWL_Caret::CFWL_Caret(const CFWL_App* app,
                        std::unique_ptr<CFWL_WidgetProperties> properties,
-                       IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
+                       CFWL_Widget* pOuter)
+    : CFWL_Widget(app, std::move(properties), pOuter),
       m_pTimer(new CFWL_Caret::Timer(this)),
       m_pTimerInfo(nullptr) {
   SetStates(FWL_STATE_CAT_HightLight);
diff --git a/xfa/fwl/core/cfwl_caret.h b/xfa/fwl/core/cfwl_caret.h
index 9e68cdf..ad38f7a 100644
--- a/xfa/fwl/core/cfwl_caret.h
+++ b/xfa/fwl/core/cfwl_caret.h
@@ -10,22 +10,22 @@
 #include <memory>
 
 #include "xfa/fwl/core/cfwl_timer.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 
 class CFWL_WidgetProperties;
-class IFWL_Widget;
+class CFWL_Widget;
 
 #define FWL_STATE_CAT_HightLight 1
 
-class CFWL_Caret : public IFWL_Widget {
+class CFWL_Caret : public CFWL_Widget {
  public:
   CFWL_Caret(const CFWL_App* app,
              std::unique_ptr<CFWL_WidgetProperties> properties,
-             IFWL_Widget* pOuter);
+             CFWL_Widget* pOuter);
   ~CFWL_Caret() override;
 
-  // IFWL_Widget
+  // CFWL_Widget
   FWL_Type GetClassID() const override;
   void DrawWidget(CFX_Graphics* pGraphics,
                   const CFX_Matrix* pMatrix = nullptr) override;
diff --git a/xfa/fwl/core/cfwl_checkbox.cpp b/xfa/fwl/core/cfwl_checkbox.cpp
index 5053d2f..cdd8211 100644
--- a/xfa/fwl/core/cfwl_checkbox.cpp
+++ b/xfa/fwl/core/cfwl_checkbox.cpp
@@ -6,32 +6,480 @@
 
 #include "xfa/fwl/core/cfwl_checkbox.h"
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
-#include "xfa/fwl/core/fwl_error.h"
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_evtcheckstatechanged.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/cfwl_widgetmgr.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
+
+namespace {
+
+const int kCaptionMargin = 5;
+
+}  // namespace
 
 CFWL_CheckBox::CFWL_CheckBox(const CFWL_App* app)
-    : CFWL_Widget(app), m_fBoxHeight(16.0f) {}
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
+      m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
+      m_iTTOAlign(FDE_TTOALIGNMENT_Center),
+      m_bBtnDown(false),
+      m_fBoxHeight(16.0f) {
+  m_rtClient.Reset();
+  m_rtBox.Reset();
+  m_rtCaption.Reset();
+  m_rtFocus.Reset();
+}
 
 CFWL_CheckBox::~CFWL_CheckBox() {}
 
-void CFWL_CheckBox::Initialize() {
-  ASSERT(!m_pIface);
-
-  auto iface = pdfium::MakeUnique<IFWL_CheckBox>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
-  iface->SetDataProvider(this);
-  m_pIface = std::move(iface);
-
-  CFWL_Widget::Initialize();
+FWL_Type CFWL_CheckBox::GetClassID() const {
+  return FWL_Type::CheckBox;
 }
 
 void CFWL_CheckBox::SetBoxSize(FX_FLOAT fHeight) {
   m_fBoxHeight = fHeight;
 }
 
-FX_FLOAT CFWL_CheckBox::GetBoxSize(IFWL_Widget* pWidget) {
-  return m_fBoxHeight;
+void CFWL_CheckBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  rect.Set(0, 0, 0, 0);
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  CFX_SizeF sz = CalcTextSize(
+      L"Check box", m_pProperties->m_pThemeProvider,
+      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine));
+  rect.Set(0, 0, sz.x, sz.y);
+  rect.Inflate(kCaptionMargin, kCaptionMargin);
+
+  rect.width += m_fBoxHeight;
+  rect.height = std::max(rect.height, m_fBoxHeight);
+  CFWL_Widget::GetWidgetRect(rect, true);
+}
+
+void CFWL_CheckBox::Update() {
+  if (IsLocked())
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  UpdateTextOutStyles();
+  Layout();
+}
+
+void CFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  if (HasBorder()) {
+    DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
+               pMatrix);
+  }
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+
+  int32_t dwStates = GetPartStates();
+
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = CFWL_Part::Background;
+  param.m_dwStates = dwStates;
+  param.m_pGraphics = pGraphics;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix);
+  param.m_rtPart = m_rtClient;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+    param.m_pData = &m_rtFocus;
+  pTheme->DrawBackground(&param);
+
+  param.m_iPart = CFWL_Part::CheckBox;
+  param.m_rtPart = m_rtBox;
+  pTheme->DrawBackground(&param);
+
+  CFWL_ThemeText textParam;
+  textParam.m_pWidget = this;
+  textParam.m_iPart = CFWL_Part::Caption;
+  textParam.m_dwStates = dwStates;
+  textParam.m_pGraphics = pGraphics;
+  if (pMatrix)
+    textParam.m_matrix.Concat(*pMatrix);
+  textParam.m_rtPart = m_rtCaption;
+  textParam.m_wsText = L"Check box";
+  textParam.m_dwTTOStyles = m_dwTTOStyles;
+  textParam.m_iTTOAlign = m_iTTOAlign;
+  pTheme->DrawText(&textParam);
+}
+
+void CFWL_CheckBox::SetCheckState(int32_t iCheck) {
+  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
+  switch (iCheck) {
+    case 1:
+      m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
+      break;
+    case 2:
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;
+      break;
+    default:
+      break;
+  }
+  Repaint(&m_rtClient);
+}
+
+void CFWL_CheckBox::Layout() {
+  m_pProperties->m_rtWidget.width =
+      FXSYS_round(m_pProperties->m_rtWidget.width);
+  m_pProperties->m_rtWidget.height =
+      FXSYS_round(m_pProperties->m_rtWidget.height);
+  GetClientRect(m_rtClient);
+
+  FX_FLOAT fBoxTop = m_rtClient.top;
+  FX_FLOAT fClientBottom = m_rtClient.bottom();
+
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) {
+    case FWL_STYLEEXT_CKB_Top:
+      break;
+    case FWL_STYLEEXT_CKB_Bottom: {
+      fBoxTop = fClientBottom - m_fBoxHeight;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_VCenter:
+    default: {
+      fBoxTop = m_rtClient.top + (m_rtClient.height - m_fBoxHeight) / 2;
+      fBoxTop = FXSYS_floor(fBoxTop);
+      break;
+    }
+  }
+
+  FX_FLOAT fBoxLeft = m_rtClient.left;
+  FX_FLOAT fTextLeft = 0.0;
+  FX_FLOAT fTextRight = 0.0;
+  FX_FLOAT fClientRight = m_rtClient.right();
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_LeftText) {
+    fBoxLeft = fClientRight - m_fBoxHeight;
+    fTextLeft = m_rtClient.left;
+    fTextRight = fBoxLeft;
+  } else {
+    fTextLeft = fBoxLeft + m_fBoxHeight;
+    fTextRight = fClientRight;
+  }
+  m_rtBox.Set(fBoxLeft, fBoxTop, m_fBoxHeight, m_fBoxHeight);
+  m_rtCaption.Set(fTextLeft, m_rtClient.top, fTextRight - fTextLeft,
+                  m_rtClient.height);
+  m_rtCaption.Inflate(-kCaptionMargin, -kCaptionMargin);
+
+  CFX_RectF rtFocus;
+  rtFocus.Set(m_rtCaption.left, m_rtCaption.top, m_rtCaption.width,
+              m_rtCaption.height);
+
+  CalcTextRect(L"Check box", m_pProperties->m_pThemeProvider, m_dwTTOStyles,
+               m_iTTOAlign, rtFocus);
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) == 0) {
+    FX_FLOAT fWidth = std::max(m_rtCaption.width, rtFocus.width);
+    FX_FLOAT fHeight = std::min(m_rtCaption.height, rtFocus.height);
+    FX_FLOAT fLeft = m_rtCaption.left;
+    FX_FLOAT fTop = m_rtCaption.top;
+    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) ==
+        FWL_STYLEEXT_CKB_Center) {
+      fLeft = m_rtCaption.left + (m_rtCaption.width - fWidth) / 2;
+    } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) ==
+               FWL_STYLEEXT_CKB_Right) {
+      fLeft = m_rtCaption.right() - fWidth;
+    }
+    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) ==
+        FWL_STYLEEXT_CKB_VCenter) {
+      fTop = m_rtCaption.top + (m_rtCaption.height - fHeight) / 2;
+    } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) ==
+               FWL_STYLEEXT_CKB_Bottom) {
+      fTop = m_rtCaption.bottom() - fHeight;
+    }
+    m_rtFocus.Set(fLeft, fTop, fWidth, fHeight);
+  } else {
+    m_rtFocus.Set(rtFocus.left, rtFocus.top, rtFocus.width, rtFocus.height);
+  }
+  m_rtFocus.Inflate(1, 1);
+}
+
+uint32_t CFWL_CheckBox::GetPartStates() const {
+  int32_t dwStates = CFWL_PartState_Normal;
+  if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
+      FWL_STATE_CKB_Neutral) {
+    dwStates = CFWL_PartState_Neutral;
+  } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
+             FWL_STATE_CKB_Checked) {
+    dwStates = CFWL_PartState_Checked;
+  }
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    dwStates |= CFWL_PartState_Disabled;
+  else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)
+    dwStates |= CFWL_PartState_Hovered;
+  else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed)
+    dwStates |= CFWL_PartState_Pressed;
+  else
+    dwStates |= CFWL_PartState_Normal;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+    dwStates |= CFWL_PartState_Focused;
+  return dwStates;
+}
+
+void CFWL_CheckBox::UpdateTextOutStyles() {
+  switch (m_pProperties->m_dwStyleExes &
+          (FWL_STYLEEXT_CKB_HLayoutMask | FWL_STYLEEXT_CKB_VLayoutMask)) {
+    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_VCenter: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_VCenter: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;
+      break;
+    }
+    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_VCenter:
+    default: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_Center;
+      break;
+    }
+  }
+  m_dwTTOStyles = 0;
+  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
+    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine)
+    m_dwTTOStyles |= FDE_TTOSTYLE_LineWrap;
+  else
+    m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;
+}
+
+void CFWL_CheckBox::NextStates() {
+  uint32_t dwFirststate = m_pProperties->m_dwStates;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton) {
+    if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
+        FWL_STATE_CKB_Unchecked) {
+      CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
+      if (!pWidgetMgr->IsFormDisabled()) {
+        CFX_ArrayTemplate<CFWL_Widget*> radioarr;
+        pWidgetMgr->GetSameGroupRadioButton(this, radioarr);
+        CFWL_CheckBox* pCheckBox = nullptr;
+        int32_t iCount = radioarr.GetSize();
+        for (int32_t i = 0; i < iCount; i++) {
+          pCheckBox = static_cast<CFWL_CheckBox*>(radioarr[i]);
+          if (pCheckBox != this &&
+              pCheckBox->GetStates() & FWL_STATE_CKB_Checked) {
+            pCheckBox->SetCheckState(0);
+            CFX_RectF rt;
+            pCheckBox->GetWidgetRect(rt);
+            rt.left = rt.top = 0;
+            m_pWidgetMgr->RepaintWidget(pCheckBox, &rt);
+            break;
+          }
+        }
+      }
+      m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
+    }
+  } else {
+    if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
+        FWL_STATE_CKB_Neutral) {
+      m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
+    } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
+               FWL_STATE_CKB_Checked) {
+      m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
+    } else {
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;
+      else
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
+    }
+  }
+
+  Repaint(&m_rtClient);
+  if (dwFirststate == m_pProperties->m_dwStates)
+    return;
+
+  CFWL_EvtCheckStateChanged wmCheckBoxState;
+  wmCheckBoxState.m_pSrcTarget = this;
+  DispatchEvent(&wmCheckBoxState);
+}
+
+void CFWL_CheckBox::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+
+  switch (pMessage->GetClassID()) {
+    case CFWL_MessageType::SetFocus:
+      OnFocusChanged(true);
+      break;
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(false);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown();
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        case FWL_MouseCommand::Move:
+          OnMouseMove(pMsg);
+          break;
+        case FWL_MouseCommand::Leave:
+          OnMouseLeave();
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
+      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
+        OnKeyDown(pKey);
+      break;
+    }
+    default:
+      break;
+  }
+
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_CheckBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                 const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_CheckBox::OnFocusChanged(bool bSet) {
+  if (bSet)
+    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
+  else
+    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
+
+  Repaint(&m_rtClient);
+}
+
+void CFWL_CheckBox::OnLButtonDown() {
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    return;
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    SetFocus(true);
+
+  m_bBtnDown = true;
+  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
+  m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;
+  Repaint(&m_rtClient);
+}
+
+void CFWL_CheckBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  if (!m_bBtnDown)
+    return;
+
+  m_bBtnDown = false;
+  if (!m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy))
+    return;
+
+  m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
+  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;
+  NextStates();
+}
+
+void CFWL_CheckBox::OnMouseMove(CFWL_MsgMouse* pMsg) {
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    return;
+
+  bool bRepaint = false;
+  if (m_bBtnDown) {
+    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
+      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) == 0) {
+        bRepaint = true;
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;
+      }
+      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)) {
+        bRepaint = true;
+        m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
+      }
+    } else {
+      if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) {
+        bRepaint = true;
+        m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;
+      }
+      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {
+        bRepaint = true;
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
+      }
+    }
+  } else {
+    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
+      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {
+        bRepaint = true;
+        m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
+      }
+    }
+  }
+  if (bRepaint)
+    Repaint(&m_rtBox);
+}
+
+void CFWL_CheckBox::OnMouseLeave() {
+  if (m_bBtnDown)
+    m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
+  else
+    m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
+
+  Repaint(&m_rtBox);
+}
+
+void CFWL_CheckBox::OnKeyDown(CFWL_MsgKey* pMsg) {
+  if (pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
+    DispatchKeyEvent(pMsg);
+    return;
+  }
+  if (pMsg->m_dwKeyCode == FWL_VKEY_Return ||
+      pMsg->m_dwKeyCode == FWL_VKEY_Space) {
+    NextStates();
+  }
 }
diff --git a/xfa/fwl/core/cfwl_checkbox.h b/xfa/fwl/core/cfwl_checkbox.h
index dd1db68..71497a3 100644
--- a/xfa/fwl/core/cfwl_checkbox.h
+++ b/xfa/fwl/core/cfwl_checkbox.h
@@ -7,22 +7,85 @@
 #ifndef XFA_FWL_CORE_CFWL_CHECKBOX_H_
 #define XFA_FWL_CORE_CFWL_CHECKBOX_H_
 
-#include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_checkbox.h"
+#include <memory>
 
-class CFWL_CheckBox : public CFWL_Widget, public IFWL_CheckBox::DataProvider {
+#include "xfa/fwl/core/cfwl_event.h"
+#include "xfa/fwl/core/cfwl_widget.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
+
+#define FWL_STYLEEXT_CKB_Left (0L << 0)
+#define FWL_STYLEEXT_CKB_Center (1L << 0)
+#define FWL_STYLEEXT_CKB_Right (2L << 0)
+#define FWL_STYLEEXT_CKB_Top (0L << 2)
+#define FWL_STYLEEXT_CKB_VCenter (1L << 2)
+#define FWL_STYLEEXT_CKB_Bottom (2L << 2)
+#define FWL_STYLEEXT_CKB_LeftText (1L << 4)
+#define FWL_STYLEEXT_CKB_MultiLine (1L << 5)
+#define FWL_STYLEEXT_CKB_3State (1L << 6)
+#define FWL_STYLEEXT_CKB_RadioButton (1L << 7)
+#define FWL_STYLEEXT_CKB_ShapeSolidSquare (0L << 8)
+#define FWL_STYLEEXT_CKB_ShapeSunkenSquare (1L << 8)
+#define FWL_STYLEEXT_CKB_ShapeSolidCircle (2L << 8)
+#define FWL_STYLEEXT_CKB_ShapeSunkenCircle (3L << 8)
+#define FWL_STYLEEXT_CKB_SignShapeCheck (0L << 10)
+#define FWL_STYLEEXT_CKB_SignShapeCircle (1L << 10)
+#define FWL_STYLEEXT_CKB_SignShapeCross (2L << 10)
+#define FWL_STYLEEXT_CKB_SignShapeDiamond (3L << 10)
+#define FWL_STYLEEXT_CKB_SignShapeSquare (4L << 10)
+#define FWL_STYLEEXT_CKB_SignShapeStar (5L << 10)
+#define FWL_STYLEEXT_CKB_HLayoutMask (3L << 0)
+#define FWL_STYLEEXT_CKB_VLayoutMask (3L << 2)
+#define FWL_STYLEEXT_CKB_ShapeMask (3L << 8)
+#define FWL_STYLEEXT_CKB_SignShapeMask (7L << 10)
+#define FWL_STATE_CKB_Hovered (1 << FWL_WGTSTATE_MAX)
+#define FWL_STATE_CKB_Pressed (1 << (FWL_WGTSTATE_MAX + 1))
+#define FWL_STATE_CKB_Unchecked (0 << (FWL_WGTSTATE_MAX + 2))
+#define FWL_STATE_CKB_Checked (1 << (FWL_WGTSTATE_MAX + 2))
+#define FWL_STATE_CKB_Neutral (2 << (FWL_WGTSTATE_MAX + 2))
+#define FWL_STATE_CKB_CheckMask (3L << (FWL_WGTSTATE_MAX + 2))
+
+class CFWL_MsgMouse;
+class CFWL_WidgetProperties;
+class CFWL_Widget;
+
+class CFWL_CheckBox : public CFWL_Widget {
  public:
   explicit CFWL_CheckBox(const CFWL_App* pApp);
   ~CFWL_CheckBox() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void Update() override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
 
-  // IFWL_CheckBox::DataProvider
-  FX_FLOAT GetBoxSize(IFWL_Widget* pWidget) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
 
   void SetBoxSize(FX_FLOAT fHeight);
 
  private:
+  void SetCheckState(int32_t iCheck);
+  void Layout();
+  uint32_t GetPartStates() const;
+  void UpdateTextOutStyles();
+  void NextStates();
+  void OnFocusChanged(bool bSet);
+  void OnLButtonDown();
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnMouseMove(CFWL_MsgMouse* pMsg);
+  void OnMouseLeave();
+  void OnKeyDown(CFWL_MsgKey* pMsg);
+
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtBox;
+  CFX_RectF m_rtCaption;
+  CFX_RectF m_rtFocus;
+  uint32_t m_dwTTOStyles;
+  int32_t m_iTTOAlign;
+  bool m_bBtnDown;
   FX_FLOAT m_fBoxHeight;
 };
 
diff --git a/xfa/fwl/core/cfwl_combobox.cpp b/xfa/fwl/core/cfwl_combobox.cpp
index 532f49f..b7be67d 100644
--- a/xfa/fwl/core/cfwl_combobox.cpp
+++ b/xfa/fwl/core/cfwl_combobox.cpp
@@ -6,144 +6,1124 @@
 
 #include "xfa/fwl/core/cfwl_combobox.h"
 
+#include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
-#include "xfa/fwl/core/fwl_error.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fde/cfde_txtedtengine.h"
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_evteditchanged.h"
+#include "xfa/fwl/core/cfwl_evtpostdropdown.h"
+#include "xfa/fwl/core/cfwl_evtpredropdown.h"
+#include "xfa/fwl/core/cfwl_evtselectchanged.h"
+#include "xfa/fwl/core/cfwl_evttextchanged.h"
+#include "xfa/fwl/core/cfwl_formproxy.h"
+#include "xfa/fwl/core/cfwl_listbox.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgkillfocus.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_msgsetfocus.h"
+#include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
+#include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/cfwl_widgetmgr.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
 
-namespace {
+CFWL_ComboBox::CFWL_ComboBox(const CFWL_App* app)
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
+      m_pComboBoxProxy(nullptr),
+      m_bLButtonDown(false),
+      m_iCurSel(-1),
+      m_iBtnState(CFWL_PartState_Normal),
+      m_fComboFormHandler(0) {
+  m_rtClient.Reset();
+  m_rtBtn.Reset();
+  m_rtHandler.Reset();
 
-IFWL_ComboBox* ToComboBox(IFWL_Widget* widget) {
-  return static_cast<IFWL_ComboBox*>(widget);
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_InitComboList();
+    DisForm_InitComboEdit();
+    return;
+  }
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+  prop->m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText)
+    prop->m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon;
+  m_pListBox =
+      pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this);
+
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) {
+    m_pEdit.reset(new CFWL_ComboEdit(
+        m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this));
+    m_pEdit->SetOuter(this);
+  }
+  if (m_pEdit)
+    m_pEdit->SetParent(this);
+
+  SetStates(m_pProperties->m_dwStates);
 }
 
-}  // namespace
-
-CFWL_ComboBox::CFWL_ComboBox(const CFWL_App* app) : CFWL_Widget(app) {}
-
 CFWL_ComboBox::~CFWL_ComboBox() {}
 
-void CFWL_ComboBox::Initialize() {
-  ASSERT(!m_pIface);
+FWL_Type CFWL_ComboBox::GetClassID() const {
+  return FWL_Type::ComboBox;
+}
 
-  m_pIface = pdfium::MakeUnique<IFWL_ComboBox>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
+void CFWL_ComboBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
 
-  CFWL_Widget::Initialize();
+  rect.Reset();
+  if (IsDropDownStyle() && m_pEdit) {
+    m_pEdit->GetWidgetRect(rect, true);
+  } else {
+    rect.width = 100;
+    rect.height = 16;
+  }
+  if (!m_pProperties->m_pThemeProvider)
+    ResetTheme();
+
+  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pFWidth)
+    return;
+
+  rect.Inflate(0, 0, *pFWidth, 0);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
 void CFWL_ComboBox::AddString(const CFX_WideStringC& wsText) {
-  if (GetWidget())
-    ToComboBox(GetWidget())->AddString(wsText);
+  m_pListBox->AddString(wsText);
 }
 
 bool CFWL_ComboBox::RemoveAt(int32_t iIndex) {
-  return GetWidget() && ToComboBox(GetWidget())->RemoveAt(iIndex);
+  return m_pListBox->RemoveAt(iIndex);
 }
 
 void CFWL_ComboBox::RemoveAll() {
-  if (GetWidget())
-    ToComboBox(GetWidget())->RemoveAll();
+  m_pListBox->DeleteAll();
+}
+
+void CFWL_ComboBox::ModifyStylesEx(uint32_t dwStylesExAdded,
+                                   uint32_t dwStylesExRemoved) {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+    return;
+  }
+
+  bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown);
+  bool bRemoveDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown);
+  if (bAddDropDown && !m_pEdit) {
+    m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>(
+        m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
+    m_pEdit->SetOuter(this);
+    m_pEdit->SetParent(this);
+  } else if (bRemoveDropDown && m_pEdit) {
+    m_pEdit->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+  CFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+}
+
+void CFWL_ComboBox::Update() {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_Update();
+    return;
+  }
+  if (IsLocked())
+    return;
+
+  ResetTheme();
+  if (IsDropDownStyle() && m_pEdit)
+    ResetEditAlignment();
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  Layout();
+  CFWL_ThemePart part;
+  part.m_pWidget = this;
+  m_fComboFormHandler =
+      *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity(
+          &part, CFWL_WidgetCapacity::ComboFormHandler));
+}
+
+FWL_WidgetHit CFWL_ComboBox::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_HitTest(fx, fy);
+  return CFWL_Widget::HitTest(fx, fy);
+}
+
+void CFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix) {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_DrawWidget(pGraphics, pMatrix);
+    return;
+  }
+
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  if (HasBorder())
+    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+
+  if (!IsDropDownStyle()) {
+    CFX_RectF rtTextBk(m_rtClient);
+    rtTextBk.width -= m_rtBtn.width;
+
+    CFWL_ThemeBackground param;
+    param.m_pWidget = this;
+    param.m_iPart = CFWL_Part::Background;
+    param.m_pGraphics = pGraphics;
+    if (pMatrix)
+      param.m_matrix.Concat(*pMatrix);
+    param.m_rtPart = rtTextBk;
+
+    if (m_iCurSel >= 0) {
+      if (void* p = m_pListBox->GetItemData(
+              m_pListBox.get(),
+              m_pListBox->GetItem(m_pListBox.get(), m_iCurSel))) {
+        param.m_pData = p;
+      }
+    }
+
+    if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
+      param.m_dwStates = CFWL_PartState_Disabled;
+    } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
+               (m_iCurSel >= 0)) {
+      param.m_dwStates = CFWL_PartState_Selected;
+    } else {
+      param.m_dwStates = CFWL_PartState_Normal;
+    }
+    pTheme->DrawBackground(&param);
+
+    if (m_iCurSel >= 0) {
+      if (!m_pListBox)
+        return;
+
+      CFX_WideString wsText;
+      CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
+      m_pListBox->GetDataProviderItemText(hItem, wsText);
+
+      CFWL_ThemeText theme_text;
+      theme_text.m_pWidget = this;
+      theme_text.m_iPart = CFWL_Part::Caption;
+      theme_text.m_dwStates = m_iBtnState;
+      theme_text.m_pGraphics = pGraphics;
+      theme_text.m_matrix.Concat(*pMatrix);
+      theme_text.m_rtPart = rtTextBk;
+      theme_text.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+                                  ? CFWL_PartState_Selected
+                                  : CFWL_PartState_Normal;
+      theme_text.m_wsText = wsText;
+      theme_text.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
+      theme_text.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
+      pTheme->DrawText(&theme_text);
+    }
+  }
+
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = CFWL_Part::DropDownButton;
+  param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+                         ? CFWL_PartState_Disabled
+                         : m_iBtnState;
+  param.m_pGraphics = pGraphics;
+  param.m_matrix.Concat(*pMatrix);
+  param.m_rtPart = m_rtBtn;
+  pTheme->DrawBackground(&param);
+}
+
+void CFWL_ComboBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
+  if (!pThemeProvider)
+    return;
+
+  m_pProperties->m_pThemeProvider = pThemeProvider;
+  if (m_pListBox)
+    m_pListBox->SetThemeProvider(pThemeProvider);
+  if (m_pEdit)
+    m_pEdit->SetThemeProvider(pThemeProvider);
 }
 
 void CFWL_ComboBox::GetTextByIndex(int32_t iIndex,
                                    CFX_WideString& wsText) const {
-  if (!GetWidget())
-    return;
-  ToComboBox(GetWidget())->GetTextByIndex(iIndex, wsText);
-}
-
-int32_t CFWL_ComboBox::GetCurSel() const {
-  return GetWidget() ? ToComboBox(GetWidget())->GetCurSel() : -1;
+  CFWL_ListItem* pItem = static_cast<CFWL_ListItem*>(
+      m_pListBox->GetItem(m_pListBox.get(), iIndex));
+  if (pItem)
+    wsText = pItem->m_wsText;
 }
 
 void CFWL_ComboBox::SetCurSel(int32_t iSel) {
-  if (GetWidget())
-    ToComboBox(GetWidget())->SetCurSel(iSel);
+  int32_t iCount = m_pListBox->CountItems(nullptr);
+  bool bClearSel = iSel < 0 || iSel >= iCount;
+  if (IsDropDownStyle() && m_pEdit) {
+    if (bClearSel) {
+      m_pEdit->SetText(CFX_WideString());
+    } else {
+      CFX_WideString wsText;
+      CFWL_ListItem* hItem = m_pListBox->GetItem(this, iSel);
+      m_pListBox->GetDataProviderItemText(hItem, wsText);
+      m_pEdit->SetText(wsText);
+    }
+    m_pEdit->Update();
+  }
+  m_iCurSel = bClearSel ? -1 : iSel;
+}
+
+void CFWL_ComboBox::SetStates(uint32_t dwStates, bool bSet) {
+  if (IsDropDownStyle() && m_pEdit)
+    m_pEdit->SetStates(dwStates, bSet);
+  if (m_pListBox)
+    m_pListBox->SetStates(dwStates, bSet);
+  CFWL_Widget::SetStates(dwStates, bSet);
 }
 
 void CFWL_ComboBox::SetEditText(const CFX_WideString& wsText) {
-  if (GetWidget())
-    ToComboBox(GetWidget())->SetEditText(wsText);
+  if (!m_pEdit)
+    return;
+
+  m_pEdit->SetText(wsText);
+  m_pEdit->Update();
 }
 
 void CFWL_ComboBox::GetEditText(CFX_WideString& wsText,
                                 int32_t nStart,
                                 int32_t nCount) const {
-  if (GetWidget())
-    ToComboBox(GetWidget())->GetEditText(wsText, nStart, nCount);
+  if (m_pEdit) {
+    m_pEdit->GetText(wsText, nStart, nCount);
+    return;
+  }
+  if (!m_pListBox)
+    return;
+
+  CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
+  m_pListBox->GetDataProviderItemText(hItem, wsText);
 }
 
 void CFWL_ComboBox::OpenDropDownList(bool bActivate) {
-  ToComboBox(GetWidget())->OpenDropDownList(bActivate);
+  ShowDropList(bActivate);
 }
 
-bool CFWL_ComboBox::EditCanUndo() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCanUndo() : false;
-}
+void CFWL_ComboBox::GetBBox(CFX_RectF& rect) const {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_GetBBox(rect);
+    return;
+  }
 
-bool CFWL_ComboBox::EditCanRedo() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCanRedo() : false;
-}
+  rect = m_pProperties->m_rtWidget;
+  if (!m_pListBox || !IsDropListVisible())
+    return;
 
-bool CFWL_ComboBox::EditUndo() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditUndo() : false;
-}
-
-bool CFWL_ComboBox::EditRedo() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditRedo() : false;
-}
-
-bool CFWL_ComboBox::EditCanCopy() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCanCopy() : false;
-}
-
-bool CFWL_ComboBox::EditCanCut() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCanCut() : false;
-}
-
-bool CFWL_ComboBox::EditCanSelectAll() {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCanSelectAll() : false;
-}
-
-bool CFWL_ComboBox::EditCopy(CFX_WideString& wsCopy) {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCopy(wsCopy) : false;
-}
-
-bool CFWL_ComboBox::EditCut(CFX_WideString& wsCut) {
-  return GetWidget() ? ToComboBox(GetWidget())->EditCut(wsCut) : false;
-}
-
-bool CFWL_ComboBox::EditPaste(const CFX_WideString& wsPaste) {
-  return GetWidget() ? ToComboBox(GetWidget())->EditPaste(wsPaste) : false;
-}
-
-void CFWL_ComboBox::EditSelectAll() {
-  if (GetWidget())
-    ToComboBox(GetWidget())->EditSelectAll();
-}
-
-void CFWL_ComboBox::EditDelete() {
-  if (GetWidget())
-    ToComboBox(GetWidget())->EditDelete();
-}
-
-void CFWL_ComboBox::EditDeSelect() {
-  if (GetWidget())
-    ToComboBox(GetWidget())->EditDeSelect();
-}
-
-void CFWL_ComboBox::GetBBox(CFX_RectF& rect) {
-  if (GetWidget())
-    ToComboBox(GetWidget())->GetBBox(rect);
+  CFX_RectF rtList;
+  m_pListBox->GetWidgetRect(rtList);
+  rtList.Offset(rect.left, rect.top);
+  rect.Union(rtList);
 }
 
 void CFWL_ComboBox::EditModifyStylesEx(uint32_t dwStylesExAdded,
                                        uint32_t dwStylesExRemoved) {
-  if (GetWidget()) {
-    ToComboBox(GetWidget())
-        ->EditModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+  if (m_pEdit)
+    m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+}
+
+void CFWL_ComboBox::DrawStretchHandler(CFX_Graphics* pGraphics,
+                                       const CFX_Matrix* pMatrix) {
+  CFWL_ThemeBackground param;
+  param.m_pGraphics = pGraphics;
+  param.m_iPart = CFWL_Part::StretchHandler;
+  param.m_dwStates = CFWL_PartState_Normal;
+  param.m_pWidget = this;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix);
+  param.m_rtPart = m_rtHandler;
+  m_pProperties->m_pThemeProvider->DrawBackground(&param);
+}
+
+void CFWL_ComboBox::ShowDropList(bool bActivate) {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_ShowDropList(bActivate);
+  if (IsDropListVisible() == bActivate)
+    return;
+  if (!m_pComboBoxProxy)
+    InitProxyForm();
+
+  m_pComboBoxProxy->Reset();
+  if (!bActivate) {
+    m_pComboBoxProxy->EndDoModal();
+
+    m_bLButtonDown = false;
+    m_pListBox->SetNotifyOwner(true);
+    SetFocus(true);
+    return;
   }
+
+  m_pListBox->ChangeSelected(m_iCurSel);
+  ResetListItemAlignment();
+
+  uint32_t dwStyleAdd = m_pProperties->m_dwStyleExes &
+                        (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw);
+  m_pListBox->ModifyStylesEx(dwStyleAdd, 0);
+  m_pListBox->GetWidgetRect(m_rtList, true);
+
+  CFX_RectF rtAnchor;
+  rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
+               m_pProperties->m_rtWidget.height);
+
+  m_rtList.width = std::max(m_rtList.width, m_rtClient.width);
+  m_rtProxy = m_rtList;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag)
+    m_rtProxy.height += m_fComboFormHandler;
+
+  GetPopupPos(0, m_rtProxy.height, rtAnchor, m_rtProxy);
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
+    FX_FLOAT fx = 0;
+    FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2;
+    TransformTo(nullptr, fx, fy);
+
+    m_bUpFormHandler = fy > m_rtProxy.top;
+    if (m_bUpFormHandler) {
+      m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler);
+      m_rtList.top = m_fComboFormHandler;
+    } else {
+      m_rtHandler.Set(0, m_rtList.height, m_rtList.width, m_fComboFormHandler);
+    }
+  }
+  m_pComboBoxProxy->SetWidgetRect(m_rtProxy);
+  m_pComboBoxProxy->Update();
+  m_pListBox->SetWidgetRect(m_rtList);
+  m_pListBox->Update();
+
+  CFWL_EvtPreDropDown ev;
+  ev.m_pSrcTarget = this;
+  DispatchEvent(&ev);
+
+  m_fItemHeight = m_pListBox->GetItemHeight();
+  m_pListBox->SetFocus(true);
+  m_pComboBoxProxy->DoModal();
+  m_pListBox->SetFocus(false);
+}
+
+void CFWL_ComboBox::MatchEditText() {
+  CFX_WideString wsText;
+  m_pEdit->GetText(wsText);
+  int32_t iMatch = m_pListBox->MatchItem(wsText);
+  if (iMatch != m_iCurSel) {
+    m_pListBox->ChangeSelected(iMatch);
+    if (iMatch >= 0)
+      SyncEditText(iMatch);
+  } else if (iMatch >= 0) {
+    m_pEdit->SetSelected();
+  }
+  m_iCurSel = iMatch;
+}
+
+void CFWL_ComboBox::SyncEditText(int32_t iListItem) {
+  CFX_WideString wsText;
+  CFWL_ListItem* hItem = m_pListBox->GetItem(this, iListItem);
+  m_pListBox->GetDataProviderItemText(hItem, wsText);
+  m_pEdit->SetText(wsText);
+  m_pEdit->Update();
+  m_pEdit->SetSelected();
+}
+
+void CFWL_ComboBox::Layout() {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_Layout();
+
+  GetClientRect(m_rtClient);
+  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pFWidth)
+    return;
+
+  FX_FLOAT fBtn = *pFWidth;
+  m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn,
+              m_rtClient.height);
+  if (!IsDropDownStyle() || !m_pEdit)
+    return;
+
+  CFX_RectF rtEdit;
+  rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
+             m_rtClient.height);
+  m_pEdit->SetWidgetRect(rtEdit);
+
+  if (m_iCurSel >= 0) {
+    CFX_WideString wsText;
+    CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
+    m_pListBox->GetDataProviderItemText(hItem, wsText);
+    m_pEdit->LockUpdate();
+    m_pEdit->SetText(wsText);
+    m_pEdit->UnlockUpdate();
+  }
+  m_pEdit->Update();
+}
+
+void CFWL_ComboBox::ResetTheme() {
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  if (!pTheme) {
+    pTheme = GetAvailableTheme();
+    m_pProperties->m_pThemeProvider = pTheme;
+  }
+  if (m_pListBox && !m_pListBox->GetThemeProvider())
+    m_pListBox->SetThemeProvider(pTheme);
+  if (m_pEdit && !m_pEdit->GetThemeProvider())
+    m_pEdit->SetThemeProvider(pTheme);
+}
+
+void CFWL_ComboBox::ResetEditAlignment() {
+  if (!m_pEdit)
+    return;
+
+  uint32_t dwAdd = 0;
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditHAlignMask) {
+    case FWL_STYLEEXT_CMB_EditHCenter: {
+      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
+      break;
+    }
+    case FWL_STYLEEXT_CMB_EditHFar: {
+      dwAdd |= FWL_STYLEEXT_EDT_HFar;
+      break;
+    }
+    default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; }
+  }
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditVAlignMask) {
+    case FWL_STYLEEXT_CMB_EditVCenter: {
+      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
+      break;
+    }
+    case FWL_STYLEEXT_CMB_EditVFar: {
+      dwAdd |= FWL_STYLEEXT_EDT_VFar;
+      break;
+    }
+    default: {
+      dwAdd |= FWL_STYLEEXT_EDT_VNear;
+      break;
+    }
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditJustified)
+    dwAdd |= FWL_STYLEEXT_EDT_Justified;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditDistributed)
+    dwAdd |= FWL_STYLEEXT_EDT_Distributed;
+
+  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
+                                     FWL_STYLEEXT_EDT_HAlignModeMask |
+                                     FWL_STYLEEXT_EDT_VAlignMask);
+}
+
+void CFWL_ComboBox::ResetListItemAlignment() {
+  if (!m_pListBox)
+    return;
+
+  uint32_t dwAdd = 0;
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemAlignMask) {
+    case FWL_STYLEEXT_CMB_ListItemCenterAlign: {
+      dwAdd |= FWL_STYLEEXT_LTB_CenterAlign;
+      break;
+    }
+    case FWL_STYLEEXT_CMB_ListItemRightAlign: {
+      dwAdd |= FWL_STYLEEXT_LTB_RightAlign;
+      break;
+    }
+    default: {
+      dwAdd |= FWL_STYLEEXT_LTB_LeftAlign;
+      break;
+    }
+  }
+  m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask);
+}
+
+void CFWL_ComboBox::ProcessSelChanged(bool bLButtonUp) {
+  m_iCurSel = m_pListBox->GetItemIndex(this, m_pListBox->GetSelItem(0));
+  if (!IsDropDownStyle()) {
+    Repaint(&m_rtClient);
+    return;
+  }
+
+  CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
+  if (!hItem)
+    return;
+
+  CFX_WideString wsText;
+  m_pListBox->GetItemText(this, hItem, wsText);
+  if (m_pEdit) {
+    m_pEdit->SetText(wsText);
+    m_pEdit->Update();
+    m_pEdit->SetSelected();
+  }
+
+  CFWL_EvtSelectChanged ev;
+  ev.bLButtonUp = bLButtonUp;
+  ev.m_pSrcTarget = this;
+  DispatchEvent(&ev);
+}
+
+void CFWL_ComboBox::InitProxyForm() {
+  if (m_pComboBoxProxy)
+    return;
+  if (!m_pListBox)
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_pOwner = this;
+  prop->m_dwStyles = FWL_WGTSTYLE_Popup;
+  prop->m_dwStates = FWL_WGTSTATE_Invisible;
+
+  // TODO(dsinclair): Does this leak? I don't see a delete, but I'm not sure
+  // if the SetParent call is going to transfer ownership.
+  m_pComboBoxProxy = new CFWL_ComboBoxProxy(this, m_pOwnerApp, std::move(prop),
+                                            m_pListBox.get());
+  m_pListBox->SetParent(m_pComboBoxProxy);
+}
+
+void CFWL_ComboBox::DisForm_InitComboList() {
+  if (m_pListBox)
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_pParent = this;
+  prop->m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
+  prop->m_dwStates = FWL_WGTSTATE_Invisible;
+  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+  m_pListBox =
+      pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this);
+}
+
+void CFWL_ComboBox::DisForm_InitComboEdit() {
+  if (m_pEdit)
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_pParent = this;
+  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+
+  m_pEdit =
+      pdfium::MakeUnique<CFWL_ComboEdit>(m_pOwnerApp, std::move(prop), this);
+  m_pEdit->SetOuter(this);
+}
+
+void CFWL_ComboBox::DisForm_ShowDropList(bool bActivate) {
+  if (DisForm_IsDropListVisible() == bActivate)
+    return;
+
+  if (bActivate) {
+    CFWL_EvtPreDropDown preEvent;
+    preEvent.m_pSrcTarget = this;
+    DispatchEvent(&preEvent);
+
+    CFWL_ComboList* pComboList = m_pListBox.get();
+    int32_t iItems = pComboList->CountItems(nullptr);
+    if (iItems < 1)
+      return;
+
+    ResetListItemAlignment();
+    pComboList->ChangeSelected(m_iCurSel);
+
+    FX_FLOAT fItemHeight = pComboList->CalcItemHeight();
+    FX_FLOAT fBorder = GetBorderSize();
+    FX_FLOAT fPopupMin = 0.0f;
+    if (iItems > 3)
+      fPopupMin = fItemHeight * 3 + fBorder * 2;
+
+    FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2;
+    CFX_RectF rtList;
+    rtList.left = m_rtClient.left;
+    rtList.width = m_pProperties->m_rtWidget.width;
+    rtList.top = 0;
+    rtList.height = 0;
+    GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList);
+
+    m_pListBox->SetWidgetRect(rtList);
+    m_pListBox->Update();
+  } else {
+    SetFocus(true);
+  }
+
+  m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
+  if (bActivate) {
+    CFWL_EvtPostDropDown postEvent;
+    postEvent.m_pSrcTarget = this;
+    DispatchEvent(&postEvent);
+  }
+
+  CFX_RectF rect;
+  m_pListBox->GetWidgetRect(rect);
+  rect.Inflate(2, 2);
+  Repaint(&rect);
+}
+
+void CFWL_ComboBox::DisForm_ModifyStylesEx(uint32_t dwStylesExAdded,
+                                           uint32_t dwStylesExRemoved) {
+  if (!m_pEdit)
+    DisForm_InitComboEdit();
+
+  bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown);
+  bool bDelDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown);
+
+  dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown;
+  m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown;
+
+  if (bAddDropDown)
+    m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly);
+  else if (bDelDropDown)
+    m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0);
+  CFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+}
+
+void CFWL_ComboBox::DisForm_Update() {
+  if (m_iLock)
+    return;
+  if (m_pEdit)
+    ResetEditAlignment();
+  ResetTheme();
+  Layout();
+}
+
+FWL_WidgetHit CFWL_ComboBox::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  CFX_RectF rect;
+  rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width,
+           m_pProperties->m_rtWidget.height);
+  if (rect.Contains(fx, fy))
+    return FWL_WidgetHit::Edit;
+  if (m_rtBtn.Contains(fx, fy))
+    return FWL_WidgetHit::Client;
+  if (DisForm_IsDropListVisible()) {
+    m_pListBox->GetWidgetRect(rect);
+    if (rect.Contains(fx, fy))
+      return FWL_WidgetHit::Client;
+  }
+  return FWL_WidgetHit::Unknown;
+}
+
+void CFWL_ComboBox::DisForm_DrawWidget(CFX_Graphics* pGraphics,
+                                       const CFX_Matrix* pMatrix) {
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  CFX_Matrix mtOrg;
+  mtOrg.Set(1, 0, 0, 1, 0, 0);
+  if (pMatrix)
+    mtOrg = *pMatrix;
+
+  pGraphics->SaveGraphState();
+  pGraphics->ConcatMatrix(&mtOrg);
+  if (!m_rtBtn.IsEmpty(0.1f)) {
+    CFWL_ThemeBackground param;
+    param.m_pWidget = this;
+    param.m_iPart = CFWL_Part::DropDownButton;
+    param.m_dwStates = m_iBtnState;
+    param.m_pGraphics = pGraphics;
+    param.m_rtPart = m_rtBtn;
+    pTheme->DrawBackground(&param);
+  }
+  pGraphics->RestoreGraphState();
+
+  if (m_pEdit) {
+    CFX_RectF rtEdit;
+    m_pEdit->GetWidgetRect(rtEdit);
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
+    mt.Concat(mtOrg);
+    m_pEdit->DrawWidget(pGraphics, &mt);
+  }
+  if (m_pListBox && DisForm_IsDropListVisible()) {
+    CFX_RectF rtList;
+    m_pListBox->GetWidgetRect(rtList);
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, rtList.left, rtList.top);
+    mt.Concat(mtOrg);
+    m_pListBox->DrawWidget(pGraphics, &mt);
+  }
+}
+
+void CFWL_ComboBox::DisForm_GetBBox(CFX_RectF& rect) const {
+  rect = m_pProperties->m_rtWidget;
+  if (!m_pListBox || !DisForm_IsDropListVisible())
+    return;
+
+  CFX_RectF rtList;
+  m_pListBox->GetWidgetRect(rtList);
+  rtList.Offset(rect.left, rect.top);
+  rect.Union(rtList);
+}
+
+void CFWL_ComboBox::DisForm_Layout() {
+  GetClientRect(m_rtClient);
+  m_rtContent = m_rtClient;
+  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pFWidth)
+    return;
+
+  FX_FLOAT borderWidth = 1;
+  FX_FLOAT fBtn = *pFWidth;
+  if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) {
+    m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth,
+                fBtn - borderWidth, m_rtClient.height - 2 * borderWidth);
+  }
+
+  CFX_RectF* pUIMargin =
+      static_cast<CFX_RectF*>(GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
+  if (pUIMargin) {
+    m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
+                        pUIMargin->height);
+  }
+
+  if (!IsDropDownStyle() || !m_pEdit)
+    return;
+
+  CFX_RectF rtEdit;
+  rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn,
+             m_rtContent.height);
+  m_pEdit->SetWidgetRect(rtEdit);
+
+  if (m_iCurSel >= 0) {
+    CFX_WideString wsText;
+    CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
+    m_pListBox->GetDataProviderItemText(hItem, wsText);
+    m_pEdit->LockUpdate();
+    m_pEdit->SetText(wsText);
+    m_pEdit->UnlockUpdate();
+  }
+  m_pEdit->Update();
+}
+
+void CFWL_ComboBox::OnProcessMessage(CFWL_Message* pMessage) {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_OnProcessMessage(pMessage);
+    return;
+  }
+  if (!pMessage)
+    return;
+
+  switch (pMessage->GetClassID()) {
+    case CFWL_MessageType::SetFocus:
+      OnFocusChanged(pMessage, true);
+      break;
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(pMessage, false);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        case FWL_MouseCommand::Move:
+          OnMouseMove(pMsg);
+          break;
+        case FWL_MouseCommand::Leave:
+          OnMouseLeave(pMsg);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key:
+      OnKey(static_cast<CFWL_MsgKey*>(pMessage));
+      break;
+    default:
+      break;
+  }
+
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_ComboBox::OnProcessEvent(CFWL_Event* pEvent) {
+  CFWL_EventType dwFlag = pEvent->GetClassID();
+  if (dwFlag == CFWL_EventType::Scroll) {
+    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
+    CFWL_EvtScroll pScrollEv;
+    pScrollEv.m_pSrcTarget = this;
+    pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode;
+    pScrollEv.m_fPos = pScrollEvent->m_fPos;
+    DispatchEvent(&pScrollEv);
+  } else if (dwFlag == CFWL_EventType::TextChanged) {
+    CFWL_EvtEditChanged pTemp;
+    pTemp.m_pSrcTarget = this;
+    DispatchEvent(&pTemp);
+  }
+}
+
+void CFWL_ComboBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                 const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_ComboBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  if (bSet) {
+    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
+    if (IsDropDownStyle() && pMsg->m_pSrcTarget != m_pListBox.get()) {
+      if (!m_pEdit)
+        return;
+      m_pEdit->SetSelected();
+      return;
+    }
+
+    Repaint(&m_rtClient);
+    return;
+  }
+
+  m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
+  if (!IsDropDownStyle() || pMsg->m_pDstTarget == m_pListBox.get()) {
+    Repaint(&m_rtClient);
+    return;
+  }
+  if (!m_pEdit)
+    return;
+
+  m_pEdit->FlagFocus(false);
+  m_pEdit->ClearSelected();
+}
+
+void CFWL_ComboBox::OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    return;
+
+  CFX_RectF& rtBtn = IsDropDownStyle() ? m_rtBtn : m_rtClient;
+  if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    return;
+
+  if (IsDropDownStyle() && m_pEdit)
+    MatchEditText();
+
+  m_bLButtonDown = true;
+  m_iBtnState = CFWL_PartState_Pressed;
+  Repaint(&m_rtClient);
+
+  ShowDropList(true);
+  m_iBtnState = CFWL_PartState_Normal;
+  Repaint(&m_rtClient);
+}
+
+void CFWL_ComboBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  m_bLButtonDown = false;
+  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    m_iBtnState = CFWL_PartState_Hovered;
+  else
+    m_iBtnState = CFWL_PartState_Normal;
+
+  Repaint(&m_rtBtn);
+}
+
+void CFWL_ComboBox::OnMouseMove(CFWL_MsgMouse* pMsg) {
+  int32_t iOldState = m_iBtnState;
+  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
+    m_iBtnState =
+        m_bLButtonDown ? CFWL_PartState_Pressed : CFWL_PartState_Hovered;
+  } else {
+    m_iBtnState = CFWL_PartState_Normal;
+  }
+  if ((iOldState != m_iBtnState) &&
+      !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
+        FWL_WGTSTATE_Disabled)) {
+    Repaint(&m_rtBtn);
+  }
+}
+
+void CFWL_ComboBox::OnMouseLeave(CFWL_MsgMouse* pMsg) {
+  if (!IsDropListVisible() &&
+      !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
+        FWL_WGTSTATE_Disabled)) {
+    m_iBtnState = CFWL_PartState_Normal;
+    Repaint(&m_rtBtn);
+  }
+}
+
+void CFWL_ComboBox::OnKey(CFWL_MsgKey* pMsg) {
+  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
+  if (dwKeyCode == FWL_VKEY_Tab) {
+    DispatchKeyEvent(pMsg);
+    return;
+  }
+  if (pMsg->m_pDstTarget == this)
+    DoSubCtrlKey(pMsg);
+}
+
+void CFWL_ComboBox::DoSubCtrlKey(CFWL_MsgKey* pMsg) {
+  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
+  const bool bUp = dwKeyCode == FWL_VKEY_Up;
+  const bool bDown = dwKeyCode == FWL_VKEY_Down;
+  if (bUp || bDown) {
+    int32_t iCount = m_pListBox->CountItems(nullptr);
+    if (iCount < 1)
+      return;
+
+    bool bMatchEqual = false;
+    int32_t iCurSel = m_iCurSel;
+    bool bDropDown = IsDropDownStyle();
+    if (bDropDown && m_pEdit) {
+      CFX_WideString wsText;
+      m_pEdit->GetText(wsText);
+      iCurSel = m_pListBox->MatchItem(wsText);
+      if (iCurSel >= 0) {
+        CFX_WideString wsTemp;
+        CFWL_ListItem* hItem = m_pListBox->GetItem(this, iCurSel);
+        m_pListBox->GetDataProviderItemText(hItem, wsTemp);
+        bMatchEqual = wsText == wsTemp;
+      }
+    }
+    if (iCurSel < 0) {
+      iCurSel = 0;
+    } else if (!bDropDown || bMatchEqual) {
+      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1))
+        return;
+      if (bUp)
+        iCurSel--;
+      else
+        iCurSel++;
+    }
+    m_iCurSel = iCurSel;
+    if (bDropDown && m_pEdit)
+      SyncEditText(m_iCurSel);
+    else
+      Repaint(&m_rtClient);
+    return;
+  }
+
+  if (IsDropDownStyle())
+    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
+}
+
+void CFWL_ComboBox::DisForm_OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+
+  bool backDefault = true;
+  switch (pMessage->GetClassID()) {
+    case CFWL_MessageType::SetFocus: {
+      backDefault = false;
+      DisForm_OnFocusChanged(pMessage, true);
+      break;
+    }
+    case CFWL_MessageType::KillFocus: {
+      backDefault = false;
+      DisForm_OnFocusChanged(pMessage, false);
+      break;
+    }
+    case CFWL_MessageType::Mouse: {
+      backDefault = false;
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          DisForm_OnLButtonDown(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      backDefault = false;
+      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
+      if (pKey->m_dwCmd == FWL_KeyCommand::KeyUp)
+        break;
+      if (DisForm_IsDropListVisible() &&
+          pKey->m_dwCmd == FWL_KeyCommand::KeyDown) {
+        bool bListKey = pKey->m_dwKeyCode == FWL_VKEY_Up ||
+                        pKey->m_dwKeyCode == FWL_VKEY_Down ||
+                        pKey->m_dwKeyCode == FWL_VKEY_Return ||
+                        pKey->m_dwKeyCode == FWL_VKEY_Escape;
+        if (bListKey) {
+          m_pListBox->GetDelegate()->OnProcessMessage(pMessage);
+          break;
+        }
+      }
+      DisForm_OnKey(pKey);
+      break;
+    }
+    default:
+      break;
+  }
+  if (backDefault)
+    CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_ComboBox::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  bool bDropDown = DisForm_IsDropListVisible();
+  CFX_RectF& rtBtn = bDropDown ? m_rtBtn : m_rtClient;
+  if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    return;
+
+  if (DisForm_IsDropListVisible()) {
+    DisForm_ShowDropList(false);
+    return;
+  }
+  if (m_pEdit)
+    MatchEditText();
+  DisForm_ShowDropList(true);
+}
+
+void CFWL_ComboBox::DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  if (bSet) {
+    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
+    if ((m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) {
+      CFWL_MsgSetFocus msg;
+      msg.m_pDstTarget = m_pEdit.get();
+      msg.m_pSrcTarget = nullptr;
+      m_pEdit->GetDelegate()->OnProcessMessage(&msg);
+    }
+  } else {
+    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
+    DisForm_ShowDropList(false);
+    CFWL_MsgKillFocus msg;
+    msg.m_pDstTarget = nullptr;
+    msg.m_pSrcTarget = m_pEdit.get();
+    m_pEdit->GetDelegate()->OnProcessMessage(&msg);
+  }
+}
+
+void CFWL_ComboBox::DisForm_OnKey(CFWL_MsgKey* pMsg) {
+  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
+  const bool bUp = dwKeyCode == FWL_VKEY_Up;
+  const bool bDown = dwKeyCode == FWL_VKEY_Down;
+  if (bUp || bDown) {
+    CFWL_ComboList* pComboList = m_pListBox.get();
+    int32_t iCount = pComboList->CountItems(nullptr);
+    if (iCount < 1)
+      return;
+
+    bool bMatchEqual = false;
+    int32_t iCurSel = m_iCurSel;
+    if (m_pEdit) {
+      CFX_WideString wsText;
+      m_pEdit->GetText(wsText);
+      iCurSel = pComboList->MatchItem(wsText);
+      if (iCurSel >= 0) {
+        CFX_WideString wsTemp;
+        CFWL_ListItem* item = m_pListBox->GetSelItem(iCurSel);
+        m_pListBox->GetDataProviderItemText(item, wsTemp);
+        bMatchEqual = wsText == wsTemp;
+      }
+    }
+    if (iCurSel < 0) {
+      iCurSel = 0;
+    } else if (bMatchEqual) {
+      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1))
+        return;
+      if (bUp)
+        iCurSel--;
+      else
+        iCurSel++;
+    }
+    m_iCurSel = iCurSel;
+    SyncEditText(m_iCurSel);
+    return;
+  }
+  if (m_pEdit)
+    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
 }
diff --git a/xfa/fwl/core/cfwl_combobox.h b/xfa/fwl/core/cfwl_combobox.h
index 7b6f434..a454519 100644
--- a/xfa/fwl/core/cfwl_combobox.h
+++ b/xfa/fwl/core/cfwl_combobox.h
@@ -8,26 +8,74 @@
 #define XFA_FWL_CORE_CFWL_COMBOBOX_H_
 
 #include <memory>
-#include <vector>
 
-#include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
+#include "xfa/fwl/core/cfwl_comboboxproxy.h"
+#include "xfa/fwl/core/cfwl_comboedit.h"
+#include "xfa/fwl/core/cfwl_combolist.h"
+#include "xfa/fwl/core/cfwl_form.h"
+#include "xfa/fwl/core/cfwl_listbox.h"
+#include "xfa/fxgraphics/cfx_graphics.h"
+
+class CFWL_WidgetProperties;
+class CFWL_ComboBox;
+class CFWL_ComboBoxProxy;
+class CFWL_FormProxy;
+class CFWL_ListBox;
+class CFWL_Widget;
+
+#define FWL_STYLEEXT_CMB_DropList (0L << 0)
+#define FWL_STYLEEXT_CMB_DropDown (1L << 0)
+#define FWL_STYLEEXT_CMB_Sort (1L << 1)
+#define FWL_STYLEEXT_CMB_ListDrag (1L << 2)
+#define FWL_STYLEEXT_CMB_OwnerDraw (1L << 3)
+#define FWL_STYLEEXT_CMB_EditHNear (0L << 4)
+#define FWL_STYLEEXT_CMB_EditHCenter (1L << 4)
+#define FWL_STYLEEXT_CMB_EditHFar (2L << 4)
+#define FWL_STYLEEXT_CMB_EditVNear (0L << 6)
+#define FWL_STYLEEXT_CMB_EditVCenter (1L << 6)
+#define FWL_STYLEEXT_CMB_EditVFar (2L << 6)
+#define FWL_STYLEEXT_CMB_EditJustified (1L << 8)
+#define FWL_STYLEEXT_CMB_EditDistributed (2L << 8)
+#define FWL_STYLEEXT_CMB_EditHAlignMask (3L << 4)
+#define FWL_STYLEEXT_CMB_EditVAlignMask (3L << 6)
+#define FWL_STYLEEXT_CMB_EditHAlignModeMask (3L << 8)
+#define FWL_STYLEEXT_CMB_ListItemLeftAlign (0L << 10)
+#define FWL_STYLEEXT_CMB_ListItemCenterAlign (1L << 10)
+#define FWL_STYLEEXT_CMB_ListItemRightAlign (2L << 10)
+#define FWL_STYLEEXT_CMB_ListItemAlignMask (3L << 10)
+#define FWL_STYLEEXT_CMB_ListItemText (0L << 12)
+#define FWL_STYLEEXT_CMB_ListItemIconText (1L << 12)
+#define FWL_STYLEEXT_CMB_ReadOnly (1L << 13)
 
 class CFWL_ComboBox : public CFWL_Widget {
  public:
   explicit CFWL_ComboBox(const CFWL_App* pApp);
   ~CFWL_ComboBox() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void ModifyStylesEx(uint32_t dwStylesExAdded,
+                      uint32_t dwStylesExRemoved) override;
+  void SetStates(uint32_t dwStates, bool bSet = true) override;
+  void Update() override;
+  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnProcessEvent(CFWL_Event* pEvent) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
+
+  void GetTextByIndex(int32_t iIndex, CFX_WideString& wsText) const;
+  int32_t GetCurSel() const { return m_iCurSel; }
+  void SetCurSel(int32_t iSel);
 
   void AddString(const CFX_WideStringC& wsText);
   bool RemoveAt(int32_t iIndex);  // Returns false iff |iIndex| out of range.
   void RemoveAll();
 
-  void GetTextByIndex(int32_t iIndex, CFX_WideString& wsText) const;
-  int32_t GetCurSel() const;
-  void SetCurSel(int32_t iSel);
-
   void SetEditText(const CFX_WideString& wsText);
   void GetEditText(CFX_WideString& wsText,
                    int32_t nStart = 0,
@@ -35,22 +83,93 @@
 
   void OpenDropDownList(bool bActivate);
 
-  bool EditCanUndo();
-  bool EditCanRedo();
-  bool EditUndo();
-  bool EditRedo();
-  bool EditCanCopy();
-  bool EditCanCut();
-  bool EditCanSelectAll();
-  bool EditCopy(CFX_WideString& wsCopy);
-  bool EditCut(CFX_WideString& wsCut);
-  bool EditPaste(const CFX_WideString& wsPaste);
-  void EditSelectAll();
-  void EditDelete();
-  void EditDeSelect();
+  bool EditCanUndo() const { return m_pEdit->CanUndo(); }
+  bool EditCanRedo() const { return m_pEdit->CanRedo(); }
+  bool EditUndo() { return m_pEdit->Undo(); }
+  bool EditRedo() { return m_pEdit->Redo(); }
+  bool EditCanCopy() const { return m_pEdit->CountSelRanges() > 0; }
+  bool EditCanCut() const {
+    if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)
+      return false;
+    return EditCanCopy();
+  }
+  bool EditCanSelectAll() const { return m_pEdit->GetTextLength() > 0; }
+  bool EditCopy(CFX_WideString& wsCopy) const { return m_pEdit->Copy(wsCopy); }
+  bool EditCut(CFX_WideString& wsCut) { return m_pEdit->Cut(wsCut); }
+  bool EditPaste(const CFX_WideString& wsPaste) {
+    return m_pEdit->Paste(wsPaste);
+  }
+  void EditSelectAll() { m_pEdit->AddSelRange(0); }
+  void EditDelete() { m_pEdit->ClearText(); }
+  void EditDeSelect() { m_pEdit->ClearSelections(); }
 
-  void GetBBox(CFX_RectF& rect);
+  void GetBBox(CFX_RectF& rect) const;
   void EditModifyStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved);
+
+  void DrawStretchHandler(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix);
+  bool IsDropListVisible() const {
+    return m_pComboBoxProxy &&
+           !(m_pComboBoxProxy->GetStates() & FWL_WGTSTATE_Invisible);
+  }
+  void ShowDropList(bool bActivate);
+
+  CFWL_ComboEdit* GetComboEdit() const { return m_pEdit.get(); }
+
+  void ProcessSelChanged(bool bLButtonUp);
+  int32_t GetCurrentSelection() const { return m_iCurSel; }
+
+ private:
+  bool IsDropDownStyle() const {
+    return !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown);
+  }
+  void MatchEditText();
+  void SyncEditText(int32_t iListItem);
+  void Layout();
+  void ResetTheme();
+  void ResetEditAlignment();
+  void ResetListItemAlignment();
+  void InitProxyForm();
+  void DisForm_InitComboList();
+  void DisForm_InitComboEdit();
+  void DisForm_ShowDropList(bool bActivate);
+  bool DisForm_IsDropListVisible() const {
+    return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible);
+  }
+  void DisForm_ModifyStylesEx(uint32_t dwStylesExAdded,
+                              uint32_t dwStylesExRemoved);
+  void DisForm_Update();
+  FWL_WidgetHit DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy);
+  void DisForm_DrawWidget(CFX_Graphics* pGraphics,
+                          const CFX_Matrix* pMatrix = nullptr);
+  void DisForm_GetBBox(CFX_RectF& rect) const;
+  void DisForm_Layout();
+  void OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
+  void OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnMouseMove(CFWL_MsgMouse* pMsg);
+  void OnMouseLeave(CFWL_MsgMouse* pMsg);
+  void OnKey(CFWL_MsgKey* pMsg);
+  void DoSubCtrlKey(CFWL_MsgKey* pMsg);
+  void DisForm_OnProcessMessage(CFWL_Message* pMessage);
+  void DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
+  void DisForm_OnKey(CFWL_MsgKey* pMsg);
+
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtContent;
+  CFX_RectF m_rtBtn;
+  CFX_RectF m_rtList;
+  CFX_RectF m_rtProxy;
+  CFX_RectF m_rtHandler;
+  std::unique_ptr<CFWL_ComboEdit> m_pEdit;
+  std::unique_ptr<CFWL_ComboList> m_pListBox;
+  CFWL_ComboBoxProxy* m_pComboBoxProxy;  // Can this be a unique_ptr?
+  bool m_bLButtonDown;
+  bool m_bUpFormHandler;
+  int32_t m_iCurSel;
+  int32_t m_iBtnState;
+  FX_FLOAT m_fComboFormHandler;
+  FX_FLOAT m_fItemHeight;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_COMBOBOX_H_
diff --git a/xfa/fwl/core/cfwl_comboboxproxy.cpp b/xfa/fwl/core/cfwl_comboboxproxy.cpp
index c367eef..4ad358d 100644
--- a/xfa/fwl/core/cfwl_comboboxproxy.cpp
+++ b/xfa/fwl/core/cfwl_comboboxproxy.cpp
@@ -10,16 +10,16 @@
 #include <utility>
 
 #include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_combobox.h"
 #include "xfa/fwl/core/cfwl_msgkillfocus.h"
 #include "xfa/fwl/core/cfwl_msgmouse.h"
 #include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
 
 CFWL_ComboBoxProxy::CFWL_ComboBoxProxy(
-    IFWL_ComboBox* pComboBox,
+    CFWL_ComboBox* pComboBox,
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
+    CFWL_Widget* pOuter)
     : CFWL_FormProxy(app, std::move(properties), pOuter),
       m_bLButtonDown(false),
       m_bLButtonUpSelf(false),
@@ -55,7 +55,7 @@
     default:
       break;
   }
-  IFWL_Widget::OnProcessMessage(pMessage);
+  CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_ComboBoxProxy::OnDrawWidget(CFX_Graphics* pGraphics,
diff --git a/xfa/fwl/core/cfwl_comboboxproxy.h b/xfa/fwl/core/cfwl_comboboxproxy.h
index 33f5a82..11fb364 100644
--- a/xfa/fwl/core/cfwl_comboboxproxy.h
+++ b/xfa/fwl/core/cfwl_comboboxproxy.h
@@ -11,14 +11,14 @@
 
 #include "xfa/fwl/core/cfwl_formproxy.h"
 
-class IFWL_ComboBox;
+class CFWL_ComboBox;
 
 class CFWL_ComboBoxProxy : public CFWL_FormProxy {
  public:
-  CFWL_ComboBoxProxy(IFWL_ComboBox* pCombobBox,
+  CFWL_ComboBoxProxy(CFWL_ComboBox* pCombobBox,
                      const CFWL_App* app,
                      std::unique_ptr<CFWL_WidgetProperties> properties,
-                     IFWL_Widget* pOuter);
+                     CFWL_Widget* pOuter);
   ~CFWL_ComboBoxProxy() override;
 
   // CFWL_FormProxy
@@ -35,7 +35,7 @@
 
   bool m_bLButtonDown;
   bool m_bLButtonUpSelf;
-  IFWL_ComboBox* m_pComboBox;
+  CFWL_ComboBox* m_pComboBox;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_COMBOBOXPROXY_H_
diff --git a/xfa/fwl/core/cfwl_comboedit.cpp b/xfa/fwl/core/cfwl_comboedit.cpp
index 2051daa..af5c2a7 100644
--- a/xfa/fwl/core/cfwl_comboedit.cpp
+++ b/xfa/fwl/core/cfwl_comboedit.cpp
@@ -10,15 +10,15 @@
 #include <utility>
 
 #include "xfa/fde/cfde_txtedtengine.h"
+#include "xfa/fwl/core/cfwl_combobox.h"
 #include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
 
 CFWL_ComboEdit::CFWL_ComboEdit(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
-    : IFWL_Edit(app, std::move(properties), pOuter) {
-  m_pOuter = static_cast<IFWL_ComboBox*>(pOuter);
+    CFWL_Widget* pOuter)
+    : CFWL_Edit(app, std::move(properties), pOuter) {
+  m_pOuter = static_cast<CFWL_ComboBox*>(pOuter);
 }
 
 void CFWL_ComboEdit::ClearSelected() {
@@ -71,5 +71,5 @@
       break;
   }
   if (backDefault)
-    IFWL_Edit::OnProcessMessage(pMessage);
+    CFWL_Edit::OnProcessMessage(pMessage);
 }
diff --git a/xfa/fwl/core/cfwl_comboedit.h b/xfa/fwl/core/cfwl_comboedit.h
index 30c5e85..5ac6082 100644
--- a/xfa/fwl/core/cfwl_comboedit.h
+++ b/xfa/fwl/core/cfwl_comboedit.h
@@ -9,19 +9,19 @@
 
 #include <memory>
 
+#include "xfa/fwl/core/cfwl_edit.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
-class IFWL_ComboBox;
+class CFWL_ComboBox;
 
-class CFWL_ComboEdit : public IFWL_Edit {
+class CFWL_ComboEdit : public CFWL_Edit {
  public:
   CFWL_ComboEdit(const CFWL_App* app,
                  std::unique_ptr<CFWL_WidgetProperties> properties,
-                 IFWL_Widget* pOuter);
+                 CFWL_Widget* pOuter);
 
-  // IFWL_Edit.
+  // CFWL_Edit.
   void OnProcessMessage(CFWL_Message* pMessage) override;
 
   void ClearSelected();
@@ -29,7 +29,7 @@
   void FlagFocus(bool bSet);
 
  private:
-  IFWL_ComboBox* m_pOuter;
+  CFWL_ComboBox* m_pOuter;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_COMBOEDIT_H_
diff --git a/xfa/fwl/core/cfwl_combolist.cpp b/xfa/fwl/core/cfwl_combolist.cpp
index e98f38e..0476498 100644
--- a/xfa/fwl/core/cfwl_combolist.cpp
+++ b/xfa/fwl/core/cfwl_combolist.cpp
@@ -10,18 +10,18 @@
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
+#include "xfa/fwl/core/cfwl_combobox.h"
 #include "xfa/fwl/core/cfwl_comboedit.h"
+#include "xfa/fwl/core/cfwl_listbox.h"
 #include "xfa/fwl/core/cfwl_msgkey.h"
 #include "xfa/fwl/core/cfwl_msgkillfocus.h"
 #include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
 
 CFWL_ComboList::CFWL_ComboList(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
-    : IFWL_ListBox(app, std::move(properties), pOuter), m_bNotifyOwner(true) {
+    CFWL_Widget* pOuter)
+    : CFWL_ListBox(app, std::move(properties), pOuter), m_bNotifyOwner(true) {
   ASSERT(pOuter);
 }
 
@@ -68,7 +68,7 @@
 
 void CFWL_ComboList::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) {
   fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top;
-  IFWL_Widget* pOwner = GetOwner();
+  CFWL_Widget* pOwner = GetOwner();
   if (!pOwner)
     return;
   pOwner->TransformTo(m_pOuter, fx, fy);
@@ -119,7 +119,7 @@
     backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage));
   }
   if (backDefault)
-    IFWL_ListBox::OnProcessMessage(pMessage);
+    CFWL_ListBox::OnProcessMessage(pMessage);
 }
 
 void CFWL_ComboList::OnDropListFocusChanged(CFWL_Message* pMsg, bool bSet) {
@@ -127,7 +127,7 @@
     return;
 
   CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg);
-  IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+  CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
   if (pKill->m_pSetFocus == m_pOuter ||
       pKill->m_pSetFocus == pOuter->GetComboEdit()) {
     pOuter->ShowDropList(false);
@@ -154,7 +154,7 @@
     ChangeSelected(GetItemIndex(this, hItem));
   } else if (m_bNotifyOwner) {
     ClientToOuter(pMsg->m_fx, pMsg->m_fy);
-    IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+    CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
     pOuter->GetDelegate()->OnProcessMessage(pMsg);
   }
 }
@@ -163,12 +163,12 @@
   if (GetRTClient().Contains(pMsg->m_fx, pMsg->m_fy))
     return;
 
-  IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+  CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
   pOuter->ShowDropList(false);
 }
 
 void CFWL_ComboList::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) {
-  IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+  CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
   if (m_bNotifyOwner) {
     ClientToOuter(pMsg->m_fx, pMsg->m_fy);
     pOuter->GetDelegate()->OnProcessMessage(pMsg);
@@ -190,7 +190,7 @@
 }
 
 bool CFWL_ComboList::OnDropListKey(CFWL_MsgKey* pKey) {
-  IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+  CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
   bool bPropagate = false;
   if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown) {
     uint32_t dwKeyCode = pKey->m_dwKeyCode;
@@ -229,7 +229,7 @@
     case FWL_VKEY_Down:
     case FWL_VKEY_Home:
     case FWL_VKEY_End: {
-      IFWL_ComboBox* pOuter = static_cast<IFWL_ComboBox*>(m_pOuter);
+      CFWL_ComboBox* pOuter = static_cast<CFWL_ComboBox*>(m_pOuter);
       CFWL_ListItem* hItem = GetItem(this, pOuter->GetCurrentSelection());
       hItem = GetListItem(hItem, dwKeyCode);
       if (!hItem)
diff --git a/xfa/fwl/core/cfwl_combolist.h b/xfa/fwl/core/cfwl_combolist.h
index ad97b5b..0c1cd57 100644
--- a/xfa/fwl/core/cfwl_combolist.h
+++ b/xfa/fwl/core/cfwl_combolist.h
@@ -9,17 +9,17 @@
 
 #include <memory>
 
+#include "xfa/fwl/core/cfwl_listbox.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
-class CFWL_ComboList : public IFWL_ListBox {
+class CFWL_ComboList : public CFWL_ListBox {
  public:
   CFWL_ComboList(const CFWL_App* app,
                  std::unique_ptr<CFWL_WidgetProperties> properties,
-                 IFWL_Widget* pOuter);
+                 CFWL_Widget* pOuter);
 
-  // IFWL_ListBox.
+  // CFWL_ListBox.
   void OnProcessMessage(CFWL_Message* pMessage) override;
 
   int32_t MatchItem(const CFX_WideString& wsMatch);
diff --git a/xfa/fwl/core/cfwl_datetimeedit.cpp b/xfa/fwl/core/cfwl_datetimeedit.cpp
index 16ebb3c..b74efb1 100644
--- a/xfa/fwl/core/cfwl_datetimeedit.cpp
+++ b/xfa/fwl/core/cfwl_datetimeedit.cpp
@@ -10,15 +10,15 @@
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
+#include "xfa/fwl/core/cfwl_datetimepicker.h"
 #include "xfa/fwl/core/cfwl_msgmouse.h"
 #include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
 
 CFWL_DateTimeEdit::CFWL_DateTimeEdit(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
-    : IFWL_Edit(app, std::move(properties), pOuter) {}
+    CFWL_Widget* pOuter)
+    : CFWL_Edit(app, std::move(properties), pOuter) {}
 
 void CFWL_DateTimeEdit::OnProcessMessage(CFWL_Message* pMessage) {
   if (m_pWidgetMgr->IsFormDisabled()) {
@@ -29,7 +29,7 @@
   CFWL_MessageType dwHashCode = pMessage->GetClassID();
   if (dwHashCode == CFWL_MessageType::SetFocus ||
       dwHashCode == CFWL_MessageType::KillFocus) {
-    IFWL_Widget* pOuter = GetOuter();
+    CFWL_Widget* pOuter = GetOuter();
     pOuter->GetDelegate()->OnProcessMessage(pMessage);
   }
 }
@@ -38,7 +38,7 @@
   CFWL_MessageType dwHashCode = pMessage->GetClassID();
   if (!m_pWidgetMgr->IsFormDisabled() ||
       dwHashCode != CFWL_MessageType::Mouse) {
-    IFWL_Edit::OnProcessMessage(pMessage);
+    CFWL_Edit::OnProcessMessage(pMessage);
     return;
   }
 
@@ -48,8 +48,8 @@
     if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
       m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
 
-    IFWL_DateTimePicker* pDateTime =
-        static_cast<IFWL_DateTimePicker*>(m_pOuter);
+    CFWL_DateTimePicker* pDateTime =
+        static_cast<CFWL_DateTimePicker*>(m_pOuter);
     if (pDateTime->IsMonthCalendarVisible()) {
       CFX_RectF rtInvalidate;
       pDateTime->GetWidgetRect(rtInvalidate);
@@ -58,5 +58,5 @@
       pDateTime->Repaint(&rtInvalidate);
     }
   }
-  IFWL_Edit::OnProcessMessage(pMessage);
+  CFWL_Edit::OnProcessMessage(pMessage);
 }
diff --git a/xfa/fwl/core/cfwl_datetimeedit.h b/xfa/fwl/core/cfwl_datetimeedit.h
index 68efd2e..15fea74 100644
--- a/xfa/fwl/core/cfwl_datetimeedit.h
+++ b/xfa/fwl/core/cfwl_datetimeedit.h
@@ -9,18 +9,18 @@
 
 #include <memory>
 
+#include "xfa/fwl/core/cfwl_edit.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
 #include "xfa/fwl/core/fwl_error.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
-class CFWL_DateTimeEdit : public IFWL_Edit {
+class CFWL_DateTimeEdit : public CFWL_Edit {
  public:
   CFWL_DateTimeEdit(const CFWL_App* app,
                     std::unique_ptr<CFWL_WidgetProperties> properties,
-                    IFWL_Widget* pOuter);
+                    CFWL_Widget* pOuter);
 
-  // IFWL_Edit.
+  // CFWL_Edit.
   void OnProcessMessage(CFWL_Message* pMessage) override;
 
  private:
diff --git a/xfa/fwl/core/cfwl_datetimepicker.cpp b/xfa/fwl/core/cfwl_datetimepicker.cpp
index 98aae94..142daf5 100644
--- a/xfa/fwl/core/cfwl_datetimepicker.cpp
+++ b/xfa/fwl/core/cfwl_datetimepicker.cpp
@@ -7,66 +7,652 @@
 #include "xfa/fwl/core/cfwl_datetimepicker.h"
 
 #include <memory>
+#include <utility>
 
 #include "third_party/base/ptr_util.h"
-#include "xfa/fwl/core/fwl_error.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_evteditchanged.h"
+#include "xfa/fwl/core/cfwl_evtselectchanged.h"
+#include "xfa/fwl/core/cfwl_formproxy.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_msgsetfocus.h"
+#include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_spinbutton.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_widgetmgr.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
 
 namespace {
 
-IFWL_DateTimePicker* ToDateTimePicker(IFWL_Widget* widget) {
-  return static_cast<IFWL_DateTimePicker*>(widget);
-}
+const int kDateTimePickerWidth = 100;
+const int kDateTimePickerHeight = 20;
 
 }  // namespace
-
 CFWL_DateTimePicker::CFWL_DateTimePicker(const CFWL_App* app)
-    : CFWL_Widget(app) {}
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
+      m_iBtnState(1),
+      m_iYear(-1),
+      m_iMonth(-1),
+      m_iDay(-1),
+      m_bLBtnDown(false) {
+  m_rtBtn.Set(0, 0, 0, 0);
 
-CFWL_DateTimePicker::~CFWL_DateTimePicker() {}
+  m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat;
 
-void CFWL_DateTimePicker::Initialize() {
-  ASSERT(!m_pIface);
+  auto monthProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  monthProp->m_dwStyles = FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border;
+  monthProp->m_dwStates = FWL_WGTSTATE_Invisible;
+  monthProp->m_pParent = this;
+  monthProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+  m_pMonthCal.reset(
+      new CFWL_MonthCalendar(m_pOwnerApp, std::move(monthProp), this));
 
-  m_pIface = pdfium::MakeUnique<IFWL_DateTimePicker>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
+  CFX_RectF rtMonthCal;
+  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
+  rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height);
+  m_pMonthCal->SetWidgetRect(rtMonthCal);
 
-  CFWL_Widget::Initialize();
+  auto editProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  editProp->m_pParent = this;
+  editProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+
+  m_pEdit.reset(new CFWL_DateTimeEdit(m_pOwnerApp, std::move(editProp), this));
+  RegisterEventTarget(m_pMonthCal.get());
+  RegisterEventTarget(m_pEdit.get());
 }
 
-int32_t CFWL_DateTimePicker::CountSelRanges() {
-  return ToDateTimePicker(GetWidget())->CountSelRanges();
+CFWL_DateTimePicker::~CFWL_DateTimePicker() {
+  UnregisterEventTarget();
 }
 
-int32_t CFWL_DateTimePicker::GetSelRange(int32_t nIndex, int32_t& nStart) {
-  return ToDateTimePicker(GetWidget())->GetSelRange(nIndex, nStart);
+FWL_Type CFWL_DateTimePicker::GetClassID() const {
+  return FWL_Type::DateTimePicker;
 }
 
-void CFWL_DateTimePicker::GetEditText(CFX_WideString& wsText) {
-  ToDateTimePicker(GetWidget())->GetEditText(wsText);
+void CFWL_DateTimePicker::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_GetWidgetRect(rect, bAutoSize);
+    return;
+  }
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  rect.Set(0, 0, kDateTimePickerWidth, kDateTimePickerHeight);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
-void CFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
-  ToDateTimePicker(GetWidget())->SetEditText(wsText);
+void CFWL_DateTimePicker::Update() {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_Update();
+    return;
+  }
+  if (m_iLock)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
+  GetClientRect(m_rtClient);
+  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pFWidth)
+    return;
+
+  FX_FLOAT fBtn = *pFWidth;
+  m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1,
+              m_rtClient.height - 1);
+
+  CFX_RectF rtEdit;
+  rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
+             m_rtClient.height);
+  m_pEdit->SetWidgetRect(rtEdit);
+  ResetEditAlignment();
+  m_pEdit->Update();
+  if (!(m_pMonthCal->GetThemeProvider()))
+    m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
+
+  CFX_RectF rtMonthCal;
+  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
+  CFX_RectF rtPopUp;
+  rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
+              rtMonthCal.width, rtMonthCal.height);
+  m_pMonthCal->SetWidgetRect(rtPopUp);
+  m_pMonthCal->Update();
+  return;
+}
+
+FWL_WidgetHit CFWL_DateTimePicker::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_HitTest(fx, fy);
+  if (m_rtClient.Contains(fx, fy))
+    return FWL_WidgetHit::Client;
+  if (IsMonthCalendarVisible()) {
+    CFX_RectF rect;
+    m_pMonthCal->GetWidgetRect(rect);
+    if (rect.Contains(fx, fy))
+      return FWL_WidgetHit::Client;
+  }
+  return FWL_WidgetHit::Unknown;
+}
+
+void CFWL_DateTimePicker::DrawWidget(CFX_Graphics* pGraphics,
+                                     const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  if (HasBorder())
+    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+  if (!m_rtBtn.IsEmpty())
+    DrawDropDownButton(pGraphics, pTheme, pMatrix);
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_DrawWidget(pGraphics, pMatrix);
+    return;
+  }
+}
+
+void CFWL_DateTimePicker::SetThemeProvider(IFWL_ThemeProvider* pTP) {
+  m_pProperties->m_pThemeProvider = pTP;
+  m_pMonthCal->SetThemeProvider(pTP);
+}
+
+void CFWL_DateTimePicker::GetCurSel(int32_t& iYear,
+                                    int32_t& iMonth,
+                                    int32_t& iDay) {
+  iYear = m_iYear;
+  iMonth = m_iMonth;
+  iDay = m_iDay;
 }
 
 void CFWL_DateTimePicker::SetCurSel(int32_t iYear,
                                     int32_t iMonth,
                                     int32_t iDay) {
-  ToDateTimePicker(GetWidget())->SetCurSel(iYear, iMonth, iDay);
+  if (iYear <= 0 || iYear >= 3000)
+    return;
+  if (iMonth <= 0 || iMonth >= 13)
+    return;
+  if (iDay <= 0 || iDay >= 32)
+    return;
+
+  m_iYear = iYear;
+  m_iMonth = iMonth;
+  m_iDay = iDay;
+  m_pMonthCal->SetSelect(iYear, iMonth, iDay);
 }
 
-void CFWL_DateTimePicker::GetBBox(CFX_RectF& rect) {
-  ToDateTimePicker(GetWidget())->GetBBox(rect);
+void CFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
+  if (!m_pEdit)
+    return;
+
+  m_pEdit->SetText(wsText);
+  Repaint(&m_rtClient);
+
+  CFWL_EvtEditChanged ev;
+  DispatchEvent(&ev);
 }
 
-void CFWL_DateTimePicker::SetEditLimit(int32_t nLimit) {
-  ToDateTimePicker(GetWidget())->SetEditLimit(nLimit);
+void CFWL_DateTimePicker::GetEditText(CFX_WideString& wsText,
+                                      int32_t nStart,
+                                      int32_t nCount) const {
+  if (m_pEdit)
+    m_pEdit->GetText(wsText, nStart, nCount);
+}
+
+void CFWL_DateTimePicker::GetBBox(CFX_RectF& rect) const {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    DisForm_GetBBox(rect);
+    return;
+  }
+
+  rect = m_pProperties->m_rtWidget;
+  if (IsMonthCalendarVisible()) {
+    CFX_RectF rtMonth;
+    m_pMonthCal->GetWidgetRect(rtMonth);
+    rtMonth.Offset(m_pProperties->m_rtWidget.left,
+                   m_pProperties->m_rtWidget.top);
+    rect.Union(rtMonth);
+  }
 }
 
 void CFWL_DateTimePicker::ModifyEditStylesEx(uint32_t dwStylesExAdded,
                                              uint32_t dwStylesExRemoved) {
-  ToDateTimePicker(GetWidget())
-      ->ModifyEditStylesEx(dwStylesExAdded, dwStylesExRemoved);
+  m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+}
+
+void CFWL_DateTimePicker::DrawDropDownButton(CFX_Graphics* pGraphics,
+                                             IFWL_ThemeProvider* pTheme,
+                                             const CFX_Matrix* pMatrix) {
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_Spin) ==
+      FWL_STYLEEXT_DTP_Spin) {
+    return;
+  }
+
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = CFWL_Part::DropDownButton;
+  param.m_dwStates = m_iBtnState;
+  param.m_pGraphics = pGraphics;
+  param.m_rtPart = m_rtBtn;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix);
+  pTheme->DrawBackground(&param);
+}
+
+void CFWL_DateTimePicker::FormatDateString(int32_t iYear,
+                                           int32_t iMonth,
+                                           int32_t iDay,
+                                           CFX_WideString& wsText) {
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) ==
+      FWL_STYLEEXT_DTP_ShortDateFormat) {
+    wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay);
+  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) ==
+             FWL_STYLEEXT_DTP_LongDateFormat) {
+    wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay);
+  }
+}
+
+void CFWL_DateTimePicker::ShowMonthCalendar(bool bActivate) {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_ShowMonthCalendar(bActivate);
+  if (IsMonthCalendarVisible() == bActivate)
+    return;
+  if (!m_pForm)
+    InitProxyForm();
+
+  if (!bActivate) {
+    m_pForm->EndDoModal();
+    return;
+  }
+
+  CFX_RectF rtMonth;
+  m_pMonthCal->GetWidgetRect(rtMonth);
+
+  CFX_RectF rtAnchor;
+  rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
+               m_pProperties->m_rtWidget.height);
+  GetPopupPos(0, rtMonth.height, rtAnchor, rtMonth);
+  m_pForm->SetWidgetRect(rtMonth);
+
+  rtMonth.left = rtMonth.top = 0;
+  m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
+  m_pMonthCal->SetWidgetRect(rtMonth);
+  m_pMonthCal->Update();
+  m_pForm->DoModal();
+}
+
+bool CFWL_DateTimePicker::IsMonthCalendarVisible() const {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_IsMonthCalendarVisible();
+  if (!m_pForm)
+    return false;
+  return !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
+}
+
+void CFWL_DateTimePicker::ResetEditAlignment() {
+  if (!m_pEdit)
+    return;
+
+  uint32_t dwAdd = 0;
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditHAlignMask) {
+    case FWL_STYLEEXT_DTP_EditHCenter: {
+      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
+      break;
+    }
+    case FWL_STYLEEXT_DTP_EditHFar: {
+      dwAdd |= FWL_STYLEEXT_EDT_HFar;
+      break;
+    }
+    default: {
+      dwAdd |= FWL_STYLEEXT_EDT_HNear;
+      break;
+    }
+  }
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditVAlignMask) {
+    case FWL_STYLEEXT_DTP_EditVCenter: {
+      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
+      break;
+    }
+    case FWL_STYLEEXT_DTP_EditVFar: {
+      dwAdd |= FWL_STYLEEXT_EDT_VFar;
+      break;
+    }
+    default: {
+      dwAdd |= FWL_STYLEEXT_EDT_VNear;
+      break;
+    }
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditJustified)
+    dwAdd |= FWL_STYLEEXT_EDT_Justified;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditDistributed)
+    dwAdd |= FWL_STYLEEXT_EDT_Distributed;
+
+  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
+                                     FWL_STYLEEXT_EDT_HAlignModeMask |
+                                     FWL_STYLEEXT_EDT_VAlignMask);
+}
+
+void CFWL_DateTimePicker::ProcessSelChanged(int32_t iYear,
+                                            int32_t iMonth,
+                                            int32_t iDay) {
+  m_iYear = iYear;
+  m_iMonth = iMonth;
+  m_iDay = iDay;
+
+  CFX_WideString wsText;
+  FormatDateString(m_iYear, m_iMonth, m_iDay, wsText);
+  m_pEdit->SetText(wsText);
+  m_pEdit->Update();
+  Repaint(&m_rtClient);
+
+  CFWL_EvtSelectChanged ev;
+  ev.m_pSrcTarget = this;
+  ev.iYear = m_iYear;
+  ev.iMonth = m_iMonth;
+  ev.iDay = m_iDay;
+  DispatchEvent(&ev);
+}
+
+void CFWL_DateTimePicker::InitProxyForm() {
+  if (m_pForm)
+    return;
+  if (!m_pMonthCal)
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_dwStyles = FWL_WGTSTYLE_Popup;
+  prop->m_dwStates = FWL_WGTSTATE_Invisible;
+  prop->m_pOwner = this;
+
+  m_pForm = pdfium::MakeUnique<CFWL_FormProxy>(m_pOwnerApp, std::move(prop),
+                                               m_pMonthCal.get());
+  m_pMonthCal->SetParent(m_pForm.get());
+}
+
+bool CFWL_DateTimePicker::DisForm_IsMonthCalendarVisible() const {
+  if (!m_pMonthCal)
+    return false;
+  return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible);
+}
+
+void CFWL_DateTimePicker::DisForm_ShowMonthCalendar(bool bActivate) {
+  if (IsMonthCalendarVisible() == bActivate)
+    return;
+
+  if (bActivate) {
+    CFX_RectF rtMonthCal;
+    m_pMonthCal->GetWidgetRect(rtMonthCal, true);
+    FX_FLOAT fPopupMin = rtMonthCal.height;
+    FX_FLOAT fPopupMax = rtMonthCal.height;
+    CFX_RectF rtAnchor(m_pProperties->m_rtWidget);
+    rtAnchor.width = rtMonthCal.width;
+    rtMonthCal.left = m_rtClient.left;
+    rtMonthCal.top = rtAnchor.Height();
+    GetPopupPos(fPopupMin, fPopupMax, rtAnchor, rtMonthCal);
+    m_pMonthCal->SetWidgetRect(rtMonthCal);
+    if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0)
+      m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay);
+    m_pMonthCal->Update();
+  }
+  m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
+
+  if (bActivate) {
+    CFWL_MsgSetFocus msg;
+    msg.m_pDstTarget = m_pMonthCal.get();
+    msg.m_pSrcTarget = m_pEdit.get();
+    m_pEdit->GetDelegate()->OnProcessMessage(&msg);
+  }
+
+  CFX_RectF rtInvalidate, rtCal;
+  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
+                   m_pProperties->m_rtWidget.height);
+  m_pMonthCal->GetWidgetRect(rtCal);
+  rtInvalidate.Union(rtCal);
+  rtInvalidate.Inflate(2, 2);
+  Repaint(&rtInvalidate);
+}
+
+FWL_WidgetHit CFWL_DateTimePicker::DisForm_HitTest(FX_FLOAT fx,
+                                                   FX_FLOAT fy) const {
+  CFX_RectF rect;
+  rect.Set(0, 0, m_pProperties->m_rtWidget.width,
+           m_pProperties->m_rtWidget.height);
+  if (rect.Contains(fx, fy))
+    return FWL_WidgetHit::Edit;
+  if (DisForm_IsNeedShowButton())
+    rect.width += m_fBtn;
+  if (rect.Contains(fx, fy))
+    return FWL_WidgetHit::Client;
+  if (IsMonthCalendarVisible()) {
+    m_pMonthCal->GetWidgetRect(rect);
+    if (rect.Contains(fx, fy))
+      return FWL_WidgetHit::Client;
+  }
+  return FWL_WidgetHit::Unknown;
+}
+
+bool CFWL_DateTimePicker::DisForm_IsNeedShowButton() const {
+  return m_pProperties->m_dwStates & FWL_WGTSTATE_Focused ||
+         m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused ||
+         m_pEdit->GetStates() & FWL_WGTSTATE_Focused;
+}
+
+void CFWL_DateTimePicker::DisForm_Update() {
+  if (m_iLock)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
+  GetClientRect(m_rtClient);
+  m_pEdit->SetWidgetRect(m_rtClient);
+  ResetEditAlignment();
+  m_pEdit->Update();
+
+  if (!m_pMonthCal->GetThemeProvider())
+    m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
+
+  FX_FLOAT* pWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pWidth)
+    return;
+
+  m_fBtn = *pWidth;
+  CFX_RectF rtMonthCal;
+  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
+
+  CFX_RectF rtPopUp;
+  rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
+              rtMonthCal.width, rtMonthCal.height);
+  m_pMonthCal->SetWidgetRect(rtPopUp);
+  m_pMonthCal->Update();
+}
+
+void CFWL_DateTimePicker::DisForm_GetWidgetRect(CFX_RectF& rect,
+                                                bool bAutoSize) {
+  rect = m_pProperties->m_rtWidget;
+  if (DisForm_IsNeedShowButton())
+    rect.width += m_fBtn;
+}
+
+void CFWL_DateTimePicker::DisForm_GetBBox(CFX_RectF& rect) const {
+  rect = m_pProperties->m_rtWidget;
+  if (DisForm_IsNeedShowButton())
+    rect.width += m_fBtn;
+  if (!IsMonthCalendarVisible())
+    return;
+
+  CFX_RectF rtMonth;
+  m_pMonthCal->GetWidgetRect(rtMonth);
+  rtMonth.Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
+  rect.Union(rtMonth);
+}
+
+void CFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics,
+                                             const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (m_pEdit) {
+    CFX_RectF rtEdit;
+    m_pEdit->GetWidgetRect(rtEdit);
+
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
+    if (pMatrix)
+      mt.Concat(*pMatrix);
+    m_pEdit->DrawWidget(pGraphics, &mt);
+  }
+  if (!IsMonthCalendarVisible())
+    return;
+
+  CFX_RectF rtMonth;
+  m_pMonthCal->GetWidgetRect(rtMonth);
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, rtMonth.left, rtMonth.top);
+  if (pMatrix)
+    mt.Concat(*pMatrix);
+  m_pMonthCal->DrawWidget(pGraphics, &mt);
+}
+
+void CFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+
+  switch (pMessage->GetClassID()) {
+    case CFWL_MessageType::SetFocus:
+      OnFocusChanged(pMessage, true);
+      break;
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(pMessage, false);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMouse->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown(pMouse);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMouse);
+          break;
+        case FWL_MouseCommand::Move:
+          OnMouseMove(pMouse);
+          break;
+        case FWL_MouseCommand::Leave:
+          OnMouseLeave(pMouse);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
+        m_pEdit->GetDelegate()->OnProcessMessage(pMessage);
+        return;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_DateTimePicker::OnDrawWidget(CFX_Graphics* pGraphics,
+                                       const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_DateTimePicker::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  if (!pMsg)
+    return;
+  if (m_pWidgetMgr->IsFormDisabled())
+    return DisForm_OnFocusChanged(pMsg, bSet);
+
+  if (bSet) {
+    m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
+    Repaint(&m_rtClient);
+  } else {
+    m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
+    Repaint(&m_rtClient);
+  }
+  if (pMsg->m_pSrcTarget == m_pMonthCal.get() && IsMonthCalendarVisible()) {
+    ShowMonthCalendar(false);
+  }
+  Repaint(&m_rtClient);
+}
+
+void CFWL_DateTimePicker::OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  if (!pMsg)
+    return;
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    SetFocus(true);
+  if (!m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    return;
+
+  if (IsMonthCalendarVisible()) {
+    ShowMonthCalendar(false);
+    return;
+  }
+  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_TimeFormat))
+    ShowMonthCalendar(true);
+
+  m_bLBtnDown = true;
+  Repaint(&m_rtClient);
+}
+
+void CFWL_DateTimePicker::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  if (!pMsg)
+    return;
+
+  m_bLBtnDown = false;
+  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    m_iBtnState = CFWL_PartState_Hovered;
+  else
+    m_iBtnState = CFWL_PartState_Normal;
+  Repaint(&m_rtBtn);
+}
+
+void CFWL_DateTimePicker::OnMouseMove(CFWL_MsgMouse* pMsg) {
+  if (!m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
+    m_iBtnState = CFWL_PartState_Normal;
+  Repaint(&m_rtBtn);
+}
+
+void CFWL_DateTimePicker::OnMouseLeave(CFWL_MsgMouse* pMsg) {
+  if (!pMsg)
+    return;
+  m_iBtnState = CFWL_PartState_Normal;
+  Repaint(&m_rtBtn);
+}
+
+void CFWL_DateTimePicker::DisForm_OnFocusChanged(CFWL_Message* pMsg,
+                                                 bool bSet) {
+  CFX_RectF rtInvalidate(m_rtBtn);
+  if (bSet) {
+    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
+    if (m_pEdit && !(m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) {
+      m_rtBtn.Set(m_pProperties->m_rtWidget.width, 0, m_fBtn,
+                  m_pProperties->m_rtWidget.height - 1);
+    }
+    rtInvalidate = m_rtBtn;
+    pMsg->m_pDstTarget = m_pEdit.get();
+    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
+  } else {
+    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
+    m_rtBtn.Set(0, 0, 0, 0);
+    if (DisForm_IsMonthCalendarVisible())
+      ShowMonthCalendar(false);
+    if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
+      pMsg->m_pSrcTarget = m_pEdit.get();
+      m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
+    }
+  }
+  rtInvalidate.Inflate(2, 2);
+  Repaint(&rtInvalidate);
 }
diff --git a/xfa/fwl/core/cfwl_datetimepicker.h b/xfa/fwl/core/cfwl_datetimepicker.h
index 08e092e..c5dd0ae 100644
--- a/xfa/fwl/core/cfwl_datetimepicker.h
+++ b/xfa/fwl/core/cfwl_datetimepicker.h
@@ -7,26 +7,112 @@
 #ifndef XFA_FWL_CORE_CFWL_DATETIMEPICKER_H_
 #define XFA_FWL_CORE_CFWL_DATETIMEPICKER_H_
 
+#include <memory>
+
+#include "xfa/fwl/core/cfwl_datetimeedit.h"
+#include "xfa/fwl/core/cfwl_event.h"
+#include "xfa/fwl/core/cfwl_monthcalendar.h"
 #include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
+
+#define FWL_STYLEEXT_DTP_AllowEdit (1L << 0)
+#define FWL_STYLEEXT_DTP_LongDateFormat (0L << 1)
+#define FWL_STYLEEXT_DTP_ShortDateFormat (1L << 1)
+#define FWL_STYLEEXT_DTP_TimeFormat (2L << 1)
+#define FWL_STYLEEXT_DTP_Spin (1L << 3)
+#define FWL_STYLEEXT_DTP_EditHNear (0L << 4)
+#define FWL_STYLEEXT_DTP_EditHCenter (1L << 4)
+#define FWL_STYLEEXT_DTP_EditHFar (2L << 4)
+#define FWL_STYLEEXT_DTP_EditVNear (0L << 6)
+#define FWL_STYLEEXT_DTP_EditVCenter (1L << 6)
+#define FWL_STYLEEXT_DTP_EditVFar (2L << 6)
+#define FWL_STYLEEXT_DTP_EditJustified (1L << 8)
+#define FWL_STYLEEXT_DTP_EditDistributed (2L << 8)
+#define FWL_STYLEEXT_DTP_EditHAlignMask (3L << 4)
+#define FWL_STYLEEXT_DTP_EditVAlignMask (3L << 6)
+#define FWL_STYLEEXT_DTP_EditHAlignModeMask (3L << 8)
+
+class CFWL_DateTimeEdit;
+class CFWL_FormProxy;
 
 class CFWL_DateTimePicker : public CFWL_Widget {
  public:
   explicit CFWL_DateTimePicker(const CFWL_App* pApp);
   ~CFWL_DateTimePicker() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void Update() override;
+  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void SetThemeProvider(IFWL_ThemeProvider* pTP) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
 
-  void GetEditText(CFX_WideString& wsText);
-  void SetEditText(const CFX_WideString& wsText);
-
-  int32_t CountSelRanges();
-  int32_t GetSelRange(int32_t nIndex, int32_t& nStart);
-
+  void GetCurSel(int32_t& iYear, int32_t& iMonth, int32_t& iDay);
   void SetCurSel(int32_t iYear, int32_t iMonth, int32_t iDay);
-  void GetBBox(CFX_RectF& rect);
-  void SetEditLimit(int32_t nLimit);
+
+  void SetEditText(const CFX_WideString& wsText);
+  void GetEditText(CFX_WideString& wsText,
+                   int32_t nStart = 0,
+                   int32_t nCount = -1) const;
+
+  int32_t CountSelRanges() const { return m_pEdit->CountSelRanges(); }
+  int32_t GetSelRange(int32_t nIndex, int32_t& nStart) const {
+    return m_pEdit->GetSelRange(nIndex, nStart);
+  }
+
+  void GetBBox(CFX_RectF& rect) const;
+  void SetEditLimit(int32_t nLimit) { m_pEdit->SetLimit(nLimit); }
   void ModifyEditStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved);
+
+  bool IsMonthCalendarVisible() const;
+  void ShowMonthCalendar(bool bActivate);
+  void ProcessSelChanged(int32_t iYear, int32_t iMonth, int32_t iDay);
+
+  CFWL_FormProxy* GetFormProxy() const { return m_pForm.get(); }
+
+ private:
+  void DrawDropDownButton(CFX_Graphics* pGraphics,
+                          IFWL_ThemeProvider* pTheme,
+                          const CFX_Matrix* pMatrix);
+  void FormatDateString(int32_t iYear,
+                        int32_t iMonth,
+                        int32_t iDay,
+                        CFX_WideString& wsText);
+  void ResetEditAlignment();
+  void InitProxyForm();
+
+  bool DisForm_IsMonthCalendarVisible() const;
+  void DisForm_ShowMonthCalendar(bool bActivate);
+  FWL_WidgetHit DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) const;
+  bool DisForm_IsNeedShowButton() const;
+  void DisForm_Update();
+  void DisForm_GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false);
+  void DisForm_GetBBox(CFX_RectF& rect) const;
+  void DisForm_DrawWidget(CFX_Graphics* pGraphics,
+                          const CFX_Matrix* pMatrix = nullptr);
+  void DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet);
+  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
+  void OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnMouseMove(CFWL_MsgMouse* pMsg);
+  void OnMouseLeave(CFWL_MsgMouse* pMsg);
+
+  CFX_RectF m_rtBtn;
+  CFX_RectF m_rtClient;
+  int32_t m_iBtnState;
+  int32_t m_iYear;
+  int32_t m_iMonth;
+  int32_t m_iDay;
+  bool m_bLBtnDown;
+  std::unique_ptr<CFWL_DateTimeEdit> m_pEdit;
+  std::unique_ptr<CFWL_MonthCalendar> m_pMonthCal;
+  std::unique_ptr<CFWL_FormProxy> m_pForm;
+  FX_FLOAT m_fBtn;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_DATETIMEPICKER_H_
diff --git a/xfa/fwl/core/cfwl_edit.cpp b/xfa/fwl/core/cfwl_edit.cpp
index e404b1d..99cac68 100644
--- a/xfa/fwl/core/cfwl_edit.cpp
+++ b/xfa/fwl/core/cfwl_edit.cpp
@@ -6,67 +6,1656 @@
 
 #include "xfa/fwl/core/cfwl_edit.h"
 
+#include <algorithm>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "third_party/base/ptr_util.h"
+#include "third_party/base/stl_util.h"
+#include "xfa/fde/cfde_txtedtengine.h"
+#include "xfa/fde/fde_gedevice.h"
+#include "xfa/fde/fde_render.h"
+#include "xfa/fde/ifde_txtedtpage.h"
+#include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_caret.h"
+#include "xfa/fwl/core/cfwl_evtcheckword.h"
+#include "xfa/fwl/core/cfwl_evttextchanged.h"
+#include "xfa/fwl/core/cfwl_evttextfull.h"
+#include "xfa/fwl/core/cfwl_evtvalidate.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
+#include "xfa/fwl/core/cfwl_widgetmgr.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
+#include "xfa/fxfa/xfa_ffdoc.h"
+#include "xfa/fxfa/xfa_ffwidget.h"
+#include "xfa/fxgraphics/cfx_path.h"
 
 namespace {
 
-IFWL_Edit* ToEdit(IFWL_Widget* widget) {
-  return static_cast<IFWL_Edit*>(widget);
+const int kEditMargin = 3;
+
+bool FX_EDIT_ISLATINWORD(FX_WCHAR c) {
+  return c == 0x2D || (c <= 0x005A && c >= 0x0041) ||
+         (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) ||
+         c == 0x0027;
+}
+
+void AddSquigglyPath(CFX_Path* pPathData,
+                     FX_FLOAT fStartX,
+                     FX_FLOAT fEndX,
+                     FX_FLOAT fY,
+                     FX_FLOAT fStep) {
+  pPathData->MoveTo(fStartX, fY);
+  int i = 1;
+  for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i)
+    pPathData->LineTo(fx, fY + (i & 1) * fStep);
 }
 
 }  // namespace
 
-CFWL_Edit::CFWL_Edit(const CFWL_App* app) : CFWL_Widget(app) {}
+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_fVAlignOffset(0.0f),
+      m_fScrollOffsetX(0.0f),
+      m_fScrollOffsetY(0.0f),
+      m_bLButtonDown(false),
+      m_nSelStart(0),
+      m_nLimit(-1),
+      m_fFontSize(0),
+      m_bSetRange(false),
+      m_iMax(0xFFFFFFF),
+      m_iCurRecord(-1),
+      m_iMaxRecord(128) {
+  m_rtClient.Reset();
+  m_rtEngine.Reset();
+  m_rtStatic.Reset();
 
-CFWL_Edit::~CFWL_Edit() {}
+  InitCaret();
+}
 
-void CFWL_Edit::Initialize() {
-  ASSERT(!m_pIface);
+CFWL_Edit::~CFWL_Edit() {
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+    ShowCaret(false);
+  ClearRecord();
+}
 
-  m_pIface = pdfium::MakeUnique<IFWL_Edit>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
+FWL_Type CFWL_Edit::GetClassID() const {
+  return FWL_Type::Edit;
+}
 
-  CFWL_Widget::Initialize();
+void CFWL_Edit::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+      if (IsShowScrollBar(true)) {
+        FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
+            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+        rect.width += *pfWidth;
+        rect.width += kEditMargin;
+      }
+      if (IsShowScrollBar(false)) {
+        FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
+            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+        rect.height += *pfWidth;
+        rect.height += kEditMargin;
+      }
+    }
+    return;
+  }
+
+  rect.Set(0, 0, 0, 0);
+
+  int32_t iTextLen = m_EdtEngine.GetTextLength();
+  if (iTextLen > 0) {
+    CFX_WideString wsText;
+    m_EdtEngine.GetText(wsText, 0);
+    CFX_SizeF sz = CalcTextSize(
+        wsText, m_pProperties->m_pThemeProvider,
+        !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine));
+    rect.Set(0, 0, sz.x, sz.y);
+  }
+  CFWL_Widget::GetWidgetRect(rect, true);
+}
+
+void CFWL_Edit::SetStates(uint32_t dwStates, bool bSet) {
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
+      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
+    ShowCaret(false);
+  }
+  CFWL_Widget::SetStates(dwStates, bSet);
+}
+
+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(FX_FLOAT fx, FX_FLOAT fy) {
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+    if (IsShowScrollBar(true)) {
+      CFX_RectF rect;
+      m_pVertScrollBar->GetWidgetRect(rect);
+      if (rect.Contains(fx, fy))
+        return FWL_WidgetHit::VScrollBar;
+    }
+    if (IsShowScrollBar(false)) {
+      CFX_RectF rect;
+      m_pHorzScrollBar->GetWidgetRect(rect);
+      if (rect.Contains(fx, fy))
+        return FWL_WidgetHit::HScrollBar;
+    }
+  }
+  if (m_rtClient.Contains(fx, fy))
+    return FWL_WidgetHit::Edit;
+  return FWL_WidgetHit::Unknown;
+}
+
+void CFWL_Edit::AddSpellCheckObj(CFX_Path& PathData,
+                                 int32_t nStart,
+                                 int32_t nCount,
+                                 FX_FLOAT fOffSetX,
+                                 FX_FLOAT fOffSetY) {
+  FX_FLOAT fStartX = 0.0f;
+  FX_FLOAT fEndX = 0.0f;
+  FX_FLOAT fY = 0.0f;
+  FX_FLOAT fStep = 0.0f;
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  CFX_RectFArray rectArray;
+  CFX_RectF rectText;
+  const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams();
+  FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) *
+                    txtEdtParams->fFontSize / 1000;
+  pPage->CalcRangeRectArray(nStart, nCount, rectArray);
+
+  for (int i = 0; i < rectArray.GetSize(); i++) {
+    rectText = rectArray.GetAt(i);
+    fY = rectText.top + fAsent + fOffSetY;
+    fStep = txtEdtParams->fFontSize / 16.0f;
+    fStartX = rectText.left + fOffSetX;
+    fEndX = fStartX + rectText.Width();
+    AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep);
+  }
+}
+
+void CFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix) {
+  pGraphics->SaveGraphState();
+  if (pMatrix)
+    pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix));
+
+  CFX_Color crLine(0xFFFF0000);
+  CFWL_EvtCheckWord checkWordEvent;
+  checkWordEvent.m_pSrcTarget = this;
+
+  CFX_ByteString sLatinWord;
+  CFX_Path pathSpell;
+  pathSpell.Create();
+
+  int32_t nStart = 0;
+  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
+  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
+
+  CFX_WideString wsSpell;
+  GetText(wsSpell);
+  int32_t nContentLen = wsSpell.GetLength();
+  for (int i = 0; i < nContentLen; i++) {
+    if (FX_EDIT_ISLATINWORD(wsSpell[i])) {
+      if (sLatinWord.IsEmpty())
+        nStart = i;
+      sLatinWord += (FX_CHAR)wsSpell[i];
+      continue;
+    }
+    checkWordEvent.bsWord = sLatinWord;
+    checkWordEvent.bCheckWord = true;
+    DispatchEvent(&checkWordEvent);
+
+    if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
+      AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
+                       fOffSetY);
+    }
+    sLatinWord.clear();
+  }
+
+  checkWordEvent.bsWord = sLatinWord;
+  checkWordEvent.bCheckWord = true;
+  DispatchEvent(&checkWordEvent);
+
+  if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
+    AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
+                     fOffSetY);
+  }
+  if (!pathSpell.IsEmpty()) {
+    CFX_RectF rtClip = m_rtEngine;
+    CFX_Matrix mt;
+    mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
+    if (pMatrix) {
+      pMatrix->TransformRect(rtClip);
+      mt.Concat(*pMatrix);
+    }
+    pGraphics->SetClipRect(rtClip);
+    pGraphics->SetStrokeColor(&crLine);
+    pGraphics->SetLineWidth(0);
+    pGraphics->StrokePath(&pathSpell, nullptr);
+  }
+  pGraphics->RestoreGraphState();
+}
+
+void CFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+  if (m_rtClient.IsEmpty())
+    return;
+
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  if (!m_pWidgetMgr->IsFormDisabled())
+    DrawTextBk(pGraphics, pTheme, pMatrix);
+  DrawContent(pGraphics, pTheme, pMatrix);
+
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
+      !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) {
+    DrawSpellCheck(pGraphics, pMatrix);
+  }
+  if (HasBorder())
+    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+}
+
+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 CFX_WideString& wsText) {
-  if (GetWidget())
-    ToEdit(GetWidget())->SetText(wsText);
+  m_EdtEngine.SetText(wsText);
+}
+
+int32_t CFWL_Edit::GetTextLength() const {
+  return m_EdtEngine.GetTextLength();
 }
 
 void CFWL_Edit::GetText(CFX_WideString& wsText,
                         int32_t nStart,
                         int32_t nCount) const {
-  if (GetWidget())
-    ToEdit(GetWidget())->GetText(wsText, nStart, nCount);
+  m_EdtEngine.GetText(wsText, nStart, nCount);
+}
+
+void CFWL_Edit::ClearText() {
+  m_EdtEngine.ClearText();
+}
+
+void CFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) {
+  m_EdtEngine.AddSelRange(nStart, nCount);
 }
 
 int32_t CFWL_Edit::CountSelRanges() const {
-  return GetWidget() ? ToEdit(GetWidget())->CountSelRanges() : 0;
+  return m_EdtEngine.CountSelRanges();
 }
 
 int32_t CFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) const {
-  return GetWidget() ? ToEdit(GetWidget())->GetSelRange(nIndex, nStart) : 0;
+  return m_EdtEngine.GetSelRange(nIndex, nStart);
+}
+
+void CFWL_Edit::ClearSelections() {
+  m_EdtEngine.ClearSelection();
 }
 
 int32_t CFWL_Edit::GetLimit() const {
-  return GetWidget() ? ToEdit(GetWidget())->GetLimit() : -1;
+  return m_nLimit;
 }
 
 void CFWL_Edit::SetLimit(int32_t nLimit) {
-  if (GetWidget())
-    ToEdit(GetWidget())->SetLimit(nLimit);
+  m_nLimit = nLimit;
+  m_EdtEngine.SetLimit(nLimit);
 }
 
 void CFWL_Edit::SetAliasChar(FX_WCHAR wAlias) {
-  if (GetWidget())
-    ToEdit(GetWidget())->SetAliasChar(wAlias);
+  m_EdtEngine.SetAliasChar(wAlias);
+}
+
+bool CFWL_Edit::Copy(CFX_WideString& wsCopy) {
+  int32_t nCount = m_EdtEngine.CountSelRanges();
+  if (nCount == 0)
+    return false;
+
+  wsCopy.clear();
+  CFX_WideString wsTemp;
+  int32_t nStart, nLength;
+  for (int32_t i = 0; i < nCount; i++) {
+    nLength = m_EdtEngine.GetSelRange(i, nStart);
+    m_EdtEngine.GetText(wsTemp, nStart, nLength);
+    wsCopy += wsTemp;
+    wsTemp.clear();
+  }
+  return true;
+}
+
+bool CFWL_Edit::Cut(CFX_WideString& wsCut) {
+  int32_t nCount = m_EdtEngine.CountSelRanges();
+  if (nCount == 0)
+    return false;
+
+  wsCut.clear();
+  CFX_WideString wsTemp;
+  int32_t nStart, nLength;
+  for (int32_t i = 0; i < nCount; i++) {
+    nLength = m_EdtEngine.GetSelRange(i, nStart);
+    m_EdtEngine.GetText(wsTemp, nStart, nLength);
+    wsCut += wsTemp;
+    wsTemp.clear();
+  }
+  m_EdtEngine.Delete(0);
+  return true;
+}
+
+bool CFWL_Edit::Paste(const CFX_WideString& wsPaste) {
+  int32_t nCaret = m_EdtEngine.GetCaretPos();
+  int32_t iError =
+      m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength());
+  if (iError < 0) {
+    ProcessInsertError(iError);
+    return false;
+  }
+  return true;
+}
+
+bool CFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) {
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
+    return true;
+  return m_EdtEngine.Redo(pRecord);
+}
+
+bool CFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) {
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
+    return true;
+  return m_EdtEngine.Undo(pRecord);
+}
+
+bool CFWL_Edit::Undo() {
+  if (!CanUndo())
+    return false;
+  return Undo(m_DoRecords[m_iCurRecord--].get());
+}
+
+bool CFWL_Edit::Redo() {
+  if (!CanRedo())
+    return false;
+  return Redo(m_DoRecords[++m_iCurRecord].get());
+}
+
+bool CFWL_Edit::CanUndo() {
+  return m_iCurRecord >= 0;
+}
+
+bool CFWL_Edit::CanRedo() {
+  return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
+}
+
+void CFWL_Edit::SetOuter(CFWL_Widget* pOuter) {
+  m_pOuter = pOuter;
+}
+
+void CFWL_Edit::On_CaretChanged(CFDE_TxtEdtEngine* pEdit,
+                                int32_t nPage,
+                                bool bVisible) {
+  if (m_rtEngine.IsEmpty())
+    return;
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    return;
+
+  bool bRepaintContent = UpdateOffset();
+  UpdateCaret();
+  CFX_RectF rtInvalid;
+  rtInvalid.Set(0, 0, 0, 0);
+  bool bRepaintScroll = false;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
+    CFWL_ScrollBar* pScroll = UpdateScroll();
+    if (pScroll) {
+      pScroll->GetWidgetRect(rtInvalid);
+      bRepaintScroll = true;
+    }
+  }
+  if (bRepaintContent || bRepaintScroll) {
+    if (bRepaintContent)
+      rtInvalid.Union(m_rtEngine);
+    Repaint(&rtInvalid);
+  }
+}
+
+void CFWL_Edit::On_TextChanged(CFDE_TxtEdtEngine* pEdit,
+                               FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) {
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask)
+    UpdateVAlignment();
+
+  CFX_RectF rtTemp;
+  GetClientRect(rtTemp);
+
+  CFWL_EvtTextChanged event;
+  event.m_pSrcTarget = this;
+  event.nChangeType = ChangeInfo.nChangeType;
+  event.wsInsert = ChangeInfo.wsInsert;
+  event.wsDelete = ChangeInfo.wsDelete;
+  event.wsPrevText = ChangeInfo.wsPrevText;
+  DispatchEvent(&event);
+
+  LayoutScrollBar();
+  Repaint(&rtTemp);
+}
+
+void CFWL_Edit::On_SelChanged(CFDE_TxtEdtEngine* pEdit) {
+  CFX_RectF rtTemp;
+  GetClientRect(rtTemp);
+  Repaint(&rtTemp);
+}
+
+bool CFWL_Edit::On_PageLoad(CFDE_TxtEdtEngine* pEdit,
+                            int32_t nPageIndex,
+                            int32_t nPurpose) {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
+  if (!pPage)
+    return false;
+
+  pPage->LoadPage(nullptr, nullptr);
+  return true;
+}
+
+bool CFWL_Edit::On_PageUnload(CFDE_TxtEdtEngine* pEdit,
+                              int32_t nPageIndex,
+                              int32_t nPurpose) {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
+  if (!pPage)
+    return false;
+
+  pPage->UnloadPage(nullptr);
+  return true;
+}
+
+void CFWL_Edit::On_AddDoRecord(CFDE_TxtEdtEngine* pEdit,
+                               IFDE_TxtEdtDoRecord* pRecord) {
+  AddDoRecord(pRecord);
+}
+
+bool CFWL_Edit::On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText) {
+  CFWL_Widget* pDst = GetOuter();
+  if (!pDst)
+    pDst = this;
+
+  CFWL_EvtValidate event;
+  event.pDstWidget = pDst;
+  event.m_pSrcTarget = this;
+  event.wsInsert = wsText;
+  event.bValidate = true;
+  DispatchEvent(&event);
+  return event.bValidate;
 }
 
 void CFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) {
-  if (GetWidget())
-    ToEdit(GetWidget())->SetScrollOffset(fScrollOffset);
+  m_fScrollOffsetY = fScrollOffset;
+}
+
+void CFWL_Edit::DrawTextBk(CFX_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 rtScorll;
+  m_pHorzScrollBar->GetWidgetRect(rtScorll);
+
+  CFX_RectF rtStatic;
+  rtStatic.Set(m_rtClient.right() - rtScorll.height,
+               m_rtClient.bottom() - rtScorll.height, rtScorll.height,
+               rtScorll.height);
+  param.m_bStaticBackground = true;
+  param.m_bMaximize = true;
+  param.m_rtPart = rtStatic;
+  pTheme->DrawBackground(&param);
+}
+
+void CFWL_Edit::DrawContent(CFX_Graphics* pGraphics,
+                            IFWL_ThemeProvider* pTheme,
+                            const CFX_Matrix* pMatrix) {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return;
+
+  pGraphics->SaveGraphState();
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
+    pGraphics->SaveGraphState();
+
+  CFX_RectF rtClip = m_rtEngine;
+  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
+  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
+  CFX_Matrix mt;
+  mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
+  if (pMatrix) {
+    pMatrix->TransformRect(rtClip);
+    mt.Concat(*pMatrix);
+  }
+
+  bool bShowSel = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) ||
+                  (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
+  if (bShowSel) {
+    CFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(this);
+    if (pForm) {
+      bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) !=
+                 FWL_WGTSTATE_Deactivated;
+    }
+  }
+
+  int32_t nSelCount = m_EdtEngine.CountSelRanges();
+  if (bShowSel && nSelCount > 0) {
+    int32_t nPageCharStart = pPage->GetCharStart();
+    int32_t nPageCharCount = pPage->GetCharCount();
+    int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1;
+    int32_t nCharCount;
+    int32_t nCharStart;
+    CFX_RectFArray rectArr;
+    int32_t i = 0;
+    for (i = 0; i < nSelCount; i++) {
+      nCharCount = m_EdtEngine.GetSelRange(i, nCharStart);
+      int32_t nCharEnd = nCharStart + nCharCount - 1;
+      if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd)
+        continue;
+
+      int32_t nBgn = std::max(nCharStart, nPageCharStart);
+      int32_t nEnd = std::min(nCharEnd, nPageCharEnd);
+      pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1,
+                                rectArr);
+    }
+
+    int32_t nCount = rectArr.GetSize();
+    CFX_Path path;
+    path.Create();
+    for (i = 0; i < nCount; i++) {
+      rectArr[i].left += fOffSetX;
+      rectArr[i].top += fOffSetY;
+      path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width,
+                        rectArr[i].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();
+  if (!pRenderDev)
+    return;
+
+  std::unique_ptr<CFDE_RenderDevice> pRenderDevice(
+      new CFDE_RenderDevice(pRenderDev, false));
+  std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext);
+  pRenderDevice->SetClipRect(rtClip);
+  pRenderContext->StartRender(pRenderDevice.get(), pPage, mt);
+  pRenderContext->DoRender(nullptr);
+
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
+    pGraphics->RestoreGraphState();
+    CFX_Path path;
+    path.Create();
+    int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
+    FX_FLOAT fStep = m_rtEngine.width / iLimit;
+    FX_FLOAT fLeft = m_rtEngine.left + 1;
+    for (int32_t i = 1; i < iLimit; i++) {
+      fLeft += fStep;
+      path.AddLine(fLeft, m_rtClient.top, 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::UpdateEditEngine() {
+  UpdateEditParams();
+  UpdateEditLayout();
+  if (m_nLimit > -1)
+    m_EdtEngine.SetLimit(m_nLimit);
+}
+
+void CFWL_Edit::UpdateEditParams() {
+  FDE_TXTEDTPARAMS params;
+  params.nHorzScale = 100;
+  params.fPlateWidth = m_rtEngine.width;
+  params.fPlateHeight = m_rtEngine.height;
+  if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight)
+    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate)
+    params.dwMode |= FDE_TEXTEDITMODE_Validate;
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password)
+    params.dwMode |= FDE_TEXTEDITMODE_Password;
+
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
+    case FWL_STYLEEXT_EDT_HNear: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Left;
+      break;
+    }
+    case FWL_STYLEEXT_EDT_HCenter: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Center;
+      break;
+    }
+    case FWL_STYLEEXT_EDT_HFar: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Right;
+      break;
+    }
+    default:
+      break;
+  }
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
+    case FWL_STYLEEXT_EDT_Justified: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Justified;
+      break;
+    }
+    case FWL_STYLEEXT_EDT_Distributed: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed;
+      break;
+    }
+    default: {
+      params.dwAlignment |= FDE_TEXTEDITALIGN_Normal;
+      break;
+    }
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
+    params.dwMode |= FDE_TEXTEDITMODE_MultiLines;
+    if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 &&
+        (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
+      params.dwMode |=
+          FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz;
+    }
+    if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
+        (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) {
+      params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert;
+    } else {
+      params.fPlateHeight = 0x00FFFFFF;
+    }
+  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) ==
+             0) {
+    params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz;
+  }
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
+      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
+    params.dwMode |= FDE_TEXTEDITMODE_ReadOnly;
+  }
+
+  FX_FLOAT* pFontSize =
+      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
+  if (!pFontSize)
+    return;
+
+  m_fFontSize = *pFontSize;
+  uint32_t* pFontColor =
+      static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor));
+  if (!pFontColor)
+    return;
+
+  params.dwFontColor = *pFontColor;
+  FX_FLOAT* pLineHeight =
+      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight));
+  if (!pLineHeight)
+    return;
+
+  params.fLineSpace = *pLineHeight;
+  CFGAS_GEFont* pFont =
+      static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font));
+  if (!pFont)
+    return;
+
+  params.pFont = pFont;
+  params.fFontSize = m_fFontSize;
+  params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace);
+  if (params.nLineCount <= 0)
+    params.nLineCount = 1;
+  params.fTabWidth = params.fFontSize * 1;
+  params.bTabEquidistant = true;
+  params.wLineBreakChar = L'\n';
+  params.nCharRotation = 0;
+  params.pEventSink = this;
+  m_EdtEngine.SetEditParams(params);
+}
+
+void CFWL_Edit::UpdateEditLayout() {
+  if (m_EdtEngine.GetTextLength() <= 0)
+    m_EdtEngine.SetTextByStream(nullptr);
+
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (pPage)
+    pPage->UnloadPage(nullptr);
+
+  m_EdtEngine.StartLayout();
+  m_EdtEngine.DoLayout(nullptr);
+  m_EdtEngine.EndLayout();
+  pPage = m_EdtEngine.GetPage(0);
+  if (pPage)
+    pPage->LoadPage(nullptr, nullptr);
+}
+
+bool CFWL_Edit::UpdateOffset() {
+  CFX_RectF rtCaret;
+  m_EdtEngine.GetCaretRect(rtCaret);
+  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
+  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
+  rtCaret.Offset(fOffSetX, fOffSetY);
+  const CFX_RectF& rtEidt = m_rtEngine;
+  if (rtEidt.Contains(rtCaret)) {
+    IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+    if (!pPage)
+      return false;
+
+    CFX_RectF rtFDE = pPage->GetContentsBox();
+    rtFDE.Offset(fOffSetX, fOffSetY);
+    if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) {
+      m_fScrollOffsetX += rtFDE.right() - rtEidt.right();
+      m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f);
+    }
+    if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) {
+      m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom();
+      m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f);
+    }
+    return false;
+  }
+
+  FX_FLOAT offsetX = 0.0;
+  FX_FLOAT offsetY = 0.0;
+  if (rtCaret.left < rtEidt.left)
+    offsetX = rtCaret.left - rtEidt.left;
+  if (rtCaret.right() > rtEidt.right())
+    offsetX = rtCaret.right() - rtEidt.right();
+  if (rtCaret.top < rtEidt.top)
+    offsetY = rtCaret.top - rtEidt.top;
+  if (rtCaret.bottom() > rtEidt.bottom())
+    offsetY = rtCaret.bottom() - rtEidt.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, FX_FLOAT fPosChanged) {
+  if (pScrollBar == m_pHorzScrollBar.get())
+    m_fScrollOffsetX += fPosChanged;
+  else
+    m_fScrollOffsetY += fPosChanged;
+  return true;
+}
+
+void CFWL_Edit::UpdateVAlignment() {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return;
+
+  const CFX_RectF& rtFDE = pPage->GetContentsBox();
+  FX_FLOAT fOffsetY = 0.0f;
+  FX_FLOAT fSpaceAbove = 0.0f;
+  FX_FLOAT fSpaceBelow = 0.0f;
+  CFX_SizeF* pSpace = static_cast<CFX_SizeF*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow));
+  if (pSpace) {
+    fSpaceAbove = pSpace->x;
+    fSpaceBelow = pSpace->y;
+  }
+  if (fSpaceAbove < 0.1f)
+    fSpaceAbove = 0;
+  if (fSpaceBelow < 0.1f)
+    fSpaceBelow = 0;
+
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
+    fOffsetY = (m_rtEngine.height - rtFDE.height) / 2;
+    if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 &&
+        fSpaceAbove < fSpaceBelow) {
+      return;
+    }
+    fOffsetY += (fSpaceAbove - fSpaceBelow) / 2;
+  } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
+    fOffsetY = (m_rtEngine.height - rtFDE.height);
+    fOffsetY -= fSpaceBelow;
+  } else {
+    fOffsetY += fSpaceAbove;
+  }
+  m_fVAlignOffset = std::max(fOffsetY, 0.0f);
+}
+
+void CFWL_Edit::UpdateCaret() {
+  CFX_RectF rtFDE;
+  m_EdtEngine.GetCaretRect(rtFDE);
+
+  rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX,
+               m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);
+  CFX_RectF rtCaret;
+  rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height);
+
+  CFX_RectF rtClient;
+  GetClientRect(rtClient);
+  rtCaret.Intersect(rtClient);
+
+  if (rtCaret.left > rtClient.right()) {
+    FX_FLOAT right = rtCaret.right();
+    rtCaret.left = rtClient.right() - 1;
+    rtCaret.width = right - rtCaret.left;
+  }
+
+  bool bShow =
+      m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty();
+  ShowCaret(bShow, &rtCaret);
+}
+
+CFWL_ScrollBar* CFWL_Edit::UpdateScroll() {
+  bool bShowHorz =
+      m_pHorzScrollBar &&
+      ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
+  bool bShowVert =
+      m_pVertScrollBar &&
+      ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
+  if (!bShowHorz && !bShowVert)
+    return nullptr;
+
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return nullptr;
+
+  const CFX_RectF& rtFDE = pPage->GetContentsBox();
+  CFWL_ScrollBar* pRepaint = nullptr;
+  if (bShowHorz) {
+    CFX_RectF rtScroll;
+    m_pHorzScrollBar->GetWidgetRect(rtScroll);
+    if (rtScroll.width < rtFDE.width) {
+      m_pHorzScrollBar->LockUpdate();
+      FX_FLOAT fRange = rtFDE.width - rtScroll.width;
+      m_pHorzScrollBar->SetRange(0.0f, fRange);
+
+      FX_FLOAT fPos = std::min(std::max(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->SetStates(FWL_WGTSTATE_Disabled, false);
+      m_pHorzScrollBar->UnlockUpdate();
+      m_pHorzScrollBar->Update();
+      pRepaint = m_pHorzScrollBar.get();
+    } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
+      m_pHorzScrollBar->LockUpdate();
+      m_pHorzScrollBar->SetRange(0, -1);
+      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, true);
+      m_pHorzScrollBar->UnlockUpdate();
+      m_pHorzScrollBar->Update();
+      pRepaint = m_pHorzScrollBar.get();
+    }
+  }
+
+  if (bShowVert) {
+    CFX_RectF rtScroll;
+    m_pVertScrollBar->GetWidgetRect(rtScroll);
+    if (rtScroll.height < rtFDE.height) {
+      m_pVertScrollBar->LockUpdate();
+      FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace;
+      FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep);
+
+      m_pVertScrollBar->SetRange(0.0f, fRange);
+      FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange);
+      m_pVertScrollBar->SetPos(fPos);
+      m_pVertScrollBar->SetTrackPos(fPos);
+      m_pVertScrollBar->SetPageSize(rtScroll.height);
+      m_pVertScrollBar->SetStepSize(fStep);
+      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, false);
+      m_pVertScrollBar->UnlockUpdate();
+      m_pVertScrollBar->Update();
+      pRepaint = m_pVertScrollBar.get();
+    } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
+      m_pVertScrollBar->LockUpdate();
+      m_pVertScrollBar->SetRange(0, -1);
+      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, true);
+      m_pVertScrollBar->UnlockUpdate();
+      m_pVertScrollBar->Update();
+      pRepaint = m_pVertScrollBar.get();
+    }
+  }
+  return pRepaint;
+}
+
+bool CFWL_Edit::IsShowScrollBar(bool bVert) {
+  bool bShow =
+      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
+          ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
+                FWL_WGTSTATE_Focused
+          : true;
+  if (bVert) {
+    return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
+           (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
+           IsContentHeightOverflow();
+  }
+  return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) &&
+         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
+}
+
+bool CFWL_Edit::IsContentHeightOverflow() {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return false;
+  return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f;
+}
+
+int32_t CFWL_Edit::AddDoRecord(IFDE_TxtEdtDoRecord* pRecord) {
+  int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords);
+  if (m_iCurRecord == nCount - 1) {
+    if (nCount == m_iMaxRecord) {
+      m_DoRecords.pop_front();
+      m_iCurRecord--;
+    }
+  } else {
+    m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1,
+                      m_DoRecords.end());
+  }
+
+  m_DoRecords.push_back(std::unique_ptr<IFDE_TxtEdtDoRecord>(pRecord));
+  m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
+  return m_iCurRecord;
+}
+
+void CFWL_Edit::Layout() {
+  GetClientRect(m_rtClient);
+  m_rtEngine = m_rtClient;
+  FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pfWidth)
+    return;
+
+  FX_FLOAT fWidth = *pfWidth;
+  if (!m_pOuter) {
+    CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
+        GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
+    if (pUIMargin) {
+      m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
+                         pUIMargin->height);
+    }
+  } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) {
+    CFWL_ThemePart part;
+    part.m_pWidget = m_pOuter;
+    CFX_RectF* pUIMargin =
+        static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity(
+            &part, CFWL_WidgetCapacity::UIMargin));
+    if (pUIMargin) {
+      m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
+                         pUIMargin->height);
+    }
+  }
+
+  bool bShowVertScrollbar = IsShowScrollBar(true);
+  bool bShowHorzScrollbar = IsShowScrollBar(false);
+  if (bShowVertScrollbar) {
+    InitScrollBar();
+
+    CFX_RectF rtVertScr;
+    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+      rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
+                    m_rtClient.height);
+    } else {
+      rtVertScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
+    m_pVertScrollBar->Update();
+  } else if (m_pVertScrollBar) {
+    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+
+  if (bShowHorzScrollbar) {
+    InitScrollBar(false);
+
+    CFX_RectF rtHoriScr;
+    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+      rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
+                    m_rtClient.width, fWidth);
+    } else {
+      rtHoriScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
+    m_pHorzScrollBar->Update();
+  } else if (m_pHorzScrollBar) {
+    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+}
+
+void CFWL_Edit::LayoutScrollBar() {
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
+      0) {
+    return;
+  }
+
+  FX_FLOAT* pfWidth = nullptr;
+  bool bShowVertScrollbar = IsShowScrollBar(true);
+  bool bShowHorzScrollbar = IsShowScrollBar(false);
+  if (bShowVertScrollbar) {
+    if (!m_pVertScrollBar) {
+      pfWidth = static_cast<FX_FLOAT*>(
+          GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+      FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
+      InitScrollBar();
+      CFX_RectF rtVertScr;
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+        rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
+                      m_rtClient.height);
+      } else {
+        rtVertScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
+  } else if (m_pVertScrollBar) {
+    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+
+  if (bShowHorzScrollbar) {
+    if (!m_pHorzScrollBar) {
+      if (!pfWidth) {
+        pfWidth = static_cast<FX_FLOAT*>(
+            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+      }
+
+      FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
+      InitScrollBar(false);
+      CFX_RectF rtHoriScr;
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
+        rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
+                      m_rtClient.width, fWidth);
+      } else {
+        rtHoriScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
+  } else if (m_pHorzScrollBar) {
+    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+  if (bShowVertScrollbar || bShowHorzScrollbar)
+    UpdateScroll();
+}
+
+void CFWL_Edit::DeviceToEngine(CFX_PointF& pt) {
+  pt.x += m_fScrollOffsetX - m_rtEngine.left;
+  pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset;
+}
+
+void CFWL_Edit::InitScrollBar(bool bVert) {
+  if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar))
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
+  prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
+  prop->m_pParent = this;
+  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
+
+  CFWL_ScrollBar* sb = new CFWL_ScrollBar(m_pOwnerApp, std::move(prop), this);
+  if (bVert)
+    m_pVertScrollBar.reset(sb);
+  else
+    m_pHorzScrollBar.reset(sb);
+}
+
+bool FWL_ShowCaret(CFWL_Widget* pWidget,
+                   bool bVisible,
+                   const CFX_RectF* pRtAnchor) {
+  CXFA_FFWidget* pXFAWidget =
+      static_cast<CXFA_FFWidget*>(pWidget->GetLayoutItem());
+  if (!pXFAWidget)
+    return false;
+
+  IXFA_DocEnvironment* pDocEnvironment =
+      pXFAWidget->GetDoc()->GetDocEnvironment();
+  if (!pDocEnvironment)
+    return false;
+
+  if (bVisible) {
+    CFX_Matrix mt;
+    pXFAWidget->GetRotateMatrix(mt);
+    CFX_RectF rt(*pRtAnchor);
+    mt.TransformRect(rt);
+    pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, &rt);
+    return true;
+  }
+
+  pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, pRtAnchor);
+  return true;
+}
+
+void CFWL_Edit::ShowCaret(bool bVisible, CFX_RectF* pRect) {
+  if (m_pCaret) {
+    m_pCaret->ShowCaret(bVisible);
+    if (bVisible && !pRect->IsEmpty())
+      m_pCaret->SetWidgetRect(*pRect);
+    Repaint(&m_rtEngine);
+    return;
+  }
+
+  CFWL_Widget* pOuter = this;
+  if (bVisible) {
+    pRect->Offset(m_pProperties->m_rtWidget.left,
+                  m_pProperties->m_rtWidget.top);
+  }
+  while (pOuter->GetOuter()) {
+    pOuter = pOuter->GetOuter();
+    if (bVisible) {
+      CFX_RectF rtOuter;
+      pOuter->GetWidgetRect(rtOuter);
+      pRect->Offset(rtOuter.left, rtOuter.top);
+    }
+  }
+  FWL_ShowCaret(pOuter, bVisible, pRect);
+}
+
+bool CFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) {
+  if (!m_bSetRange)
+    return true;
+
+  CFX_WideString wsOld, wsText;
+  m_EdtEngine.GetText(wsText, 0);
+  if (wsText.IsEmpty()) {
+    if (cNum == L'0')
+      return false;
+    return true;
+  }
+
+  int32_t caretPos = m_EdtEngine.GetCaretPos();
+  if (CountSelRanges() == 0) {
+    if (cNum == L'0' && caretPos == 0)
+      return false;
+
+    int32_t nLen = wsText.GetLength();
+    CFX_WideString l = wsText.Mid(0, caretPos);
+    CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos);
+    CFX_WideString wsNew = l + cNum + r;
+    if (wsNew.GetInteger() <= m_iMax)
+      return true;
+    return false;
+  }
+
+  if (wsText.GetInteger() <= m_iMax)
+    return true;
+  return false;
+}
+
+void CFWL_Edit::InitCaret() {
+  if (!m_pCaret) {
+    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) {
+      m_pCaret.reset(new CFWL_Caret(
+          m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this));
+      m_pCaret->SetParent(this);
+      m_pCaret->SetStates(m_pProperties->m_dwStates);
+    }
+  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) ==
+             0) {
+    m_pCaret.reset();
+  }
+}
+
+void CFWL_Edit::ClearRecord() {
+  m_iCurRecord = -1;
+  m_DoRecords.clear();
+}
+
+void CFWL_Edit::ProcessInsertError(int32_t iError) {
+  if (iError != -2)
+    return;
+
+  CFWL_EvtTextFull textFullEvent;
+  textFullEvent.m_pSrcTarget = this;
+  DispatchEvent(&textFullEvent);
+}
+
+void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+
+  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
+  switch (dwMsgCode) {
+    case CFWL_MessageType::SetFocus:
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(pMessage, dwMsgCode == CFWL_MessageType::SetFocus);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonDblClk:
+          OnButtonDblClk(pMsg);
+          break;
+        case FWL_MouseCommand::Move:
+          OnMouseMove(pMsg);
+          break;
+        case FWL_MouseCommand::RightButtonDown:
+          DoButtonDown(pMsg);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
+      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
+        OnKeyDown(pKey);
+      else if (pKey->m_dwCmd == FWL_KeyCommand::Char)
+        OnChar(pKey);
+      break;
+    }
+    default:
+      break;
+  }
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) {
+  if (!pEvent)
+    return;
+  if (pEvent->GetClassID() != CFWL_EventType::Scroll)
+    return;
+
+  CFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
+  if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
+      (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
+    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
+    OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
+             pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
+  }
+}
+
+void CFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics,
+                             const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_Edit::DoButtonDown(CFWL_MsgMouse* pMsg) {
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    SetFocus(true);
+
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return;
+
+  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
+  DeviceToEngine(pt);
+  bool bBefore = true;
+  int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
+  if (nIndex < 0)
+    nIndex = 0;
+
+  m_EdtEngine.SetCaretPos(nIndex, bBefore);
+}
+
+void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  uint32_t dwStyleEx = GetStylesEx();
+  bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret);
+  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;
+    ShowCaret(false);
+    if ((dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) {
+      int32_t nSel = CountSelRanges();
+      if (nSel > 0) {
+        ClearSelections();
+        bRepaint = true;
+      }
+      m_EdtEngine.SetCaretPos(0, true);
+      UpdateOffset();
+    }
+    ClearRecord();
+  }
+
+  LayoutScrollBar();
+  if (!bRepaint)
+    return;
+
+  CFX_RectF rtInvalidate;
+  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
+                   m_pProperties->m_rtWidget.height);
+  Repaint(&rtInvalidate);
+}
+
+void CFWL_Edit::OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    return;
+
+  m_bLButtonDown = true;
+  SetGrab(true);
+  DoButtonDown(pMsg);
+  int32_t nIndex = m_EdtEngine.GetCaretPos();
+  bool bRepaint = false;
+  if (m_EdtEngine.CountSelRanges() > 0) {
+    m_EdtEngine.ClearSelection();
+    bRepaint = true;
+  }
+
+  if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) {
+    int32_t iStart = std::min(m_nSelStart, nIndex);
+    int32_t iEnd = std::max(m_nSelStart, nIndex);
+    m_EdtEngine.AddSelRange(iStart, iEnd - iStart);
+    bRepaint = true;
+  } else {
+    m_nSelStart = nIndex;
+  }
+  if (bRepaint)
+    Repaint(&m_rtEngine);
+}
+
+void CFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  m_bLButtonDown = false;
+  SetGrab(false);
+}
+
+void CFWL_Edit::OnButtonDblClk(CFWL_MsgMouse* pMsg) {
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return;
+
+  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
+  DeviceToEngine(pt);
+  int32_t nCount = 0;
+  int32_t nIndex = pPage->SelectWord(pt, nCount);
+  if (nIndex < 0)
+    return;
+
+  m_EdtEngine.AddSelRange(nIndex, nCount);
+  m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false);
+  Repaint(&m_rtEngine);
+}
+
+void CFWL_Edit::OnMouseMove(CFWL_MsgMouse* pMsg) {
+  if (m_nSelStart == -1 || !m_bLButtonDown)
+    return;
+
+  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
+  if (!pPage)
+    return;
+
+  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
+  DeviceToEngine(pt);
+  bool bBefore = true;
+  int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
+  m_EdtEngine.SetCaretPos(nIndex, bBefore);
+  nIndex = m_EdtEngine.GetCaretPos();
+  m_EdtEngine.ClearSelection();
+
+  if (nIndex == m_nSelStart)
+    return;
+
+  int32_t nLen = m_EdtEngine.GetTextLength();
+  if (m_nSelStart >= nLen)
+    m_nSelStart = nLen;
+
+  m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex),
+                          FXSYS_abs(nIndex - m_nSelStart));
+}
+
+void CFWL_Edit::OnKeyDown(CFWL_MsgKey* pMsg) {
+  FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone;
+  bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
+  bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);
+  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
+  switch (dwKeyCode) {
+    case FWL_VKEY_Left: {
+      MoveCaret = MC_Left;
+      break;
+    }
+    case FWL_VKEY_Right: {
+      MoveCaret = MC_Right;
+      break;
+    }
+    case FWL_VKEY_Up: {
+      MoveCaret = MC_Up;
+      break;
+    }
+    case FWL_VKEY_Down: {
+      MoveCaret = MC_Down;
+      break;
+    }
+    case FWL_VKEY_Home: {
+      MoveCaret = bCtrl ? MC_Home : MC_LineStart;
+      break;
+    }
+    case FWL_VKEY_End: {
+      MoveCaret = bCtrl ? MC_End : MC_LineEnd;
+      break;
+    }
+    case FWL_VKEY_Insert:
+      break;
+    case FWL_VKEY_Delete: {
+      if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
+          (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
+        break;
+      }
+      int32_t nCaret = m_EdtEngine.GetCaretPos();
+#if (_FX_OS_ == _FX_MACOSX_)
+      m_EdtEngine.Delete(nCaret, true);
+#else
+      m_EdtEngine.Delete(nCaret);
+#endif
+      break;
+    }
+    case FWL_VKEY_F2:
+      break;
+    case FWL_VKEY_Tab: {
+      DispatchKeyEvent(pMsg);
+      break;
+    }
+    default:
+      break;
+  }
+  if (MoveCaret != MC_MoveNone)
+    m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl);
+}
+
+void CFWL_Edit::OnChar(CFWL_MsgKey* pMsg) {
+  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
+      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
+    return;
+  }
+
+  int32_t iError = 0;
+  FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode);
+  int32_t nCaret = m_EdtEngine.GetCaretPos();
+  switch (c) {
+    case FWL_VKEY_Back:
+      m_EdtEngine.Delete(nCaret, true);
+      break;
+    case FWL_VKEY_NewLine:
+    case FWL_VKEY_Escape:
+      break;
+    case FWL_VKEY_Tab: {
+      iError = m_EdtEngine.Insert(nCaret, L"\t", 1);
+      break;
+    }
+    case FWL_VKEY_Return: {
+      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) {
+        iError = m_EdtEngine.Insert(nCaret, L"\n", 1);
+      }
+      break;
+    }
+    default: {
+      if (!m_pWidgetMgr->IsFormDisabled()) {
+        if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) {
+          if (((pMsg->m_dwKeyCode < FWL_VKEY_0) &&
+               (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) ||
+              pMsg->m_dwKeyCode > FWL_VKEY_9) {
+            break;
+          }
+          if (!ValidateNumberChar(c))
+            break;
+        }
+      }
+#if (_FX_OS_ == _FX_MACOSX_)
+      if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
+#else
+      if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
+#endif
+      {
+        break;
+      }
+      iError = m_EdtEngine.Insert(nCaret, &c, 1);
+      break;
+    }
+  }
+  if (iError < 0)
+    ProcessInsertError(iError);
+}
+
+bool CFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar,
+                         FWL_SCBCODE dwCode,
+                         FX_FLOAT fPos) {
+  CFX_SizeF fs;
+  pScrollBar->GetRange(&fs.x, &fs.y);
+  FX_FLOAT iCurPos = pScrollBar->GetPos();
+  FX_FLOAT fStep = pScrollBar->GetStepSize();
+  switch (dwCode) {
+    case FWL_SCBCODE::Min: {
+      fPos = fs.x;
+      break;
+    }
+    case FWL_SCBCODE::Max: {
+      fPos = fs.y;
+      break;
+    }
+    case FWL_SCBCODE::StepBackward: {
+      fPos -= fStep;
+      if (fPos < fs.x + fStep / 2) {
+        fPos = fs.x;
+      }
+      break;
+    }
+    case FWL_SCBCODE::StepForward: {
+      fPos += fStep;
+      if (fPos > fs.y - fStep / 2) {
+        fPos = fs.y;
+      }
+      break;
+    }
+    case FWL_SCBCODE::PageBackward: {
+      fPos -= pScrollBar->GetPageSize();
+      if (fPos < fs.x) {
+        fPos = fs.x;
+      }
+      break;
+    }
+    case FWL_SCBCODE::PageForward: {
+      fPos += pScrollBar->GetPageSize();
+      if (fPos > fs.y) {
+        fPos = fs.y;
+      }
+      break;
+    }
+    case FWL_SCBCODE::Pos:
+    case FWL_SCBCODE::TrackPos:
+    case FWL_SCBCODE::None:
+      break;
+    case FWL_SCBCODE::EndScroll:
+      return false;
+  }
+  if (iCurPos == fPos)
+    return true;
+
+  pScrollBar->SetPos(fPos);
+  pScrollBar->SetTrackPos(fPos);
+  UpdateOffset(pScrollBar, fPos - iCurPos);
+  UpdateCaret();
+
+  CFX_RectF rect;
+  GetWidgetRect(rect);
+  CFX_RectF rtInvalidate;
+  rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2);
+  Repaint(&rtInvalidate);
+  return true;
 }
diff --git a/xfa/fwl/core/cfwl_edit.h b/xfa/fwl/core/cfwl_edit.h
index 4570d57..3c4c807 100644
--- a/xfa/fwl/core/cfwl_edit.h
+++ b/xfa/fwl/core/cfwl_edit.h
@@ -7,34 +7,190 @@
 #ifndef XFA_FWL_CORE_CFWL_EDIT_H_
 #define XFA_FWL_CORE_CFWL_EDIT_H_
 
+#include <deque>
+#include <memory>
 #include <vector>
 
+#include "xfa/fde/cfde_txtedtengine.h"
+#include "xfa/fde/ifde_txtedtdorecord.h"
+#include "xfa/fwl/core/cfwl_event.h"
+#include "xfa/fwl/core/cfwl_scrollbar.h"
 #include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_edit.h"
+#include "xfa/fxgraphics/cfx_path.h"
+
+#define FWL_STYLEEXT_EDT_ReadOnly (1L << 0)
+#define FWL_STYLEEXT_EDT_MultiLine (1L << 1)
+#define FWL_STYLEEXT_EDT_WantReturn (1L << 2)
+#define FWL_STYLEEXT_EDT_NoHideSel (1L << 3)
+#define FWL_STYLEEXT_EDT_AutoHScroll (1L << 4)
+#define FWL_STYLEEXT_EDT_AutoVScroll (1L << 5)
+#define FWL_STYLEEXT_EDT_NoRedoUndo (1L << 6)
+#define FWL_STYLEEXT_EDT_Validate (1L << 7)
+#define FWL_STYLEEXT_EDT_Password (1L << 8)
+#define FWL_STYLEEXT_EDT_Number (1L << 9)
+#define FWL_STYLEEXT_EDT_VerticalLayout (1L << 12)
+#define FWL_STYLEEXT_EDT_VerticalChars (1L << 13)
+#define FWL_STYLEEXT_EDT_ReverseLine (1L << 14)
+#define FWL_STYLEEXT_EDT_ArabicShapes (1L << 15)
+#define FWL_STYLEEXT_EDT_ExpandTab (1L << 16)
+#define FWL_STYLEEXT_EDT_CombText (1L << 17)
+#define FWL_STYLEEXT_EDT_HNear (0L << 18)
+#define FWL_STYLEEXT_EDT_HCenter (1L << 18)
+#define FWL_STYLEEXT_EDT_HFar (2L << 18)
+#define FWL_STYLEEXT_EDT_VNear (0L << 20)
+#define FWL_STYLEEXT_EDT_VCenter (1L << 20)
+#define FWL_STYLEEXT_EDT_VFar (2L << 20)
+#define FWL_STYLEEXT_EDT_Justified (1L << 22)
+#define FWL_STYLEEXT_EDT_Distributed (2L << 22)
+#define FWL_STYLEEXT_EDT_HAlignMask (3L << 18)
+#define FWL_STYLEEXT_EDT_VAlignMask (3L << 20)
+#define FWL_STYLEEXT_EDT_HAlignModeMask (3L << 22)
+#define FWL_STYLEEXT_EDT_InnerCaret (1L << 24)
+#define FWL_STYLEEXT_EDT_ShowScrollbarFocus (1L << 25)
+#define FWL_STYLEEXT_EDT_OuterScrollbar (1L << 26)
+#define FWL_STYLEEXT_EDT_LastLineHeight (1L << 27)
 
 class IFDE_TxtEdtDoRecord;
+class CFWL_Edit;
+class CFWL_MsgMouse;
+class CFWL_WidgetProperties;
+class CFWL_Caret;
 
 class CFWL_Edit : public CFWL_Widget {
  public:
-  explicit CFWL_Edit(const CFWL_App*);
+  CFWL_Edit(const CFWL_App* app,
+            std::unique_ptr<CFWL_WidgetProperties> properties,
+            CFWL_Widget* pOuter);
   ~CFWL_Edit() override;
 
-  void Initialize();
+  // CFWL_Widget:
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void Update() override;
+  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
+  void SetStates(uint32_t dwStates, bool bSet = true) override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnProcessEvent(CFWL_Event* pEvent) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
 
-  void SetText(const CFX_WideString& wsText);
+  virtual void SetText(const CFX_WideString& wsText);
+
+  int32_t GetTextLength() const;
   void GetText(CFX_WideString& wsText,
                int32_t nStart = 0,
                int32_t nCount = -1) const;
+  void ClearText();
 
+  void AddSelRange(int32_t nStart, int32_t nCount = -1);
   int32_t CountSelRanges() const;
   int32_t GetSelRange(int32_t nIndex, int32_t& nStart) const;
-
+  void ClearSelections();
   int32_t GetLimit() const;
   void SetLimit(int32_t nLimit);
-
   void SetAliasChar(FX_WCHAR wAlias);
+  bool Copy(CFX_WideString& wsCopy);
+  bool Cut(CFX_WideString& wsCut);
+  bool Paste(const CFX_WideString& wsPaste);
+  bool Redo(const IFDE_TxtEdtDoRecord* pRecord);
+  bool Undo(const IFDE_TxtEdtDoRecord* pRecord);
+  bool Undo();
+  bool Redo();
+  bool CanUndo();
+  bool CanRedo();
 
+  void SetOuter(CFWL_Widget* pOuter);
+
+  void On_CaretChanged(CFDE_TxtEdtEngine* pEdit,
+                       int32_t nPage,
+                       bool bVisible = true);
+  void On_TextChanged(CFDE_TxtEdtEngine* pEdit,
+                      FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo);
+  void On_SelChanged(CFDE_TxtEdtEngine* pEdit);
+  bool On_PageLoad(CFDE_TxtEdtEngine* pEdit,
+                   int32_t nPageIndex,
+                   int32_t nPurpose);
+  bool On_PageUnload(CFDE_TxtEdtEngine* pEdit,
+                     int32_t nPageIndex,
+                     int32_t nPurpose);
+  void On_AddDoRecord(CFDE_TxtEdtEngine* pEdit, IFDE_TxtEdtDoRecord* pRecord);
+  bool On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText);
   void SetScrollOffset(FX_FLOAT fScrollOffset);
+
+ protected:
+  void ShowCaret(bool bVisible, CFX_RectF* pRect = nullptr);
+  const CFX_RectF& GetRTClient() const { return m_rtClient; }
+  CFDE_TxtEdtEngine* GetTxtEdtEngine() { return &m_EdtEngine; }
+
+ private:
+  void DrawTextBk(CFX_Graphics* pGraphics,
+                  IFWL_ThemeProvider* pTheme,
+                  const CFX_Matrix* pMatrix = nullptr);
+  void DrawContent(CFX_Graphics* pGraphics,
+                   IFWL_ThemeProvider* pTheme,
+                   const CFX_Matrix* pMatrix = nullptr);
+  void UpdateEditEngine();
+  void UpdateEditParams();
+  void UpdateEditLayout();
+  bool UpdateOffset();
+  bool UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged);
+  void UpdateVAlignment();
+  void UpdateCaret();
+  CFWL_ScrollBar* UpdateScroll();
+  void Layout();
+  void LayoutScrollBar();
+  void DeviceToEngine(CFX_PointF& pt);
+  void InitScrollBar(bool bVert = true);
+  void InitEngine();
+  bool ValidateNumberChar(FX_WCHAR cNum);
+  void InitCaret();
+  void ClearRecord();
+  bool IsShowScrollBar(bool bVert);
+  bool IsContentHeightOverflow();
+  int32_t AddDoRecord(IFDE_TxtEdtDoRecord* pRecord);
+  void ProcessInsertError(int32_t iError);
+
+  void DrawSpellCheck(CFX_Graphics* pGraphics,
+                      const CFX_Matrix* pMatrix = nullptr);
+  void AddSpellCheckObj(CFX_Path& PathData,
+                        int32_t nStart,
+                        int32_t nCount,
+                        FX_FLOAT fOffSetX,
+                        FX_FLOAT fOffSetY);
+  void DoButtonDown(CFWL_MsgMouse* pMsg);
+  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
+  void OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnButtonDblClk(CFWL_MsgMouse* pMsg);
+  void OnMouseMove(CFWL_MsgMouse* pMsg);
+  void OnKeyDown(CFWL_MsgKey* pMsg);
+  void OnChar(CFWL_MsgKey* pMsg);
+  bool OnScroll(CFWL_ScrollBar* pScrollBar, FWL_SCBCODE dwCode, FX_FLOAT fPos);
+
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtEngine;
+  CFX_RectF m_rtStatic;
+  FX_FLOAT m_fVAlignOffset;
+  FX_FLOAT m_fScrollOffsetX;
+  FX_FLOAT m_fScrollOffsetY;
+  CFDE_TxtEdtEngine m_EdtEngine;
+  bool m_bLButtonDown;
+  int32_t m_nSelStart;
+  int32_t m_nLimit;
+  FX_FLOAT m_fFontSize;
+  bool m_bSetRange;
+  int32_t m_iMax;
+  std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar;
+  std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar;
+  std::unique_ptr<CFWL_Caret> m_pCaret;
+  CFX_WideString m_wsCache;
+  CFX_WideString m_wsFont;
+  std::deque<std::unique_ptr<IFDE_TxtEdtDoRecord>> m_DoRecords;
+  int32_t m_iCurRecord;
+  int32_t m_iMaxRecord;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_EDIT_H_
diff --git a/xfa/fwl/core/cfwl_event.h b/xfa/fwl/core/cfwl_event.h
index 550457a..fe8e1b3 100644
--- a/xfa/fwl/core/cfwl_event.h
+++ b/xfa/fwl/core/cfwl_event.h
@@ -38,7 +38,7 @@
 };
 
 class CFX_Graphics;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_Event {
  public:
@@ -47,8 +47,8 @@
 
   virtual CFWL_EventType GetClassID() const;
 
-  IFWL_Widget* m_pSrcTarget;
-  IFWL_Widget* m_pDstTarget;
+  CFWL_Widget* m_pSrcTarget;
+  CFWL_Widget* m_pDstTarget;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_EVENT_H_
diff --git a/xfa/fwl/core/cfwl_eventtarget.cpp b/xfa/fwl/core/cfwl_eventtarget.cpp
index 836a7ed..34377c2 100644
--- a/xfa/fwl/core/cfwl_eventtarget.cpp
+++ b/xfa/fwl/core/cfwl_eventtarget.cpp
@@ -6,15 +6,15 @@
 
 #include "xfa/fwl/core/cfwl_eventtarget.h"
 
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_widgetdelegate.h"
 
-CFWL_EventTarget::CFWL_EventTarget(IFWL_Widget* pListener)
+CFWL_EventTarget::CFWL_EventTarget(CFWL_Widget* pListener)
     : m_pListener(pListener), m_bInvalid(false) {}
 
 CFWL_EventTarget::~CFWL_EventTarget() {}
 
-void CFWL_EventTarget::SetEventSource(IFWL_Widget* pSource) {
+void CFWL_EventTarget::SetEventSource(CFWL_Widget* pSource) {
   if (pSource)
     m_widgets.insert(pSource);
 }
diff --git a/xfa/fwl/core/cfwl_eventtarget.h b/xfa/fwl/core/cfwl_eventtarget.h
index 3ed8e9a..5f0ee35 100644
--- a/xfa/fwl/core/cfwl_eventtarget.h
+++ b/xfa/fwl/core/cfwl_eventtarget.h
@@ -13,22 +13,22 @@
 #include "xfa/fwl/core/cfwl_event.h"
 
 class CFWL_Event;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_EventTarget {
  public:
-  explicit CFWL_EventTarget(IFWL_Widget* pListener);
+  explicit CFWL_EventTarget(CFWL_Widget* pListener);
   ~CFWL_EventTarget();
 
-  void SetEventSource(IFWL_Widget* pSource);
+  void SetEventSource(CFWL_Widget* pSource);
   bool ProcessEvent(CFWL_Event* pEvent);
 
   bool IsInvalid() const { return m_bInvalid; }
   void FlagInvalid() { m_bInvalid = true; }
 
  private:
-  std::set<IFWL_Widget*> m_widgets;
-  IFWL_Widget* m_pListener;
+  std::set<CFWL_Widget*> m_widgets;
+  CFWL_Widget* m_pListener;
   bool m_bInvalid;
 };
 
diff --git a/xfa/fwl/core/cfwl_evtkillfocus.h b/xfa/fwl/core/cfwl_evtkillfocus.h
index 5a9d292..737053b 100644
--- a/xfa/fwl/core/cfwl_evtkillfocus.h
+++ b/xfa/fwl/core/cfwl_evtkillfocus.h
@@ -16,7 +16,7 @@
 
   CFWL_EventType GetClassID() const override;
 
-  IFWL_Widget* m_pKillFocus;
+  CFWL_Widget* m_pKillFocus;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_EVTKILLFOCUS_H_
diff --git a/xfa/fwl/core/cfwl_evtsetfocus.h b/xfa/fwl/core/cfwl_evtsetfocus.h
index b1ff43d..0232b59 100644
--- a/xfa/fwl/core/cfwl_evtsetfocus.h
+++ b/xfa/fwl/core/cfwl_evtsetfocus.h
@@ -16,7 +16,7 @@
 
   CFWL_EventType GetClassID() const override;
 
-  IFWL_Widget* m_pSetFocus;
+  CFWL_Widget* m_pSetFocus;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_EVTSETFOCUS_H_
diff --git a/xfa/fwl/core/cfwl_evtsizechanged.h b/xfa/fwl/core/cfwl_evtsizechanged.h
index fe2dc6f..33d5267 100644
--- a/xfa/fwl/core/cfwl_evtsizechanged.h
+++ b/xfa/fwl/core/cfwl_evtsizechanged.h
@@ -16,7 +16,7 @@
 
   CFWL_EventType GetClassID() const override;
 
-  IFWL_Widget* m_pWidget;
+  CFWL_Widget* m_pWidget;
   CFX_RectF m_rtOld;
   CFX_RectF m_rtNew;
 };
diff --git a/xfa/fwl/core/cfwl_evtvalidate.h b/xfa/fwl/core/cfwl_evtvalidate.h
index be9fd56..fae20b8 100644
--- a/xfa/fwl/core/cfwl_evtvalidate.h
+++ b/xfa/fwl/core/cfwl_evtvalidate.h
@@ -16,7 +16,7 @@
 
   CFWL_EventType GetClassID() const override;
 
-  IFWL_Widget* pDstWidget;
+  CFWL_Widget* pDstWidget;
   CFX_WideString wsInsert;
   bool bValidate;
 };
diff --git a/xfa/fwl/core/cfwl_form.cpp b/xfa/fwl/core/cfwl_form.cpp
index d2fe149..4eec163 100644
--- a/xfa/fwl/core/cfwl_form.cpp
+++ b/xfa/fwl/core/cfwl_form.cpp
@@ -40,8 +40,8 @@
 
 CFWL_Form::CFWL_Form(const CFWL_App* app,
                      std::unique_ptr<CFWL_WidgetProperties> properties,
-                     IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
+                     CFWL_Widget* pOuter)
+    : CFWL_Widget(app, std::move(properties), pOuter),
 #if (_FX_OS_ == _FX_MACOSX_)
       m_bMouseIn(false),
 #endif
@@ -77,7 +77,7 @@
 bool CFWL_Form::IsInstance(const CFX_WideStringC& wsClass) const {
   if (wsClass == CFX_WideStringC(FWL_CLASS_Form))
     return true;
-  return IFWL_Widget::IsInstance(wsClass);
+  return CFWL_Widget::IsInstance(wsClass);
 }
 
 void CFWL_Form::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
@@ -267,7 +267,7 @@
 #endif
 }
 
-IFWL_Widget* CFWL_Form::DoModal() {
+CFWL_Widget* CFWL_Form::DoModal() {
   const CFWL_App* pApp = GetOwnerApp();
   if (!pApp)
     return nullptr;
diff --git a/xfa/fwl/core/cfwl_form.h b/xfa/fwl/core/cfwl_form.h
index cb01c5b..db09c66 100644
--- a/xfa/fwl/core/cfwl_form.h
+++ b/xfa/fwl/core/cfwl_form.h
@@ -10,8 +10,8 @@
 #include <memory>
 
 #include "core/fxcrt/fx_system.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
 #define FWL_CLASS_Form L"FWL_FORM"
 #define FWL_CLASS_FormProxy L"FWL_FORMPROXY"
@@ -29,18 +29,18 @@
 
 class CFWL_MsgMouse;
 class CFWL_NoteLoop;
-class IFWL_Widget;
+class CFWL_Widget;
 class IFWL_ThemeProvider;
 class CFWL_SysBtn;
 
-class CFWL_Form : public IFWL_Widget {
+class CFWL_Form : public CFWL_Widget {
  public:
   CFWL_Form(const CFWL_App* app,
             std::unique_ptr<CFWL_WidgetProperties> properties,
-            IFWL_Widget* pOuter);
+            CFWL_Widget* pOuter);
   ~CFWL_Form() override;
 
-  // IFWL_Widget
+  // CFWL_Widget
   FWL_Type GetClassID() const override;
   bool IsInstance(const CFX_WideStringC& wsClass) const override;
   void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
@@ -53,11 +53,11 @@
   void OnDrawWidget(CFX_Graphics* pGraphics,
                     const CFX_Matrix* pMatrix) override;
 
-  IFWL_Widget* DoModal();
+  CFWL_Widget* DoModal();
   void EndDoModal();
 
-  IFWL_Widget* GetSubFocus() const { return m_pSubFocus; }
-  void SetSubFocus(IFWL_Widget* pWidget) { m_pSubFocus = pWidget; }
+  CFWL_Widget* GetSubFocus() const { return m_pSubFocus; }
+  void SetSubFocus(CFWL_Widget* pWidget) { m_pSubFocus = pWidget; }
 
  private:
   void DrawBackground(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme);
@@ -87,7 +87,7 @@
   CFWL_SysBtn* m_pMinBox;
   CFWL_SysBtn* m_pMaxBox;
   std::unique_ptr<CFWL_NoteLoop> m_pNoteLoop;
-  IFWL_Widget* m_pSubFocus;
+  CFWL_Widget* m_pSubFocus;
   FX_FLOAT m_fCXBorder;
   FX_FLOAT m_fCYBorder;
   int32_t m_iCaptureBtn;
diff --git a/xfa/fwl/core/cfwl_formproxy.cpp b/xfa/fwl/core/cfwl_formproxy.cpp
index ef325c4..c6d667f 100644
--- a/xfa/fwl/core/cfwl_formproxy.cpp
+++ b/xfa/fwl/core/cfwl_formproxy.cpp
@@ -15,7 +15,7 @@
 CFWL_FormProxy::CFWL_FormProxy(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
+    CFWL_Widget* pOuter)
     : CFWL_Form(app, std::move(properties), pOuter) {}
 
 CFWL_FormProxy::~CFWL_FormProxy() {}
diff --git a/xfa/fwl/core/cfwl_formproxy.h b/xfa/fwl/core/cfwl_formproxy.h
index 80e0980..db8323b 100644
--- a/xfa/fwl/core/cfwl_formproxy.h
+++ b/xfa/fwl/core/cfwl_formproxy.h
@@ -17,10 +17,10 @@
  public:
   CFWL_FormProxy(const CFWL_App* app,
                  std::unique_ptr<CFWL_WidgetProperties> properties,
-                 IFWL_Widget* pOuter);
+                 CFWL_Widget* pOuter);
   ~CFWL_FormProxy() override;
 
-  // IFWL_Widget
+  // CFWL_Widget
   FWL_Type GetClassID() const override;
   bool IsInstance(const CFX_WideStringC& wsClass) const override;
   void Update() override;
diff --git a/xfa/fwl/core/cfwl_listbox.cpp b/xfa/fwl/core/cfwl_listbox.cpp
index 784bf24..f234585 100644
--- a/xfa/fwl/core/cfwl_listbox.cpp
+++ b/xfa/fwl/core/cfwl_listbox.cpp
@@ -6,60 +6,1123 @@
 
 #include "xfa/fwl/core/cfwl_listbox.h"
 
+#include <algorithm>
 #include <memory>
 #include <utility>
 
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_msgmousewheel.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
+#include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
 
 namespace {
 
-IFWL_ListBox* ToListBox(IFWL_Widget* widget) {
-  return static_cast<IFWL_ListBox*>(widget);
-}
+const int kItemTextMargin = 2;
 
 }  // namespace
 
-CFWL_ListBox::CFWL_ListBox(const CFWL_App* app) : CFWL_Widget(app) {}
+CFWL_ListBox::CFWL_ListBox(const CFWL_App* app,
+                           std::unique_ptr<CFWL_WidgetProperties> properties,
+                           CFWL_Widget* pOuter)
+    : CFWL_Widget(app, std::move(properties), pOuter),
+      m_dwTTOStyles(0),
+      m_iTTOAligns(0),
+      m_hAnchor(nullptr),
+      m_fScorllBarWidth(0),
+      m_bLButtonDown(false),
+      m_pScrollBarTP(nullptr) {
+  m_rtClient.Reset();
+  m_rtConent.Reset();
+  m_rtStatic.Reset();
+}
 
 CFWL_ListBox::~CFWL_ListBox() {}
 
-void CFWL_ListBox::Initialize() {
-  ASSERT(!m_pIface);
-
-  m_pIface = pdfium::MakeUnique<IFWL_ListBox>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
-
-  CFWL_Widget::Initialize();
+FWL_Type CFWL_ListBox::GetClassID() const {
+  return FWL_Type::ListBox;
 }
 
-CFWL_ListItem* CFWL_ListBox::GetItem(const IFWL_Widget* pWidget,
-                                     int32_t nIndex) const {
-  return GetWidget() ? ToListBox(GetWidget())->GetItem(pWidget, nIndex)
-                     : nullptr;
+void CFWL_ListBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  rect.Set(0, 0, 0, 0);
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  CFX_SizeF fs = CalcSize(true);
+  rect.Set(0, 0, fs.x, fs.y);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
-void CFWL_ListBox::GetItemText(IFWL_Widget* pWidget,
+void CFWL_ListBox::Update() {
+  if (IsLocked())
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) {
+    case FWL_STYLEEXT_LTB_LeftAlign: {
+      m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft;
+      break;
+    }
+    case FWL_STYLEEXT_LTB_RightAlign: {
+      m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight;
+      break;
+    }
+    case FWL_STYLEEXT_LTB_CenterAlign:
+    default: {
+      m_iTTOAligns = FDE_TTOALIGNMENT_Center;
+      break;
+    }
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
+    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
+
+  m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;
+  m_fScorllBarWidth = GetScrollWidth();
+  CalcSize();
+}
+
+FWL_WidgetHit CFWL_ListBox::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
+  if (IsShowScrollBar(false)) {
+    CFX_RectF rect;
+    m_pHorzScrollBar->GetWidgetRect(rect);
+    if (rect.Contains(fx, fy))
+      return FWL_WidgetHit::HScrollBar;
+  }
+  if (IsShowScrollBar(true)) {
+    CFX_RectF rect;
+    m_pVertScrollBar->GetWidgetRect(rect);
+    if (rect.Contains(fx, fy))
+      return FWL_WidgetHit::VScrollBar;
+  }
+  if (m_rtClient.Contains(fx, fy))
+    return FWL_WidgetHit::Client;
+  return FWL_WidgetHit::Unknown;
+}
+
+void CFWL_ListBox::DrawWidget(CFX_Graphics* pGraphics,
+                              const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
+  pGraphics->SaveGraphState();
+  if (HasBorder())
+    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+
+  CFX_RectF rtClip(m_rtConent);
+  if (IsShowScrollBar(false))
+    rtClip.height -= m_fScorllBarWidth;
+  if (IsShowScrollBar(true))
+    rtClip.width -= m_fScorllBarWidth;
+  if (pMatrix)
+    pMatrix->TransformRect(rtClip);
+
+  pGraphics->SetClipRect(rtClip);
+  if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0)
+    DrawBkground(pGraphics, pTheme, pMatrix);
+
+  DrawItems(pGraphics, pTheme, pMatrix);
+  pGraphics->RestoreGraphState();
+}
+
+void CFWL_ListBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
+  if (pThemeProvider)
+    m_pProperties->m_pThemeProvider = pThemeProvider;
+}
+
+int32_t CFWL_ListBox::CountSelItems() {
+  int32_t iRet = 0;
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      continue;
+
+    uint32_t dwStyle = GetItemStyles(this, pItem);
+    if (dwStyle & FWL_ITEMSTATE_LTB_Selected)
+      iRet++;
+  }
+  return iRet;
+}
+
+CFWL_ListItem* CFWL_ListBox::GetSelItem(int32_t nIndexSel) {
+  int32_t idx = GetSelIndex(nIndexSel);
+  if (idx < 0)
+    return nullptr;
+  return GetItem(this, idx);
+}
+
+int32_t CFWL_ListBox::GetSelIndex(int32_t nIndex) {
+  int32_t index = 0;
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      return -1;
+
+    uint32_t dwStyle = GetItemStyles(this, pItem);
+    if (dwStyle & FWL_ITEMSTATE_LTB_Selected) {
+      if (index == nIndex)
+        return i;
+      index++;
+    }
+  }
+  return -1;
+}
+
+void CFWL_ListBox::SetSelItem(CFWL_ListItem* pItem, bool bSelect) {
+  if (!pItem) {
+    if (bSelect) {
+      SelectAll();
+    } else {
+      ClearSelection();
+      SetFocusItem(nullptr);
+    }
+    return;
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection)
+    SetSelectionDirect(pItem, bSelect);
+  else
+    SetSelection(pItem, pItem, bSelect);
+}
+
+void CFWL_ListBox::GetDataProviderItemText(CFWL_ListItem* pItem,
+                                           CFX_WideString& wsText) {
+  if (!pItem)
+    return;
+  GetItemText(this, pItem, wsText);
+}
+
+CFWL_ListItem* CFWL_ListBox::GetListItem(CFWL_ListItem* pItem,
+                                         uint32_t dwKeyCode) {
+  CFWL_ListItem* hRet = nullptr;
+  switch (dwKeyCode) {
+    case FWL_VKEY_Up:
+    case FWL_VKEY_Down:
+    case FWL_VKEY_Home:
+    case FWL_VKEY_End: {
+      const bool bUp = dwKeyCode == FWL_VKEY_Up;
+      const bool bDown = dwKeyCode == FWL_VKEY_Down;
+      const bool bHome = dwKeyCode == FWL_VKEY_Home;
+      int32_t iDstItem = -1;
+      if (bUp || bDown) {
+        int32_t index = GetItemIndex(this, pItem);
+        iDstItem = dwKeyCode == FWL_VKEY_Up ? index - 1 : index + 1;
+      } else if (bHome) {
+        iDstItem = 0;
+      } else {
+        int32_t iCount = CountItems(this);
+        iDstItem = iCount - 1;
+      }
+      hRet = GetItem(this, iDstItem);
+      break;
+    }
+    default:
+      break;
+  }
+  return hRet;
+}
+
+void CFWL_ListBox::SetSelection(CFWL_ListItem* hStart,
+                                CFWL_ListItem* hEnd,
+                                bool bSelected) {
+  int32_t iStart = GetItemIndex(this, hStart);
+  int32_t iEnd = GetItemIndex(this, hEnd);
+  if (iStart > iEnd) {
+    int32_t iTemp = iStart;
+    iStart = iEnd;
+    iEnd = iTemp;
+  }
+  if (bSelected) {
+    int32_t iCount = CountItems(this);
+    for (int32_t i = 0; i < iCount; i++) {
+      CFWL_ListItem* pItem = GetItem(this, i);
+      SetSelectionDirect(pItem, false);
+    }
+  }
+  for (; iStart <= iEnd; iStart++) {
+    CFWL_ListItem* pItem = GetItem(this, iStart);
+    SetSelectionDirect(pItem, bSelected);
+  }
+}
+
+void CFWL_ListBox::SetSelectionDirect(CFWL_ListItem* pItem, bool bSelect) {
+  uint32_t dwOldStyle = GetItemStyles(this, pItem);
+  bSelect ? dwOldStyle |= FWL_ITEMSTATE_LTB_Selected
+          : dwOldStyle &= ~FWL_ITEMSTATE_LTB_Selected;
+  SetItemStyles(this, pItem, dwOldStyle);
+}
+
+bool CFWL_ListBox::IsItemSelected(CFWL_ListItem* pItem) {
+  uint32_t dwState = GetItemStyles(this, pItem);
+  return (dwState & FWL_ITEMSTATE_LTB_Selected) != 0;
+}
+
+void CFWL_ListBox::ClearSelection() {
+  bool bMulti = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection;
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    uint32_t dwState = GetItemStyles(this, pItem);
+    if (!(dwState & FWL_ITEMSTATE_LTB_Selected))
+      continue;
+    SetSelectionDirect(pItem, false);
+    if (!bMulti)
+      return;
+  }
+}
+
+void CFWL_ListBox::SelectAll() {
+  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection))
+    return;
+
+  int32_t iCount = CountItems(this);
+  if (iCount <= 0)
+    return;
+
+  CFWL_ListItem* pItemStart = GetItem(this, 0);
+  CFWL_ListItem* pItemEnd = GetItem(this, iCount - 1);
+  SetSelection(pItemStart, pItemEnd, false);
+}
+
+CFWL_ListItem* CFWL_ListBox::GetFocusedItem() {
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      return nullptr;
+    if (GetItemStyles(this, pItem) & FWL_ITEMSTATE_LTB_Focused)
+      return pItem;
+  }
+  return nullptr;
+}
+
+void CFWL_ListBox::SetFocusItem(CFWL_ListItem* pItem) {
+  CFWL_ListItem* hFocus = GetFocusedItem();
+  if (pItem == hFocus)
+    return;
+
+  if (hFocus) {
+    uint32_t dwStyle = GetItemStyles(this, hFocus);
+    dwStyle &= ~FWL_ITEMSTATE_LTB_Focused;
+    SetItemStyles(this, hFocus, dwStyle);
+  }
+  if (pItem) {
+    uint32_t dwStyle = GetItemStyles(this, pItem);
+    dwStyle |= FWL_ITEMSTATE_LTB_Focused;
+    SetItemStyles(this, pItem, dwStyle);
+  }
+}
+
+CFWL_ListItem* CFWL_ListBox::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
+  fx -= m_rtConent.left, fy -= m_rtConent.top;
+  FX_FLOAT fPosX = 0.0f;
+  if (m_pHorzScrollBar)
+    fPosX = m_pHorzScrollBar->GetPos();
+
+  FX_FLOAT fPosY = 0.0;
+  if (m_pVertScrollBar)
+    fPosY = m_pVertScrollBar->GetPos();
+
+  int32_t nCount = CountItems(this);
+  for (int32_t i = 0; i < nCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      continue;
+
+    CFX_RectF rtItem;
+    GetItemRect(this, pItem, rtItem);
+    rtItem.Offset(-fPosX, -fPosY);
+    if (rtItem.Contains(fx, fy))
+      return pItem;
+  }
+  return nullptr;
+}
+
+bool CFWL_ListBox::GetItemCheckRectInternal(CFWL_ListItem* pItem,
+                                            CFX_RectF& rtCheck) {
+  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
+    return false;
+  GetItemCheckRect(this, pItem, rtCheck);
+  return true;
+}
+
+bool CFWL_ListBox::GetItemChecked(CFWL_ListItem* pItem) {
+  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
+    return false;
+  return !!(GetItemCheckState(this, pItem) & FWL_ITEMSTATE_LTB_Checked);
+}
+
+bool CFWL_ListBox::SetItemChecked(CFWL_ListItem* pItem, bool bChecked) {
+  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
+    return false;
+
+  SetItemCheckState(this, pItem, bChecked ? FWL_ITEMSTATE_LTB_Checked : 0);
+  return true;
+}
+
+bool CFWL_ListBox::ScrollToVisible(CFWL_ListItem* pItem) {
+  if (!m_pVertScrollBar)
+    return false;
+
+  CFX_RectF rtItem;
+  GetItemRect(this, pItem, rtItem);
+
+  bool bScroll = false;
+  FX_FLOAT fPosY = m_pVertScrollBar->GetPos();
+  rtItem.Offset(0, -fPosY + m_rtConent.top);
+  if (rtItem.top < m_rtConent.top) {
+    fPosY += rtItem.top - m_rtConent.top;
+    bScroll = true;
+  } else if (rtItem.bottom() > m_rtConent.bottom()) {
+    fPosY += rtItem.bottom() - m_rtConent.bottom();
+    bScroll = true;
+  }
+  if (!bScroll)
+    return false;
+
+  m_pVertScrollBar->SetPos(fPosY);
+  m_pVertScrollBar->SetTrackPos(fPosY);
+  Repaint(&m_rtClient);
+  return true;
+}
+
+void CFWL_ListBox::DrawBkground(CFX_Graphics* pGraphics,
+                                IFWL_ThemeProvider* pTheme,
+                                const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!pTheme)
+    return;
+
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = CFWL_Part::Background;
+  param.m_dwStates = 0;
+  param.m_pGraphics = pGraphics;
+  param.m_matrix.Concat(*pMatrix);
+  param.m_rtPart = m_rtClient;
+  if (IsShowScrollBar(false) && IsShowScrollBar(true))
+    param.m_pData = &m_rtStatic;
+  if (!IsEnabled())
+    param.m_dwStates = CFWL_PartState_Disabled;
+
+  pTheme->DrawBackground(&param);
+}
+
+void CFWL_ListBox::DrawItems(CFX_Graphics* pGraphics,
+                             IFWL_ThemeProvider* pTheme,
+                             const CFX_Matrix* pMatrix) {
+  FX_FLOAT fPosX = 0.0f;
+  if (m_pHorzScrollBar)
+    fPosX = m_pHorzScrollBar->GetPos();
+
+  FX_FLOAT fPosY = 0.0f;
+  if (m_pVertScrollBar)
+    fPosY = m_pVertScrollBar->GetPos();
+
+  CFX_RectF rtView(m_rtConent);
+  if (m_pHorzScrollBar)
+    rtView.height -= m_fScorllBarWidth;
+  if (m_pVertScrollBar)
+    rtView.width -= m_fScorllBarWidth;
+
+  bool bMultiCol =
+      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn);
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      continue;
+
+    CFX_RectF rtItem;
+    GetItemRect(this, pItem, rtItem);
+    rtItem.Offset(m_rtConent.left - fPosX, m_rtConent.top - fPosY);
+    if (rtItem.bottom() < m_rtConent.top)
+      continue;
+    if (rtItem.top >= m_rtConent.bottom())
+      break;
+    if (bMultiCol && rtItem.left > m_rtConent.right())
+      break;
+
+    if (!(GetStylesEx() & FWL_STYLEEXT_LTB_OwnerDraw))
+      DrawItem(pGraphics, pTheme, pItem, i, rtItem, pMatrix);
+  }
+}
+
+void CFWL_ListBox::DrawItem(CFX_Graphics* pGraphics,
+                            IFWL_ThemeProvider* pTheme,
+                            CFWL_ListItem* pItem,
+                            int32_t Index,
+                            const CFX_RectF& rtItem,
+                            const CFX_Matrix* pMatrix) {
+  uint32_t dwItemStyles = GetItemStyles(this, pItem);
+  uint32_t dwPartStates = CFWL_PartState_Normal;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    dwPartStates = CFWL_PartState_Disabled;
+  else if (dwItemStyles & FWL_ITEMSTATE_LTB_Selected)
+    dwPartStates = CFWL_PartState_Selected;
+
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused &&
+      dwItemStyles & FWL_ITEMSTATE_LTB_Focused) {
+    dwPartStates |= CFWL_PartState_Focused;
+  }
+
+  CFWL_ThemeBackground bg_param;
+  bg_param.m_pWidget = this;
+  bg_param.m_iPart = CFWL_Part::ListItem;
+  bg_param.m_dwStates = dwPartStates;
+  bg_param.m_pGraphics = pGraphics;
+  bg_param.m_matrix.Concat(*pMatrix);
+  bg_param.m_rtPart = rtItem;
+  bg_param.m_bMaximize = true;
+  CFX_RectF rtFocus(rtItem);
+  bg_param.m_pData = &rtFocus;
+  if (m_pVertScrollBar && !m_pHorzScrollBar &&
+      (dwPartStates & CFWL_PartState_Focused)) {
+    bg_param.m_rtPart.left += 1;
+    bg_param.m_rtPart.width -= (m_fScorllBarWidth + 1);
+    rtFocus.Deflate(0.5, 0.5, 1 + m_fScorllBarWidth, 1);
+  }
+  pTheme->DrawBackground(&bg_param);
+
+  bool bHasIcon = !!(GetStylesEx() & FWL_STYLEEXT_LTB_Icon);
+  if (bHasIcon) {
+    CFX_RectF rtDIB;
+    CFX_DIBitmap* pDib = GetItemIcon(this, pItem);
+    rtDIB.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
+    if (pDib) {
+      CFWL_ThemeBackground param;
+      param.m_pWidget = this;
+      param.m_iPart = CFWL_Part::Icon;
+      param.m_pGraphics = pGraphics;
+      param.m_matrix.Concat(*pMatrix);
+      param.m_rtPart = rtDIB;
+      param.m_bMaximize = true;
+      param.m_pImage = pDib;
+      pTheme->DrawBackground(&param);
+    }
+  }
+
+  bool bHasCheck = !!(GetStylesEx() & FWL_STYLEEXT_LTB_Check);
+  if (bHasCheck) {
+    CFX_RectF rtCheck;
+    rtCheck.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
+    rtCheck.Deflate(2, 2, 2, 2);
+    SetItemCheckRect(this, pItem, rtCheck);
+    CFWL_ThemeBackground param;
+    param.m_pWidget = this;
+    param.m_iPart = CFWL_Part::Check;
+    param.m_pGraphics = pGraphics;
+    if (GetItemChecked(pItem))
+      param.m_dwStates = CFWL_PartState_Checked;
+    else
+      param.m_dwStates = CFWL_PartState_Normal;
+    param.m_matrix.Concat(*pMatrix);
+    param.m_rtPart = rtCheck;
+    param.m_bMaximize = true;
+    pTheme->DrawBackground(&param);
+  }
+
+  CFX_WideString wsText;
+  GetItemText(this, pItem, wsText);
+  if (wsText.GetLength() <= 0)
+    return;
+
+  CFX_RectF rtText(rtItem);
+  rtText.Deflate(kItemTextMargin, kItemTextMargin);
+  if (bHasIcon || bHasCheck)
+    rtText.Deflate(rtItem.height, 0, 0, 0);
+
+  CFWL_ThemeText textParam;
+  textParam.m_pWidget = this;
+  textParam.m_iPart = CFWL_Part::ListItem;
+  textParam.m_dwStates = dwPartStates;
+  textParam.m_pGraphics = pGraphics;
+  textParam.m_matrix.Concat(*pMatrix);
+  textParam.m_rtPart = rtText;
+  textParam.m_wsText = wsText;
+  textParam.m_dwTTOStyles = m_dwTTOStyles;
+  textParam.m_iTTOAlign = m_iTTOAligns;
+  textParam.m_bMaximize = true;
+  pTheme->DrawText(&textParam);
+}
+
+CFX_SizeF CFWL_ListBox::CalcSize(bool bAutoSize) {
+  CFX_SizeF fs;
+  if (!m_pProperties->m_pThemeProvider)
+    return fs;
+
+  GetClientRect(m_rtClient);
+  m_rtConent = m_rtClient;
+  CFX_RectF rtUIMargin;
+  rtUIMargin.Set(0, 0, 0, 0);
+  if (!m_pOuter) {
+    CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
+        GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
+    if (pUIMargin) {
+      m_rtConent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
+                         pUIMargin->height);
+    }
+  }
+
+  FX_FLOAT fWidth = GetMaxTextWidth();
+  fWidth += 2 * kItemTextMargin;
+  if (!bAutoSize) {
+    FX_FLOAT fActualWidth =
+        m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
+    fWidth = std::max(fWidth, fActualWidth);
+  }
+
+  m_fItemHeight = CalcItemHeight();
+  if ((GetStylesEx() & FWL_STYLEEXT_LTB_Icon))
+    fWidth += m_fItemHeight;
+
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* htem = GetItem(this, i);
+    GetItemSize(fs, htem, fWidth, m_fItemHeight, bAutoSize);
+  }
+  if (bAutoSize)
+    return fs;
+
+  FX_FLOAT iWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
+  FX_FLOAT iHeight = m_rtClient.height;
+  bool bShowVertScr =
+      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
+      (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll);
+  bool bShowHorzScr =
+      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
+      (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll);
+  if (!bShowVertScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll &&
+      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) == 0) {
+    bShowVertScr = (fs.y > iHeight);
+  }
+  if (!bShowHorzScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll)
+    bShowHorzScr = (fs.x > iWidth);
+
+  CFX_SizeF szRange;
+  if (bShowVertScr) {
+    if (!m_pVertScrollBar)
+      InitScrollBar();
+
+    CFX_RectF rtScrollBar;
+    rtScrollBar.Set(m_rtClient.right() - m_fScorllBarWidth, m_rtClient.top,
+                    m_fScorllBarWidth, m_rtClient.height - 1);
+    if (bShowHorzScr)
+      rtScrollBar.height -= m_fScorllBarWidth;
+
+    m_pVertScrollBar->SetWidgetRect(rtScrollBar);
+    szRange.x = 0, szRange.y = fs.y - m_rtConent.height;
+    szRange.y = std::max(szRange.y, m_fItemHeight);
+
+    m_pVertScrollBar->SetRange(szRange.x, szRange.y);
+    m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10);
+    m_pVertScrollBar->SetStepSize(m_fItemHeight);
+
+    FX_FLOAT fPos =
+        std::min(std::max(m_pVertScrollBar->GetPos(), 0.f), szRange.y);
+    m_pVertScrollBar->SetPos(fPos);
+    m_pVertScrollBar->SetTrackPos(fPos);
+    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
+            0 ||
+        (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
+      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, false);
+    }
+    m_pVertScrollBar->Update();
+  } else if (m_pVertScrollBar) {
+    m_pVertScrollBar->SetPos(0);
+    m_pVertScrollBar->SetTrackPos(0);
+    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+  if (bShowHorzScr) {
+    if (!m_pHorzScrollBar)
+      InitScrollBar(false);
+
+    CFX_RectF rtScrollBar;
+    rtScrollBar.Set(m_rtClient.left, m_rtClient.bottom() - m_fScorllBarWidth,
+                    m_rtClient.width, m_fScorllBarWidth);
+    if (bShowVertScr)
+      rtScrollBar.width -= m_fScorllBarWidth;
+
+    m_pHorzScrollBar->SetWidgetRect(rtScrollBar);
+    szRange.x = 0, szRange.y = fs.x - rtScrollBar.width;
+    m_pHorzScrollBar->SetRange(szRange.x, szRange.y);
+    m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10);
+    m_pHorzScrollBar->SetStepSize(fWidth / 10);
+
+    FX_FLOAT fPos =
+        std::min(std::max(m_pHorzScrollBar->GetPos(), 0.f), szRange.y);
+    m_pHorzScrollBar->SetPos(fPos);
+    m_pHorzScrollBar->SetTrackPos(fPos);
+    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
+            0 ||
+        (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
+      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, false);
+    }
+    m_pHorzScrollBar->Update();
+  } else if (m_pHorzScrollBar) {
+    m_pHorzScrollBar->SetPos(0);
+    m_pHorzScrollBar->SetTrackPos(0);
+    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
+  }
+  if (bShowVertScr && bShowHorzScr) {
+    m_rtStatic.Set(m_rtClient.right() - m_fScorllBarWidth,
+                   m_rtClient.bottom() - m_fScorllBarWidth, m_fScorllBarWidth,
+                   m_fScorllBarWidth);
+  }
+  return fs;
+}
+
+void CFWL_ListBox::GetItemSize(CFX_SizeF& size,
+                               CFWL_ListItem* pItem,
+                               FX_FLOAT fWidth,
+                               FX_FLOAT fItemHeight,
+                               bool bAutoSize) {
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn)
+    return;
+
+  if (!bAutoSize) {
+    CFX_RectF rtItem;
+    rtItem.Set(0, size.y, fWidth, fItemHeight);
+    SetItemRect(this, pItem, rtItem);
+  }
+  size.x = fWidth;
+  size.y += fItemHeight;
+}
+
+FX_FLOAT CFWL_ListBox::GetMaxTextWidth() {
+  FX_FLOAT fRet = 0.0f;
+  int32_t iCount = CountItems(this);
+  for (int32_t i = 0; i < iCount; i++) {
+    CFWL_ListItem* pItem = GetItem(this, i);
+    if (!pItem)
+      continue;
+
+    CFX_WideString wsText;
+    GetItemText(this, pItem, wsText);
+    CFX_SizeF sz = CalcTextSize(wsText, m_pProperties->m_pThemeProvider);
+    fRet = std::max(fRet, sz.x);
+  }
+  return fRet;
+}
+
+FX_FLOAT CFWL_ListBox::GetScrollWidth() {
+  FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
+      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
+  if (!pfWidth)
+    return 0;
+  return *pfWidth;
+}
+
+FX_FLOAT CFWL_ListBox::CalcItemHeight() {
+  FX_FLOAT* pfFont =
+      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
+  if (!pfFont)
+    return 20;
+  return *pfFont + 2 * kItemTextMargin;
+}
+
+void CFWL_ListBox::InitScrollBar(bool bVert) {
+  if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar))
+    return;
+
+  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
+  prop->m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
+  prop->m_dwStates = FWL_WGTSTATE_Invisible;
+  prop->m_pParent = this;
+  prop->m_pThemeProvider = m_pScrollBarTP;
+  CFWL_ScrollBar* sb = new CFWL_ScrollBar(m_pOwnerApp, std::move(prop), this);
+  if (bVert)
+    m_pVertScrollBar.reset(sb);
+  else
+    m_pHorzScrollBar.reset(sb);
+}
+
+bool CFWL_ListBox::IsShowScrollBar(bool bVert) {
+  CFWL_ScrollBar* pScrollbar =
+      bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get();
+  if (!pScrollbar || (pScrollbar->GetStates() & FWL_WGTSTATE_Invisible))
+    return false;
+  return !(m_pProperties->m_dwStyleExes &
+           FWL_STYLEEXT_LTB_ShowScrollBarFocus) ||
+         (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
+}
+
+void CFWL_ListBox::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+  if (!IsEnabled())
+    return;
+
+  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
+  switch (dwMsgCode) {
+    case CFWL_MessageType::SetFocus:
+      OnFocusChanged(pMessage, true);
+      break;
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(pMessage, false);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::MouseWheel:
+      OnMouseWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage));
+      break;
+    case CFWL_MessageType::Key: {
+      CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage);
+      if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown)
+        OnKeyDown(pMsg);
+      break;
+    }
+    default:
+      break;
+  }
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_ListBox::OnProcessEvent(CFWL_Event* pEvent) {
+  if (!pEvent)
+    return;
+  if (pEvent->GetClassID() != CFWL_EventType::Scroll)
+    return;
+
+  CFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
+  if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
+      (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
+    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
+    OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
+             pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
+  }
+}
+
+void CFWL_ListBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_ListBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  if (GetStylesEx() & FWL_STYLEEXT_LTB_ShowScrollBarFocus) {
+    if (m_pVertScrollBar)
+      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
+    if (m_pHorzScrollBar)
+      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
+  }
+  if (bSet)
+    m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
+  else
+    m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
+
+  Repaint(&m_rtClient);
+}
+
+void CFWL_ListBox::OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  m_bLButtonDown = true;
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    SetFocus(true);
+
+  CFWL_ListItem* pItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
+  if (!pItem)
+    return;
+
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) {
+    if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) {
+      bool bSelected = IsItemSelected(pItem);
+      SetSelectionDirect(pItem, !bSelected);
+      m_hAnchor = pItem;
+    } else if (pMsg->m_dwFlags & FWL_KEYFLAG_Shift) {
+      if (m_hAnchor)
+        SetSelection(m_hAnchor, pItem, true);
+      else
+        SetSelectionDirect(pItem, true);
+    } else {
+      SetSelection(pItem, pItem, true);
+      m_hAnchor = pItem;
+    }
+  } else {
+    SetSelection(pItem, pItem, true);
+  }
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check) {
+    CFWL_ListItem* hSelectedItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
+    CFX_RectF rtCheck;
+    GetItemCheckRectInternal(hSelectedItem, rtCheck);
+    bool bChecked = GetItemChecked(pItem);
+    if (rtCheck.Contains(pMsg->m_fx, pMsg->m_fy)) {
+      SetItemChecked(pItem, !bChecked);
+      Update();
+    }
+  }
+  SetFocusItem(pItem);
+  ScrollToVisible(pItem);
+  SetGrab(true);
+  Repaint(&m_rtClient);
+}
+
+void CFWL_ListBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  if (!m_bLButtonDown)
+    return;
+
+  m_bLButtonDown = false;
+  SetGrab(false);
+}
+
+void CFWL_ListBox::OnMouseWheel(CFWL_MsgMouseWheel* pMsg) {
+  if (IsShowScrollBar(true))
+    m_pVertScrollBar->GetDelegate()->OnProcessMessage(pMsg);
+}
+
+void CFWL_ListBox::OnKeyDown(CFWL_MsgKey* pMsg) {
+  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
+  switch (dwKeyCode) {
+    case FWL_VKEY_Tab:
+    case FWL_VKEY_Up:
+    case FWL_VKEY_Down:
+    case FWL_VKEY_Home:
+    case FWL_VKEY_End: {
+      CFWL_ListItem* pItem = GetFocusedItem();
+      pItem = GetListItem(pItem, dwKeyCode);
+      bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
+      bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);
+      OnVK(pItem, bShift, bCtrl);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void CFWL_ListBox::OnVK(CFWL_ListItem* pItem, bool bShift, bool bCtrl) {
+  if (!pItem)
+    return;
+
+  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) {
+    if (bCtrl) {
+      // Do nothing.
+    } else if (bShift) {
+      if (m_hAnchor)
+        SetSelection(m_hAnchor, pItem, true);
+      else
+        SetSelectionDirect(pItem, true);
+    } else {
+      SetSelection(pItem, pItem, true);
+      m_hAnchor = pItem;
+    }
+  } else {
+    SetSelection(pItem, pItem, true);
+  }
+
+  SetFocusItem(pItem);
+  ScrollToVisible(pItem);
+
+  CFX_RectF rtInvalidate;
+  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
+                   m_pProperties->m_rtWidget.height);
+  Repaint(&rtInvalidate);
+}
+
+bool CFWL_ListBox::OnScroll(CFWL_ScrollBar* pScrollBar,
+                            FWL_SCBCODE dwCode,
+                            FX_FLOAT fPos) {
+  CFX_SizeF fs;
+  pScrollBar->GetRange(&fs.x, &fs.y);
+  FX_FLOAT iCurPos = pScrollBar->GetPos();
+  FX_FLOAT fStep = pScrollBar->GetStepSize();
+  switch (dwCode) {
+    case FWL_SCBCODE::Min: {
+      fPos = fs.x;
+      break;
+    }
+    case FWL_SCBCODE::Max: {
+      fPos = fs.y;
+      break;
+    }
+    case FWL_SCBCODE::StepBackward: {
+      fPos -= fStep;
+      if (fPos < fs.x + fStep / 2)
+        fPos = fs.x;
+      break;
+    }
+    case FWL_SCBCODE::StepForward: {
+      fPos += fStep;
+      if (fPos > fs.y - fStep / 2)
+        fPos = fs.y;
+      break;
+    }
+    case FWL_SCBCODE::PageBackward: {
+      fPos -= pScrollBar->GetPageSize();
+      if (fPos < fs.x)
+        fPos = fs.x;
+      break;
+    }
+    case FWL_SCBCODE::PageForward: {
+      fPos += pScrollBar->GetPageSize();
+      if (fPos > fs.y)
+        fPos = fs.y;
+      break;
+    }
+    case FWL_SCBCODE::Pos:
+    case FWL_SCBCODE::TrackPos:
+    case FWL_SCBCODE::None:
+      break;
+    case FWL_SCBCODE::EndScroll:
+      return false;
+  }
+  if (iCurPos != fPos) {
+    pScrollBar->SetPos(fPos);
+    pScrollBar->SetTrackPos(fPos);
+    Repaint(&m_rtClient);
+  }
+  return true;
+}
+
+void CFWL_ListBox::GetItemText(CFWL_Widget* pWidget,
                                CFWL_ListItem* pItem,
                                CFX_WideString& wsText) {
-  if (GetWidget())
-    ToListBox(GetWidget())->GetItemText(pWidget, pItem, wsText);
+  if (pItem)
+    wsText = static_cast<CFWL_ListItem*>(pItem)->m_wsText;
+}
+
+int32_t CFWL_ListBox::CountItems(const CFWL_Widget* pWidget) const {
+  return pdfium::CollectionSize<int32_t>(m_ItemArray);
+}
+
+CFWL_ListItem* CFWL_ListBox::GetItem(const CFWL_Widget* pWidget,
+                                     int32_t nIndex) const {
+  if (nIndex < 0 || nIndex >= CountItems(pWidget))
+    return nullptr;
+  return m_ItemArray[nIndex].get();
+}
+
+int32_t CFWL_ListBox::GetItemIndex(CFWL_Widget* pWidget, CFWL_ListItem* pItem) {
+  auto it = std::find_if(
+      m_ItemArray.begin(), m_ItemArray.end(),
+      [pItem](const std::unique_ptr<CFWL_ListItem>& candidate) {
+        return candidate.get() == static_cast<CFWL_ListItem*>(pItem);
+      });
+  return it != m_ItemArray.end() ? it - m_ItemArray.begin() : -1;
+}
+
+uint32_t CFWL_ListBox::GetItemStyles(CFWL_Widget* pWidget,
+                                     CFWL_ListItem* pItem) {
+  return pItem ? static_cast<CFWL_ListItem*>(pItem)->m_dwStates : 0;
+}
+
+void CFWL_ListBox::GetItemRect(CFWL_Widget* pWidget,
+                               CFWL_ListItem* pItem,
+                               CFX_RectF& rtItem) {
+  if (pItem)
+    rtItem = static_cast<CFWL_ListItem*>(pItem)->m_rtItem;
+}
+
+void* CFWL_ListBox::GetItemData(CFWL_Widget* pWidget, CFWL_ListItem* pItem) {
+  return pItem ? static_cast<CFWL_ListItem*>(pItem)->m_pData : nullptr;
+}
+
+void CFWL_ListBox::SetItemStyles(CFWL_Widget* pWidget,
+                                 CFWL_ListItem* pItem,
+                                 uint32_t dwStyle) {
+  if (pItem)
+    static_cast<CFWL_ListItem*>(pItem)->m_dwStates = dwStyle;
+}
+
+void CFWL_ListBox::SetItemRect(CFWL_Widget* pWidget,
+                               CFWL_ListItem* pItem,
+                               const CFX_RectF& rtItem) {
+  if (pItem)
+    static_cast<CFWL_ListItem*>(pItem)->m_rtItem = rtItem;
+}
+
+CFX_DIBitmap* CFWL_ListBox::GetItemIcon(CFWL_Widget* pWidget,
+                                        CFWL_ListItem* pItem) {
+  return static_cast<CFWL_ListItem*>(pItem)->m_pDIB;
+}
+
+void CFWL_ListBox::GetItemCheckRect(CFWL_Widget* pWidget,
+                                    CFWL_ListItem* pItem,
+                                    CFX_RectF& rtCheck) {
+  rtCheck = static_cast<CFWL_ListItem*>(pItem)->m_rtCheckBox;
+}
+
+void CFWL_ListBox::SetItemCheckRect(CFWL_Widget* pWidget,
+                                    CFWL_ListItem* pItem,
+                                    const CFX_RectF& rtCheck) {
+  static_cast<CFWL_ListItem*>(pItem)->m_rtCheckBox = rtCheck;
+}
+
+uint32_t CFWL_ListBox::GetItemCheckState(CFWL_Widget* pWidget,
+                                         CFWL_ListItem* pItem) {
+  return static_cast<CFWL_ListItem*>(pItem)->m_dwCheckState;
+}
+
+void CFWL_ListBox::SetItemCheckState(CFWL_Widget* pWidget,
+                                     CFWL_ListItem* pItem,
+                                     uint32_t dwCheckState) {
+  static_cast<CFWL_ListItem*>(pItem)->m_dwCheckState = dwCheckState;
 }
 
 CFWL_ListItem* CFWL_ListBox::AddString(const CFX_WideStringC& wsAdd,
                                        bool bSelect) {
-  return GetWidget() ? ToListBox(GetWidget())->AddString(wsAdd, bSelect)
-                     : nullptr;
+  auto pItem = pdfium::MakeUnique<CFWL_ListItem>();
+  pItem->m_dwStates = 0;
+  pItem->m_wsText = wsAdd;
+  pItem->m_dwStates = bSelect ? FWL_ITEMSTATE_LTB_Selected : 0;
+  m_ItemArray.push_back(std::move(pItem));
+  return m_ItemArray.back().get();
+}
+
+bool CFWL_ListBox::RemoveAt(int32_t iIndex) {
+  if (iIndex < 0 || static_cast<size_t>(iIndex) >= m_ItemArray.size())
+    return false;
+
+  m_ItemArray.erase(m_ItemArray.begin() + iIndex);
+  return true;
 }
 
 bool CFWL_ListBox::DeleteString(CFWL_ListItem* pItem) {
-  return GetWidget() && ToListBox(GetWidget())->DeleteString(pItem);
+  int32_t nIndex = GetItemIndex(this, pItem);
+  if (nIndex < 0 || static_cast<size_t>(nIndex) >= m_ItemArray.size())
+    return false;
+
+  int32_t iSel = nIndex + 1;
+  if (iSel >= CountItems(this))
+    iSel = nIndex - 1;
+  if (iSel >= 0) {
+    CFWL_ListItem* pSel = static_cast<CFWL_ListItem*>(GetItem(this, iSel));
+    pSel->m_dwStates |= FWL_ITEMSTATE_LTB_Selected;
+  }
+  m_ItemArray.erase(m_ItemArray.begin() + nIndex);
+  return true;
 }
 
 void CFWL_ListBox::DeleteAll() {
-  if (GetWidget())
-    ToListBox(GetWidget())->DeleteAll();
+  m_ItemArray.clear();
 }
 
 uint32_t CFWL_ListBox::GetItemStates(CFWL_ListItem* pItem) {
@@ -68,19 +1131,3 @@
   return pItem->m_dwStates | pItem->m_dwCheckState;
 }
 
-int32_t CFWL_ListBox::CountSelItems() {
-  return GetWidget() ? ToListBox(GetWidget())->CountSelItems() : 0;
-}
-
-CFWL_ListItem* CFWL_ListBox::GetSelItem(int32_t nIndexSel) {
-  return GetWidget() ? ToListBox(GetWidget())->GetSelItem(nIndexSel) : nullptr;
-}
-
-int32_t CFWL_ListBox::GetSelIndex(int32_t nIndex) {
-  return GetWidget() ? ToListBox(GetWidget())->GetSelIndex(nIndex) : 0;
-}
-
-void CFWL_ListBox::SetSelItem(CFWL_ListItem* pItem, bool bSelect) {
-  if (GetWidget())
-    ToListBox(GetWidget())->SetSelItem(pItem, bSelect);
-}
diff --git a/xfa/fwl/core/cfwl_listbox.h b/xfa/fwl/core/cfwl_listbox.h
index 36d13bd..a758e19 100644
--- a/xfa/fwl/core/cfwl_listbox.h
+++ b/xfa/fwl/core/cfwl_listbox.h
@@ -10,31 +10,160 @@
 #include <memory>
 #include <vector>
 
+#include "xfa/fwl/core/cfwl_edit.h"
+#include "xfa/fwl/core/cfwl_event.h"
+#include "xfa/fwl/core/cfwl_listbox.h"
 #include "xfa/fwl/core/cfwl_listitem.h"
 #include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/fwl_error.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
+
+#define FWL_STYLEEXT_LTB_MultiSelection (1L << 0)
+#define FWL_STYLEEXT_LTB_ShowScrollBarAlaways (1L << 2)
+#define FWL_STYLEEXT_LTB_MultiColumn (1L << 3)
+#define FWL_STYLEEXT_LTB_LeftAlign (0L << 4)
+#define FWL_STYLEEXT_LTB_CenterAlign (1L << 4)
+#define FWL_STYLEEXT_LTB_RightAlign (2L << 4)
+#define FWL_STYLEEXT_LTB_MultiLine (1L << 6)
+#define FWL_STYLEEXT_LTB_OwnerDraw (1L << 7)
+#define FWL_STYLEEXT_LTB_Icon (1L << 8)
+#define FWL_STYLEEXT_LTB_Check (1L << 9)
+#define FWL_STYLEEXT_LTB_AlignMask (3L << 4)
+#define FWL_STYLEEXT_LTB_ShowScrollBarFocus (1L << 10)
+#define FWL_ITEMSTATE_LTB_Selected (1L << 0)
+#define FWL_ITEMSTATE_LTB_Focused (1L << 1)
+#define FWL_ITEMSTATE_LTB_Checked (1L << 2)
+
+class CFWL_MsgKillFocus;
+class CFWL_MsgMouse;
+class CFWL_MsgMouseWheel;
+class CFX_DIBitmap;
 
 class CFWL_ListBox : public CFWL_Widget {
  public:
-  explicit CFWL_ListBox(const CFWL_App* pApp);
+  explicit CFWL_ListBox(const CFWL_App* pApp,
+                        std::unique_ptr<CFWL_WidgetProperties> properties,
+                        CFWL_Widget* pOuter);
   ~CFWL_ListBox() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void Update() override;
+  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnProcessEvent(CFWL_Event* pEvent) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
 
-  CFWL_ListItem* GetItem(const IFWL_Widget* pWidget, int32_t nIndex) const;
-  void GetItemText(IFWL_Widget* pWidget,
+  int32_t CountItems(const CFWL_Widget* pWidget) const;
+  CFWL_ListItem* GetItem(const CFWL_Widget* pWidget, int32_t nIndex) const;
+  int32_t GetItemIndex(CFWL_Widget* pWidget, CFWL_ListItem* pItem);
+  uint32_t GetItemStyles(CFWL_Widget* pWidget, CFWL_ListItem* pItem);
+  uint32_t GetItemStates(CFWL_ListItem* pItem);
+  void GetItemText(CFWL_Widget* pWidget,
                    CFWL_ListItem* pItem,
                    CFX_WideString& wsText);
-
+  void GetItemRect(CFWL_Widget* pWidget,
+                   CFWL_ListItem* pItem,
+                   CFX_RectF& rtItem);
+  void* GetItemData(CFWL_Widget* pWidget, CFWL_ListItem* pItem);
+  void SetItemStyles(CFWL_Widget* pWidget,
+                     CFWL_ListItem* pItem,
+                     uint32_t dwStyle);
+  void SetItemRect(CFWL_Widget* pWidget,
+                   CFWL_ListItem* pItem,
+                   const CFX_RectF& rtItem);
+  CFX_DIBitmap* GetItemIcon(CFWL_Widget* pWidget, CFWL_ListItem* pItem);
+  void GetItemCheckRect(CFWL_Widget* pWidget,
+                        CFWL_ListItem* pItem,
+                        CFX_RectF& rtCheck);
+  void SetItemCheckRect(CFWL_Widget* pWidget,
+                        CFWL_ListItem* pItem,
+                        const CFX_RectF& rtCheck);
+  uint32_t GetItemCheckState(CFWL_Widget* pWidget, CFWL_ListItem* pItem);
+  void SetItemCheckState(CFWL_Widget* pWidget,
+                         CFWL_ListItem* pItem,
+                         uint32_t dwCheckState);
   CFWL_ListItem* AddString(const CFX_WideStringC& wsAdd, bool bSelect = false);
+  bool RemoveAt(int32_t iIndex);
   bool DeleteString(CFWL_ListItem* pItem);
   void DeleteAll();
+
   int32_t CountSelItems();
-  void SetSelItem(CFWL_ListItem* pItem, bool bSelect = true);
   CFWL_ListItem* GetSelItem(int32_t nIndexSel);
   int32_t GetSelIndex(int32_t nIndex);
+  void SetSelItem(CFWL_ListItem* hItem, bool bSelect = true);
+  void GetDataProviderItemText(CFWL_ListItem* hItem, CFX_WideString& wsText);
 
-  uint32_t GetItemStates(CFWL_ListItem* pItem);
+  FX_FLOAT GetItemHeight() const { return m_fItemHeight; }
+  FX_FLOAT CalcItemHeight();
+
+ protected:
+  CFWL_ListItem* GetListItem(CFWL_ListItem* hItem, uint32_t dwKeyCode);
+  void SetSelection(CFWL_ListItem* hStart, CFWL_ListItem* hEnd, bool bSelected);
+  CFWL_ListItem* GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy);
+  bool ScrollToVisible(CFWL_ListItem* hItem);
+  void InitScrollBar(bool bVert = true);
+  bool IsShowScrollBar(bool bVert);
+  CFWL_ScrollBar* GetVertScrollBar() const { return m_pVertScrollBar.get(); }
+  const CFX_RectF& GetRTClient() const { return m_rtClient; }
+
+ private:
+  void SetSelectionDirect(CFWL_ListItem* hItem, bool bSelect);
+  bool IsItemSelected(CFWL_ListItem* hItem);
+  void ClearSelection();
+  void SelectAll();
+  CFWL_ListItem* GetFocusedItem();
+  void SetFocusItem(CFWL_ListItem* hItem);
+  bool GetItemCheckRectInternal(CFWL_ListItem* hItem, CFX_RectF& rtCheck);
+  bool SetItemChecked(CFWL_ListItem* hItem, bool bChecked);
+  bool GetItemChecked(CFWL_ListItem* hItem);
+  void DrawBkground(CFX_Graphics* pGraphics,
+                    IFWL_ThemeProvider* pTheme,
+                    const CFX_Matrix* pMatrix = nullptr);
+  void DrawItems(CFX_Graphics* pGraphics,
+                 IFWL_ThemeProvider* pTheme,
+                 const CFX_Matrix* pMatrix = nullptr);
+  void DrawItem(CFX_Graphics* pGraphics,
+                IFWL_ThemeProvider* pTheme,
+                CFWL_ListItem* hItem,
+                int32_t Index,
+                const CFX_RectF& rtItem,
+                const CFX_Matrix* pMatrix = nullptr);
+  void DrawStatic(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme);
+  CFX_SizeF CalcSize(bool bAutoSize = false);
+  void GetItemSize(CFX_SizeF& size,
+                   CFWL_ListItem* hItem,
+                   FX_FLOAT fWidth,
+                   FX_FLOAT fHeight,
+                   bool bAutoSize = false);
+  FX_FLOAT GetMaxTextWidth();
+  FX_FLOAT GetScrollWidth();
+
+  void OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
+  void OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnMouseWheel(CFWL_MsgMouseWheel* pMsg);
+  void OnKeyDown(CFWL_MsgKey* pMsg);
+  void OnVK(CFWL_ListItem* hItem, bool bShift, bool bCtrl);
+  bool OnScroll(CFWL_ScrollBar* pScrollBar, FWL_SCBCODE dwCode, FX_FLOAT fPos);
+
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtStatic;
+  CFX_RectF m_rtConent;
+  std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar;
+  std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar;
+  uint32_t m_dwTTOStyles;
+  int32_t m_iTTOAligns;
+  CFWL_ListItem* m_hAnchor;
+  FX_FLOAT m_fItemHeight;
+  FX_FLOAT m_fScorllBarWidth;
+  bool m_bLButtonDown;
+  IFWL_ThemeProvider* m_pScrollBarTP;
+  std::vector<std::unique_ptr<CFWL_ListItem>> m_ItemArray;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_LISTBOX_H_
diff --git a/xfa/fwl/core/cfwl_message.h b/xfa/fwl/core/cfwl_message.h
index 1ad43a6..827b418 100644
--- a/xfa/fwl/core/cfwl_message.h
+++ b/xfa/fwl/core/cfwl_message.h
@@ -23,7 +23,7 @@
   SetFocus
 };
 
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_Message {
  public:
@@ -33,8 +33,8 @@
   virtual std::unique_ptr<CFWL_Message> Clone();
   virtual CFWL_MessageType GetClassID() const;
 
-  IFWL_Widget* m_pSrcTarget;
-  IFWL_Widget* m_pDstTarget;
+  CFWL_Widget* m_pSrcTarget;
+  CFWL_Widget* m_pDstTarget;
   uint32_t m_dwExtend;
 };
 
diff --git a/xfa/fwl/core/cfwl_monthcalendar.cpp b/xfa/fwl/core/cfwl_monthcalendar.cpp
index 4f7cff0..9d22b13 100644
--- a/xfa/fwl/core/cfwl_monthcalendar.cpp
+++ b/xfa/fwl/core/cfwl_monthcalendar.cpp
@@ -12,12 +12,12 @@
 
 #include "third_party/base/ptr_util.h"
 #include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_datetimepicker.h"
 #include "xfa/fwl/core/cfwl_formproxy.h"
 #include "xfa/fwl/core/cfwl_msgmouse.h"
 #include "xfa/fwl/core/cfwl_notedriver.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
 
 #define MONTHCAL_HSEP_HEIGHT 1
@@ -124,8 +124,8 @@
 CFWL_MonthCalendar::CFWL_MonthCalendar(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
+    CFWL_Widget* pOuter)
+    : CFWL_Widget(app, std::move(properties), pOuter),
       m_bInitialized(false),
       m_pDateTime(new CFX_DateTime),
       m_iCurYear(2011),
@@ -168,7 +168,7 @@
 
   CFX_SizeF fs = CalcSize(true);
   rect.Set(0, 0, fs.x, fs.y);
-  IFWL_Widget::GetWidgetRect(rect, true);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
 void CFWL_MonthCalendar::Update() {
@@ -943,7 +943,7 @@
     default:
       break;
   }
-  IFWL_Widget::OnProcessMessage(pMessage);
+  CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_MonthCalendar::OnDrawWidget(CFX_Graphics* pGraphics,
@@ -966,7 +966,7 @@
       Repaint(&m_rtClient);
     }
   } else {
-    IFWL_DateTimePicker* pIPicker = static_cast<IFWL_DateTimePicker*>(m_pOuter);
+    CFWL_DateTimePicker* pIPicker = static_cast<CFWL_DateTimePicker*>(m_pOuter);
     if (pIPicker->IsMonthCalendarVisible())
       m_bFlag = 1;
   }
@@ -995,7 +995,7 @@
 
   int32_t iCurSel = GetDayAtPoint(pMsg->m_fx, pMsg->m_fy);
   CFX_RectF rt;
-  IFWL_DateTimePicker* pIPicker = static_cast<IFWL_DateTimePicker*>(m_pOuter);
+  CFWL_DateTimePicker* pIPicker = static_cast<CFWL_DateTimePicker*>(m_pOuter);
   pIPicker->GetFormProxy()->GetWidgetRect(rt);
   rt.Set(0, 0, rt.width, rt.height);
   if (iCurSel > 0) {
@@ -1044,8 +1044,8 @@
       rtInvalidate.Union(lpDatesInfo->rect);
     }
     AddSelDay(iCurSel);
-    IFWL_DateTimePicker* pDateTime =
-        static_cast<IFWL_DateTimePicker*>(m_pOuter);
+    CFWL_DateTimePicker* pDateTime =
+        static_cast<CFWL_DateTimePicker*>(m_pOuter);
     pDateTime->ProcessSelChanged(m_iCurYear, m_iCurMonth, iCurSel);
     pDateTime->ShowMonthCalendar(false);
   }
diff --git a/xfa/fwl/core/cfwl_monthcalendar.h b/xfa/fwl/core/cfwl_monthcalendar.h
index 1acdf5c..6c004aa 100644
--- a/xfa/fwl/core/cfwl_monthcalendar.h
+++ b/xfa/fwl/core/cfwl_monthcalendar.h
@@ -11,8 +11,8 @@
 
 #include "xfa/fgas/localization/fgas_datetime.h"
 #include "xfa/fwl/core/cfwl_event.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
 #define FWL_STYLEEXT_MCD_MultiSelect (1L << 0)
 #define FWL_STYLEEXT_MCD_NoToday (1L << 1)
@@ -24,13 +24,13 @@
 #define FWL_ITEMSTATE_MCD_Focused (1L << 2)
 
 class CFWL_MsgMouse;
-class IFWL_Widget;
+class CFWL_Widget;
 
-class CFWL_MonthCalendar : public IFWL_Widget {
+class CFWL_MonthCalendar : public CFWL_Widget {
  public:
   CFWL_MonthCalendar(const CFWL_App* app,
                      std::unique_ptr<CFWL_WidgetProperties> properties,
-                     IFWL_Widget* pOuter);
+                     CFWL_Widget* pOuter);
   ~CFWL_MonthCalendar() override;
 
   // FWL_WidgetImp
diff --git a/xfa/fwl/core/cfwl_msgkillfocus.h b/xfa/fwl/core/cfwl_msgkillfocus.h
index 71c52d9..ef68752 100644
--- a/xfa/fwl/core/cfwl_msgkillfocus.h
+++ b/xfa/fwl/core/cfwl_msgkillfocus.h
@@ -20,7 +20,7 @@
   std::unique_ptr<CFWL_Message> Clone() override;
   CFWL_MessageType GetClassID() const override;
 
-  IFWL_Widget* m_pSetFocus;
+  CFWL_Widget* m_pSetFocus;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_MSGKILLFOCUS_H_
diff --git a/xfa/fwl/core/cfwl_msgsetfocus.h b/xfa/fwl/core/cfwl_msgsetfocus.h
index 47eab2a..42f14ed 100644
--- a/xfa/fwl/core/cfwl_msgsetfocus.h
+++ b/xfa/fwl/core/cfwl_msgsetfocus.h
@@ -20,7 +20,7 @@
   std::unique_ptr<CFWL_Message> Clone() override;
   CFWL_MessageType GetClassID() const override;
 
-  IFWL_Widget* m_pKillFocus;
+  CFWL_Widget* m_pKillFocus;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_MSGSETFOCUS_H_
diff --git a/xfa/fwl/core/cfwl_notedriver.cpp b/xfa/fwl/core/cfwl_notedriver.cpp
index c12882a..06d8fd5 100644
--- a/xfa/fwl/core/cfwl_notedriver.cpp
+++ b/xfa/fwl/core/cfwl_notedriver.cpp
@@ -45,8 +45,8 @@
   }
 }
 
-void CFWL_NoteDriver::RegisterEventTarget(IFWL_Widget* pListener,
-                                          IFWL_Widget* pEventSource) {
+void CFWL_NoteDriver::RegisterEventTarget(CFWL_Widget* pListener,
+                                          CFWL_Widget* pEventSource) {
   uint32_t key = pListener->GetEventKey();
   if (key == 0) {
     do {
@@ -60,7 +60,7 @@
   m_eventTargets[key]->SetEventSource(pEventSource);
 }
 
-void CFWL_NoteDriver::UnregisterEventTarget(IFWL_Widget* pListener) {
+void CFWL_NoteDriver::UnregisterEventTarget(CFWL_Widget* pListener) {
   uint32_t key = pListener->GetEventKey();
   if (key == 0)
     return;
@@ -84,11 +84,11 @@
   return p;
 }
 
-bool CFWL_NoteDriver::SetFocus(IFWL_Widget* pFocus, bool bNotify) {
+bool CFWL_NoteDriver::SetFocus(CFWL_Widget* pFocus, bool bNotify) {
   if (m_pFocus == pFocus)
     return true;
 
-  IFWL_Widget* pPrev = m_pFocus;
+  CFWL_Widget* pPrev = m_pFocus;
   m_pFocus = pFocus;
   if (pPrev) {
     CFWL_MsgKillFocus ms;
@@ -101,7 +101,7 @@
       pDelegate->OnProcessMessage(&ms);
   }
   if (pFocus) {
-    IFWL_Widget* pWidget =
+    CFWL_Widget* pWidget =
         pFocus->GetOwnerApp()->GetWidgetMgr()->GetSystemFormWidget(pFocus);
     CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
     if (pForm)
@@ -129,7 +129,7 @@
 #endif
 }
 
-void CFWL_NoteDriver::NotifyTargetHide(IFWL_Widget* pNoteTarget) {
+void CFWL_NoteDriver::NotifyTargetHide(CFWL_Widget* pNoteTarget) {
   if (m_pFocus == pNoteTarget)
     m_pFocus = nullptr;
   if (m_pHover == pNoteTarget)
@@ -138,7 +138,7 @@
     m_pGrab = nullptr;
 }
 
-void CFWL_NoteDriver::NotifyTargetDestroy(IFWL_Widget* pNoteTarget) {
+void CFWL_NoteDriver::NotifyTargetDestroy(CFWL_Widget* pNoteTarget) {
   if (m_pFocus == pNoteTarget)
     m_pFocus = nullptr;
   if (m_pHover == pNoteTarget)
@@ -153,7 +153,7 @@
     if (!pForm)
       continue;
 
-    IFWL_Widget* pSubFocus = pForm->GetSubFocus();
+    CFWL_Widget* pSubFocus = pForm->GetSubFocus();
     if (!pSubFocus)
       return;
     if (pSubFocus == pNoteTarget)
@@ -161,7 +161,7 @@
   }
 }
 
-void CFWL_NoteDriver::RegisterForm(IFWL_Widget* pForm) {
+void CFWL_NoteDriver::RegisterForm(CFWL_Widget* pForm) {
   if (!pForm || m_forms.Find(pForm) >= 0)
     return;
 
@@ -176,7 +176,7 @@
   pLoop->SetMainForm(pForm);
 }
 
-void CFWL_NoteDriver::UnRegisterForm(IFWL_Widget* pForm) {
+void CFWL_NoteDriver::UnRegisterForm(CFWL_Widget* pForm) {
   if (!pForm)
     return;
 
@@ -214,7 +214,7 @@
 void CFWL_NoteDriver::ProcessMessage(CFWL_Message* pMessage) {
   CFWL_WidgetMgr* pWidgetMgr =
       pMessage->m_pDstTarget->GetOwnerApp()->GetWidgetMgr();
-  IFWL_Widget* pMessageForm = pWidgetMgr->IsFormDisabled()
+  CFWL_Widget* pMessageForm = pWidgetMgr->IsFormDisabled()
                                   ? pMessage->m_pDstTarget
                                   : GetMessageForm(pMessage->m_pDstTarget);
   if (!pMessageForm)
@@ -227,7 +227,7 @@
 }
 
 bool CFWL_NoteDriver::DispatchMessage(CFWL_Message* pMessage,
-                                      IFWL_Widget* pMessageForm) {
+                                      CFWL_Widget* pMessageForm) {
   switch (pMessage->GetClassID()) {
     case CFWL_MessageType::SetFocus: {
       if (!DoSetFocus(pMessage, pMessageForm))
@@ -264,19 +264,19 @@
 }
 
 bool CFWL_NoteDriver::DoSetFocus(CFWL_Message* pMessage,
-                                 IFWL_Widget* pMessageForm) {
+                                 CFWL_Widget* pMessageForm) {
   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
   if (pWidgetMgr->IsFormDisabled()) {
     m_pFocus = pMessage->m_pDstTarget;
     return true;
   }
 
-  IFWL_Widget* pWidget = pMessage->m_pDstTarget;
+  CFWL_Widget* pWidget = pMessage->m_pDstTarget;
   if (!pWidget)
     return false;
 
   CFWL_Form* pForm = static_cast<CFWL_Form*>(pWidget);
-  IFWL_Widget* pSubFocus = pForm->GetSubFocus();
+  CFWL_Widget* pSubFocus = pForm->GetSubFocus();
   if (pSubFocus && ((pSubFocus->GetStates() & FWL_WGTSTATE_Focused) == 0)) {
     pMessage->m_pDstTarget = pSubFocus;
     if (m_pFocus != pMessage->m_pDstTarget) {
@@ -288,7 +288,7 @@
 }
 
 bool CFWL_NoteDriver::DoKillFocus(CFWL_Message* pMessage,
-                                  IFWL_Widget* pMessageForm) {
+                                  CFWL_Widget* pMessageForm) {
   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
   if (pWidgetMgr->IsFormDisabled()) {
     if (m_pFocus == pMessage->m_pDstTarget)
@@ -300,7 +300,7 @@
   if (!pForm)
     return false;
 
-  IFWL_Widget* pSubFocus = pForm->GetSubFocus();
+  CFWL_Widget* pSubFocus = pForm->GetSubFocus();
   if (pSubFocus && (pSubFocus->GetStates() & FWL_WGTSTATE_Focused)) {
     pMessage->m_pDstTarget = pSubFocus;
     if (m_pFocus == pMessage->m_pDstTarget) {
@@ -311,19 +311,19 @@
   return false;
 }
 
-bool CFWL_NoteDriver::DoKey(CFWL_Message* pMessage, IFWL_Widget* pMessageForm) {
+bool CFWL_NoteDriver::DoKey(CFWL_Message* pMessage, CFWL_Widget* pMessageForm) {
   CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage);
 #if (_FX_OS_ != _FX_MACOSX_)
   if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
       pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
     CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
-    IFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
-    IFWL_Widget* pFocus = m_pFocus;
+    CFWL_Widget* pForm = GetMessageForm(pMsg->m_pDstTarget);
+    CFWL_Widget* pFocus = m_pFocus;
     if (m_pFocus && pWidgetMgr->GetSystemFormWidget(m_pFocus) != pForm)
       pFocus = nullptr;
 
     bool bFind = false;
-    IFWL_Widget* pNextTabStop = pWidgetMgr->NextTab(pForm, pFocus, bFind);
+    CFWL_Widget* pNextTabStop = pWidgetMgr->NextTab(pForm, pFocus, bFind);
     if (!pNextTabStop) {
       bFind = false;
       pNextTabStop = pWidgetMgr->NextTab(pForm, nullptr, bFind);
@@ -340,7 +340,7 @@
     if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown &&
         pMsg->m_dwKeyCode == FWL_VKEY_Return) {
       CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
-      IFWL_Widget* defButton = pWidgetMgr->GetDefaultButton(pMessageForm);
+      CFWL_Widget* defButton = pWidgetMgr->GetDefaultButton(pMessageForm);
       if (defButton) {
         pMsg->m_pDstTarget = defButton;
         return true;
@@ -353,7 +353,7 @@
 }
 
 bool CFWL_NoteDriver::DoMouse(CFWL_Message* pMessage,
-                              IFWL_Widget* pMessageForm) {
+                              CFWL_Widget* pMessageForm) {
   CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
   if (pMsg->m_dwCmd == FWL_MouseCommand::Leave ||
       pMsg->m_dwCmd == FWL_MouseCommand::Hover ||
@@ -368,13 +368,13 @@
 }
 
 bool CFWL_NoteDriver::DoWheel(CFWL_Message* pMessage,
-                              IFWL_Widget* pMessageForm) {
+                              CFWL_Widget* pMessageForm) {
   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
   if (!pWidgetMgr)
     return false;
 
   CFWL_MsgMouseWheel* pMsg = static_cast<CFWL_MsgMouseWheel*>(pMessage);
-  IFWL_Widget* pDst =
+  CFWL_Widget* pDst =
       pWidgetMgr->GetWidgetAtPoint(pMessageForm, pMsg->m_fx, pMsg->m_fy);
   if (!pDst)
     return false;
@@ -385,11 +385,11 @@
 }
 
 bool CFWL_NoteDriver::DoMouseEx(CFWL_Message* pMessage,
-                                IFWL_Widget* pMessageForm) {
+                                CFWL_Widget* pMessageForm) {
   CFWL_WidgetMgr* pWidgetMgr = pMessageForm->GetOwnerApp()->GetWidgetMgr();
   if (!pWidgetMgr)
     return false;
-  IFWL_Widget* pTarget = nullptr;
+  CFWL_Widget* pTarget = nullptr;
   if (m_pGrab)
     pTarget = m_pGrab;
 
@@ -410,7 +410,7 @@
 }
 
 void CFWL_NoteDriver::MouseSecondary(CFWL_Message* pMessage) {
-  IFWL_Widget* pTarget = pMessage->m_pDstTarget;
+  CFWL_Widget* pTarget = pMessage->m_pDstTarget;
   if (pTarget == m_pHover)
     return;
 
@@ -444,7 +444,7 @@
 bool CFWL_NoteDriver::IsValidMessage(CFWL_Message* pMessage) {
   for (int32_t i = 0; i < m_noteLoopQueue.GetSize(); i++) {
     CFWL_NoteLoop* pNoteLoop = m_noteLoopQueue[i];
-    IFWL_Widget* pForm = pNoteLoop->GetForm();
+    CFWL_Widget* pForm = pNoteLoop->GetForm();
     if (pForm && (pForm == pMessage->m_pDstTarget))
       return true;
   }
@@ -457,12 +457,12 @@
   return false;
 }
 
-IFWL_Widget* CFWL_NoteDriver::GetMessageForm(IFWL_Widget* pDstTarget) {
+CFWL_Widget* CFWL_NoteDriver::GetMessageForm(CFWL_Widget* pDstTarget) {
   int32_t iTrackLoop = m_noteLoopQueue.GetSize();
   if (iTrackLoop <= 0)
     return nullptr;
 
-  IFWL_Widget* pMessageForm = nullptr;
+  CFWL_Widget* pMessageForm = nullptr;
   if (iTrackLoop > 1)
     pMessageForm = m_noteLoopQueue[iTrackLoop - 1]->GetForm();
   else if (m_forms.Find(pDstTarget) < 0)
diff --git a/xfa/fwl/core/cfwl_notedriver.h b/xfa/fwl/core/cfwl_notedriver.h
index ee9b384..9fdb342 100644
--- a/xfa/fwl/core/cfwl_notedriver.h
+++ b/xfa/fwl/core/cfwl_notedriver.h
@@ -12,13 +12,13 @@
 #include <unordered_map>
 
 #include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxgraphics/cfx_graphics.h"
 
 class CFWL_EventTarget;
 class CFWL_NoteLoop;
 class CFWL_TargetImp;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_NoteDriver {
  public:
@@ -27,51 +27,51 @@
 
   void SendEvent(CFWL_Event* pNote);
 
-  void RegisterEventTarget(IFWL_Widget* pListener, IFWL_Widget* pEventSource);
-  void UnregisterEventTarget(IFWL_Widget* pListener);
+  void RegisterEventTarget(CFWL_Widget* pListener, CFWL_Widget* pEventSource);
+  void UnregisterEventTarget(CFWL_Widget* pListener);
   void ClearEventTargets(bool bRemoveAll);
 
   CFWL_NoteLoop* GetTopLoop() const;
   void PushNoteLoop(CFWL_NoteLoop* pNoteLoop);
   CFWL_NoteLoop* PopNoteLoop();
 
-  IFWL_Widget* GetFocus() const { return m_pFocus; }
-  bool SetFocus(IFWL_Widget* pFocus, bool bNotify = false);
-  void SetGrab(IFWL_Widget* pGrab, bool bSet) {
+  CFWL_Widget* GetFocus() const { return m_pFocus; }
+  bool SetFocus(CFWL_Widget* pFocus, bool bNotify = false);
+  void SetGrab(CFWL_Widget* pGrab, bool bSet) {
     m_pGrab = bSet ? pGrab : nullptr;
   }
 
   void Run();
 
-  void NotifyTargetHide(IFWL_Widget* pNoteTarget);
-  void NotifyTargetDestroy(IFWL_Widget* pNoteTarget);
+  void NotifyTargetHide(CFWL_Widget* pNoteTarget);
+  void NotifyTargetDestroy(CFWL_Widget* pNoteTarget);
 
-  void RegisterForm(IFWL_Widget* pForm);
-  void UnRegisterForm(IFWL_Widget* pForm);
+  void RegisterForm(CFWL_Widget* pForm);
+  void UnRegisterForm(CFWL_Widget* pForm);
 
   void QueueMessage(std::unique_ptr<CFWL_Message> pMessage);
   void UnqueueMessage(CFWL_NoteLoop* pNoteLoop);
   void ProcessMessage(CFWL_Message* pMessage);
 
  private:
-  bool DispatchMessage(CFWL_Message* pMessage, IFWL_Widget* pMessageForm);
-  bool DoSetFocus(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
-  bool DoKillFocus(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
-  bool DoKey(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
-  bool DoMouse(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
-  bool DoWheel(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
-  bool DoMouseEx(CFWL_Message* pMsg, IFWL_Widget* pMessageForm);
+  bool DispatchMessage(CFWL_Message* pMessage, CFWL_Widget* pMessageForm);
+  bool DoSetFocus(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
+  bool DoKillFocus(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
+  bool DoKey(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
+  bool DoMouse(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
+  bool DoWheel(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
+  bool DoMouseEx(CFWL_Message* pMsg, CFWL_Widget* pMessageForm);
   void MouseSecondary(CFWL_Message* pMsg);
   bool IsValidMessage(CFWL_Message* pMessage);
-  IFWL_Widget* GetMessageForm(IFWL_Widget* pDstTarget);
+  CFWL_Widget* GetMessageForm(CFWL_Widget* pDstTarget);
 
-  CFX_ArrayTemplate<IFWL_Widget*> m_forms;
+  CFX_ArrayTemplate<CFWL_Widget*> m_forms;
   std::deque<std::unique_ptr<CFWL_Message>> m_noteQueue;
   CFX_ArrayTemplate<CFWL_NoteLoop*> m_noteLoopQueue;
   std::unordered_map<uint32_t, CFWL_EventTarget*> m_eventTargets;
-  IFWL_Widget* m_pHover;
-  IFWL_Widget* m_pFocus;
-  IFWL_Widget* m_pGrab;
+  CFWL_Widget* m_pHover;
+  CFWL_Widget* m_pFocus;
+  CFWL_Widget* m_pGrab;
   std::unique_ptr<CFWL_NoteLoop> m_pNoteLoop;
 };
 
diff --git a/xfa/fwl/core/cfwl_noteloop.h b/xfa/fwl/core/cfwl_noteloop.h
index f07bdc5..20bc03f 100644
--- a/xfa/fwl/core/cfwl_noteloop.h
+++ b/xfa/fwl/core/cfwl_noteloop.h
@@ -7,20 +7,20 @@
 #ifndef XFA_FWL_CORE_CFWL_NOTELOOP_H_
 #define XFA_FWL_CORE_CFWL_NOTELOOP_H_
 
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_NoteLoop {
  public:
   CFWL_NoteLoop();
   ~CFWL_NoteLoop() {}
 
-  IFWL_Widget* GetForm() const { return m_pForm; }
+  CFWL_Widget* GetForm() const { return m_pForm; }
   bool ContinueModal() const { return m_bContinueModal; }
   void EndModalLoop() { m_bContinueModal = false; }
-  void SetMainForm(IFWL_Widget* pForm) { m_pForm = pForm; }
+  void SetMainForm(CFWL_Widget* pForm) { m_pForm = pForm; }
 
  private:
-  IFWL_Widget* m_pForm;
+  CFWL_Widget* m_pForm;
   bool m_bContinueModal;
 };
 
diff --git a/xfa/fwl/core/cfwl_picturebox.cpp b/xfa/fwl/core/cfwl_picturebox.cpp
index af0cb86..cb4cff3 100644
--- a/xfa/fwl/core/cfwl_picturebox.cpp
+++ b/xfa/fwl/core/cfwl_picturebox.cpp
@@ -10,16 +10,54 @@
 
 #include "third_party/base/ptr_util.h"
 
-CFWL_PictureBox::CFWL_PictureBox(const CFWL_App* app) : CFWL_Widget(app) {}
+CFWL_PictureBox::CFWL_PictureBox(const CFWL_App* app)
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr) {
+  m_rtClient.Reset();
+  m_rtImage.Reset();
+  m_matrix.SetIdentity();
+}
 
 CFWL_PictureBox::~CFWL_PictureBox() {}
 
-void CFWL_PictureBox::Initialize() {
-  ASSERT(!m_pIface);
-
-  m_pIface = pdfium::MakeUnique<IFWL_PictureBox>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
-
-  CFWL_Widget::Initialize();
+FWL_Type CFWL_PictureBox::GetClassID() const {
+  return FWL_Type::PictureBox;
 }
 
+void CFWL_PictureBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  rect.Set(0, 0, 0, 0);
+
+  CFWL_Widget::GetWidgetRect(rect, true);
+}
+
+void CFWL_PictureBox::Update() {
+  if (IsLocked())
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  GetClientRect(m_rtClient);
+}
+
+void CFWL_PictureBox::DrawWidget(CFX_Graphics* pGraphics,
+                                 const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
+  if (HasBorder())
+    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
+  if (HasEdge())
+    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
+}
+
+void CFWL_PictureBox::OnDrawWidget(CFX_Graphics* pGraphics,
+                                   const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
diff --git a/xfa/fwl/core/cfwl_picturebox.h b/xfa/fwl/core/cfwl_picturebox.h
index a7b3f1f..f409733 100644
--- a/xfa/fwl/core/cfwl_picturebox.h
+++ b/xfa/fwl/core/cfwl_picturebox.h
@@ -7,15 +7,47 @@
 #ifndef XFA_FWL_CORE_CFWL_PICTUREBOX_H_
 #define XFA_FWL_CORE_CFWL_PICTUREBOX_H_
 
+#include <memory>
+
 #include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_picturebox.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
+
+#define FWL_STYLEEXT_PTB_Left 0L << 0
+#define FWL_STYLEEXT_PTB_Center 1L << 0
+#define FWL_STYLEEXT_PTB_Right 2L << 0
+#define FWL_STYLEEXT_PTB_Top 0L << 2
+#define FWL_STYLEEXT_PTB_Vcenter 1L << 2
+#define FWL_STYLEEXT_PTB_Bottom 2L << 2
+#define FWL_STYLEEXT_PTB_Normal 0L << 4
+#define FWL_STYLEEXT_PTB_AutoSize 1L << 4
+#define FWL_STYLEEXT_PTB_StretchImage 2L << 4
+#define FWL_STYLEEXT_PTB_StretchHImage 3L << 4
+#define FWL_STYLEEXT_PTB_StretchVImage 4L << 4
+#define FWL_STYLEEXT_PTB_HAlignMask 3L << 0
+#define FWL_STYLEEXT_PTB_VAlignMask 3L << 2
+#define FWL_STYLEEXT_PTB_StretchAlignMask 7L << 4
+
+class CFX_DIBitmap;
+class CFWL_Widget;
 
 class CFWL_PictureBox : public CFWL_Widget {
  public:
   explicit CFWL_PictureBox(const CFWL_App* pApp);
   ~CFWL_PictureBox() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void Update() override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
+
+ private:
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtImage;
+  CFX_Matrix m_matrix;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_PICTUREBOX_H_
diff --git a/xfa/fwl/core/cfwl_pushbutton.cpp b/xfa/fwl/core/cfwl_pushbutton.cpp
index 5fddff0..15e98fc 100644
--- a/xfa/fwl/core/cfwl_pushbutton.cpp
+++ b/xfa/fwl/core/cfwl_pushbutton.cpp
@@ -7,19 +7,308 @@
 #include "xfa/fwl/core/cfwl_pushbutton.h"
 
 #include <memory>
+#include <utility>
 
 #include "third_party/base/ptr_util.h"
+#include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_evtclick.h"
+#include "xfa/fwl/core/cfwl_evtmouse.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/ifwl_themeprovider.h"
 
-CFWL_PushButton::CFWL_PushButton(const CFWL_App* app) : CFWL_Widget(app) {}
+CFWL_PushButton::CFWL_PushButton(const CFWL_App* app)
+    : CFWL_Widget(app, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr),
+      m_bBtnDown(false),
+      m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
+      m_iTTOAlign(FDE_TTOALIGNMENT_Center) {
+  m_rtClient.Set(0, 0, 0, 0);
+  m_rtCaption.Set(0, 0, 0, 0);
+}
 
 CFWL_PushButton::~CFWL_PushButton() {}
 
-void CFWL_PushButton::Initialize() {
-  ASSERT(!m_pIface);
-
-  m_pIface = pdfium::MakeUnique<IFWL_PushButton>(
-      m_pApp, pdfium::MakeUnique<CFWL_WidgetProperties>());
-
-  CFWL_Widget::Initialize();
+FWL_Type CFWL_PushButton::GetClassID() const {
+  return FWL_Type::PushButton;
 }
 
+void CFWL_PushButton::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  rect.Set(0, 0, 0, 0);
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  FX_FLOAT* fcaption =
+      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::Margin));
+  rect.Inflate(*fcaption, *fcaption);
+  CFWL_Widget::GetWidgetRect(rect, true);
+}
+
+void CFWL_PushButton::SetStates(uint32_t dwStates, bool bSet) {
+  if ((dwStates & FWL_WGTSTATE_Disabled) && bSet) {
+    m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled;
+    return;
+  }
+  CFWL_Widget::SetStates(dwStates, bSet);
+}
+
+void CFWL_PushButton::Update() {
+  if (IsLocked())
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    m_pProperties->m_pThemeProvider = GetAvailableTheme();
+
+  UpdateTextOutStyles();
+  GetClientRect(m_rtClient);
+  m_rtCaption = m_rtClient;
+  FX_FLOAT* fcaption =
+      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::Margin));
+  m_rtCaption.Inflate(-*fcaption, -*fcaption);
+}
+
+void CFWL_PushButton::DrawWidget(CFX_Graphics* pGraphics,
+                                 const CFX_Matrix* pMatrix) {
+  if (!pGraphics)
+    return;
+  if (!m_pProperties->m_pThemeProvider)
+    return;
+
+  if (HasBorder()) {
+    DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
+               pMatrix);
+  }
+  if (HasEdge()) {
+    DrawEdge(pGraphics, CFWL_Part::Edge, m_pProperties->m_pThemeProvider,
+             pMatrix);
+  }
+  DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix);
+}
+
+void CFWL_PushButton::DrawBkground(CFX_Graphics* pGraphics,
+                                   IFWL_ThemeProvider* pTheme,
+                                   const CFX_Matrix* pMatrix) {
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = CFWL_Part::Background;
+  param.m_dwStates = GetPartStates();
+  param.m_pGraphics = pGraphics;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix);
+  param.m_rtPart = m_rtClient;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+    param.m_pData = &m_rtCaption;
+  pTheme->DrawBackground(&param);
+}
+
+uint32_t CFWL_PushButton::GetPartStates() {
+  uint32_t dwStates = CFWL_PartState_Normal;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
+    dwStates |= CFWL_PartState_Focused;
+  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
+    dwStates = CFWL_PartState_Disabled;
+  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed)
+    dwStates |= CFWL_PartState_Pressed;
+  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered)
+    dwStates |= CFWL_PartState_Hovered;
+  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Default)
+    dwStates |= CFWL_PartState_Default;
+  return dwStates;
+}
+
+void CFWL_PushButton::UpdateTextOutStyles() {
+  switch (m_pProperties->m_dwStyleExes &
+          (FWL_STYLEEXT_PSB_HLayoutMask | FWL_STYLEEXT_PSB_VLayoutMask)) {
+    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Top: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_VCenter: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_VCenter: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Bottom: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;
+      break;
+    }
+    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_VCenter:
+    default: {
+      m_iTTOAlign = FDE_TTOALIGNMENT_Center;
+      break;
+    }
+  }
+  m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
+  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
+    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
+}
+
+void CFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage)
+    return;
+  if (!IsEnabled())
+    return;
+
+  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
+  switch (dwMsgCode) {
+    case CFWL_MessageType::SetFocus:
+      OnFocusChanged(pMessage, true);
+      break;
+    case CFWL_MessageType::KillFocus:
+      OnFocusChanged(pMessage, false);
+      break;
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
+      switch (pMsg->m_dwCmd) {
+        case FWL_MouseCommand::LeftButtonDown:
+          OnLButtonDown(pMsg);
+          break;
+        case FWL_MouseCommand::LeftButtonUp:
+          OnLButtonUp(pMsg);
+          break;
+        case FWL_MouseCommand::Move:
+          OnMouseMove(pMsg);
+          break;
+        case FWL_MouseCommand::Leave:
+          OnMouseLeave(pMsg);
+          break;
+        default:
+          break;
+      }
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
+      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
+        OnKeyDown(pKey);
+      break;
+    }
+    default:
+      break;
+  }
+  CFWL_Widget::OnProcessMessage(pMessage);
+}
+
+void CFWL_PushButton::OnDrawWidget(CFX_Graphics* pGraphics,
+                                   const CFX_Matrix* pMatrix) {
+  DrawWidget(pGraphics, pMatrix);
+}
+
+void CFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
+  if (bSet)
+    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
+  else
+    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
+
+  Repaint(&m_rtClient);
+}
+
+void CFWL_PushButton::OnLButtonDown(CFWL_MsgMouse* pMsg) {
+  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+    SetFocus(true);
+
+  m_bBtnDown = true;
+  m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
+  m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
+  Repaint(&m_rtClient);
+}
+
+void CFWL_PushButton::OnLButtonUp(CFWL_MsgMouse* pMsg) {
+  m_bBtnDown = false;
+  if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
+    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
+    m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
+  } else {
+    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
+    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
+  }
+  if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
+    CFWL_EvtClick wmClick;
+    wmClick.m_pSrcTarget = this;
+    DispatchEvent(&wmClick);
+  }
+  Repaint(&m_rtClient);
+}
+
+void CFWL_PushButton::OnMouseMove(CFWL_MsgMouse* pMsg) {
+  bool bRepaint = false;
+  if (m_bBtnDown) {
+    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
+      if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
+        m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
+        bRepaint = true;
+      }
+      if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
+        m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
+        bRepaint = true;
+      }
+    } else {
+      if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
+        m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
+        bRepaint = true;
+      }
+      if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
+        m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
+        bRepaint = true;
+      }
+    }
+  } else {
+    if (!m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy))
+      return;
+    if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
+      m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
+      bRepaint = true;
+    }
+  }
+  if (bRepaint)
+    Repaint(&m_rtClient);
+}
+
+void CFWL_PushButton::OnMouseLeave(CFWL_MsgMouse* pMsg) {
+  m_bBtnDown = false;
+  m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
+  m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
+  Repaint(&m_rtClient);
+}
+
+void CFWL_PushButton::OnKeyDown(CFWL_MsgKey* pMsg) {
+  if (pMsg->m_dwKeyCode == FWL_VKEY_Return) {
+    CFWL_EvtMouse wmMouse;
+    wmMouse.m_pSrcTarget = this;
+    wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
+    DispatchEvent(&wmMouse);
+    CFWL_EvtClick wmClick;
+    wmClick.m_pSrcTarget = this;
+    DispatchEvent(&wmClick);
+    return;
+  }
+  if (pMsg->m_dwKeyCode != FWL_VKEY_Tab)
+    return;
+
+  DispatchKeyEvent(pMsg);
+}
diff --git a/xfa/fwl/core/cfwl_pushbutton.h b/xfa/fwl/core/cfwl_pushbutton.h
index 66fa406..3bfae6c 100644
--- a/xfa/fwl/core/cfwl_pushbutton.h
+++ b/xfa/fwl/core/cfwl_pushbutton.h
@@ -7,15 +7,65 @@
 #ifndef XFA_FWL_CORE_CFWL_PUSHBUTTON_H_
 #define XFA_FWL_CORE_CFWL_PUSHBUTTON_H_
 
+#include <memory>
+
 #include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_pushbutton.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
+
+#define FWL_STYLEEXT_PSB_Left (0L << 0)
+#define FWL_STYLEEXT_PSB_Center (1L << 0)
+#define FWL_STYLEEXT_PSB_Right (2L << 0)
+#define FWL_STYLEEXT_PSB_Top (0L << 2)
+#define FWL_STYLEEXT_PSB_VCenter (1L << 2)
+#define FWL_STYLEEXT_PSB_Bottom (2L << 2)
+#define FWL_STYLEEXT_PSB_TextOnly (0L << 4)
+#define FWL_STYLEEXT_PSB_IconOnly (1L << 4)
+#define FWL_STYLEEXT_PSB_TextIcon (2L << 4)
+#define FWL_STYLEEXT_PSB_HLayoutMask (3L << 0)
+#define FWL_STYLEEXT_PSB_VLayoutMask (3L << 2)
+#define FWL_STYLEEXT_PSB_ModeMask (3L << 4)
+#define FWL_STATE_PSB_Hovered (1 << FWL_WGTSTATE_MAX)
+#define FWL_STATE_PSB_Pressed (1 << (FWL_WGTSTATE_MAX + 1))
+#define FWL_STATE_PSB_Default (1 << (FWL_WGTSTATE_MAX + 2))
+
+class CFWL_MsgMouse;
+class CFX_DIBitmap;
+class CFWL_Widget;
 
 class CFWL_PushButton : public CFWL_Widget {
  public:
   explicit CFWL_PushButton(const CFWL_App*);
   ~CFWL_PushButton() override;
 
-  void Initialize();
+  // CFWL_Widget
+  FWL_Type GetClassID() const override;
+  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
+  void SetStates(uint32_t dwStates, bool bSet = true) override;
+  void Update() override;
+  void DrawWidget(CFX_Graphics* pGraphics,
+                  const CFX_Matrix* pMatrix = nullptr) override;
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix) override;
+
+ private:
+  void DrawBkground(CFX_Graphics* pGraphics,
+                    IFWL_ThemeProvider* pTheme,
+                    const CFX_Matrix* pMatrix);
+  uint32_t GetPartStates();
+  void UpdateTextOutStyles();
+  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
+  void OnLButtonDown(CFWL_MsgMouse* pMsg);
+  void OnLButtonUp(CFWL_MsgMouse* pMsg);
+  void OnMouseMove(CFWL_MsgMouse* pMsg);
+  void OnMouseLeave(CFWL_MsgMouse* pMsg);
+  void OnKeyDown(CFWL_MsgKey* pMsg);
+
+  CFX_RectF m_rtClient;
+  CFX_RectF m_rtCaption;
+  bool m_bBtnDown;
+  uint32_t m_dwTTOStyles;
+  int32_t m_iTTOAlign;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_PUSHBUTTON_H_
diff --git a/xfa/fwl/core/cfwl_scrollbar.cpp b/xfa/fwl/core/cfwl_scrollbar.cpp
index 85ab271..6647350 100644
--- a/xfa/fwl/core/cfwl_scrollbar.cpp
+++ b/xfa/fwl/core/cfwl_scrollbar.cpp
@@ -25,8 +25,8 @@
 CFWL_ScrollBar::CFWL_ScrollBar(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties,
-    IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
+    CFWL_Widget* pOuter)
+    : CFWL_Widget(app, std::move(properties), pOuter),
       m_pTimerInfo(nullptr),
       m_fRangeMin(0),
       m_fRangeMax(-1),
@@ -77,7 +77,7 @@
     rect.Set(0, 0, (*pfMinWidth), (*pfMinWidth) * 3);
   else
     rect.Set(0, 0, (*pfMinWidth) * 3, (*pfMinWidth));
-  IFWL_Widget::GetWidgetRect(rect, true);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
 void CFWL_ScrollBar::Update() {
diff --git a/xfa/fwl/core/cfwl_scrollbar.h b/xfa/fwl/core/cfwl_scrollbar.h
index 69f362d..800df51 100644
--- a/xfa/fwl/core/cfwl_scrollbar.h
+++ b/xfa/fwl/core/cfwl_scrollbar.h
@@ -12,22 +12,22 @@
 #include "core/fxcrt/fx_system.h"
 #include "xfa/fwl/core/cfwl_evtscroll.h"
 #include "xfa/fwl/core/cfwl_timer.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
-class IFWL_Widget;
+class CFWL_Widget;
 
 #define FWL_STYLEEXT_SCB_Horz (0L << 0)
 #define FWL_STYLEEXT_SCB_Vert (1L << 0)
 
-class CFWL_ScrollBar : public IFWL_Widget {
+class CFWL_ScrollBar : public CFWL_Widget {
  public:
   CFWL_ScrollBar(const CFWL_App* app,
                  std::unique_ptr<CFWL_WidgetProperties> properties,
-                 IFWL_Widget* pOuter);
+                 CFWL_Widget* pOuter);
   ~CFWL_ScrollBar() override;
 
-  // IFWL_Widget
+  // CFWL_Widget
   FWL_Type GetClassID() const override;
   void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
   void Update() override;
diff --git a/xfa/fwl/core/cfwl_spinbutton.cpp b/xfa/fwl/core/cfwl_spinbutton.cpp
index 2afbc82..71ed3b0 100644
--- a/xfa/fwl/core/cfwl_spinbutton.cpp
+++ b/xfa/fwl/core/cfwl_spinbutton.cpp
@@ -30,7 +30,7 @@
 CFWL_SpinButton::CFWL_SpinButton(
     const CFWL_App* app,
     std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr),
+    : CFWL_Widget(app, std::move(properties), nullptr),
       m_dwUpState(CFWL_PartState_Normal),
       m_dwDnState(CFWL_PartState_Normal),
       m_iButtonIndex(0),
@@ -56,7 +56,7 @@
   }
 
   rect.Set(0, 0, kMinWidth, kMinHeight);
-  IFWL_Widget::GetWidgetRect(rect, true);
+  CFWL_Widget::GetWidgetRect(rect, true);
 }
 
 void CFWL_SpinButton::Update() {
@@ -200,7 +200,7 @@
     default:
       break;
   }
-  IFWL_Widget::OnProcessMessage(pMessage);
+  CFWL_Widget::OnProcessMessage(pMessage);
 }
 
 void CFWL_SpinButton::OnDrawWidget(CFX_Graphics* pGraphics,
diff --git a/xfa/fwl/core/cfwl_spinbutton.h b/xfa/fwl/core/cfwl_spinbutton.h
index 87cf167..6b53e68 100644
--- a/xfa/fwl/core/cfwl_spinbutton.h
+++ b/xfa/fwl/core/cfwl_spinbutton.h
@@ -11,7 +11,7 @@
 
 #include "xfa/fwl/core/cfwl_event.h"
 #include "xfa/fwl/core/cfwl_timer.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxfa/cxfa_eventparam.h"
 
 #define FWL_STYLEEXE_SPB_Vert (1L << 0)
@@ -19,13 +19,13 @@
 class CFWL_MsgMouse;
 class CFWL_WidgetProperties;
 
-class CFWL_SpinButton : public IFWL_Widget {
+class CFWL_SpinButton : public CFWL_Widget {
  public:
   CFWL_SpinButton(const CFWL_App* app,
                   std::unique_ptr<CFWL_WidgetProperties> properties);
   ~CFWL_SpinButton() override;
 
-  // IFWL_Widget
+  // CFWL_Widget
   FWL_Type GetClassID() const override;
   void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
   void Update() override;
diff --git a/xfa/fwl/core/cfwl_themepart.h b/xfa/fwl/core/cfwl_themepart.h
index 93565e9..f80bb8e 100644
--- a/xfa/fwl/core/cfwl_themepart.h
+++ b/xfa/fwl/core/cfwl_themepart.h
@@ -77,7 +77,7 @@
   CFWL_PartState_Selected = 1 << 14
 };
 
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_ThemePart {
  public:
@@ -85,7 +85,7 @@
 
   CFX_Matrix m_matrix;
   CFX_RectF m_rtPart;
-  IFWL_Widget* m_pWidget;
+  CFWL_Widget* m_pWidget;
   CFWL_Part m_iPart;
   uint32_t m_dwStates;
   bool m_bMaximize;
diff --git a/xfa/fwl/core/cfwl_timer.cpp b/xfa/fwl/core/cfwl_timer.cpp
index 2d92e6d..c909afc 100644
--- a/xfa/fwl/core/cfwl_timer.cpp
+++ b/xfa/fwl/core/cfwl_timer.cpp
@@ -8,8 +8,8 @@
 
 #include "xfa/fwl/core/cfwl_app.h"
 #include "xfa/fwl/core/cfwl_timerinfo.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_adaptertimermgr.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxfa/xfa_ffapp.h"
 
 CFWL_TimerInfo* CFWL_Timer::StartTimer(uint32_t dwElapse, bool bImmediately) {
diff --git a/xfa/fwl/core/cfwl_timer.h b/xfa/fwl/core/cfwl_timer.h
index 2f91e78..7b36c3e 100644
--- a/xfa/fwl/core/cfwl_timer.h
+++ b/xfa/fwl/core/cfwl_timer.h
@@ -10,18 +10,18 @@
 #include "core/fxcrt/fx_system.h"
 
 class CFWL_TimerInfo;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_Timer {
  public:
-  explicit CFWL_Timer(IFWL_Widget* parent) : m_pWidget(parent) {}
+  explicit CFWL_Timer(CFWL_Widget* parent) : m_pWidget(parent) {}
   virtual ~CFWL_Timer() {}
 
   virtual void Run(CFWL_TimerInfo* hTimer) = 0;
   CFWL_TimerInfo* StartTimer(uint32_t dwElapse, bool bImmediately);
 
  protected:
-  IFWL_Widget* m_pWidget;  // Not owned.
+  CFWL_Widget* m_pWidget;  // Not owned.
 };
 
 #endif  // XFA_FWL_CORE_CFWL_TIMER_H_
diff --git a/xfa/fwl/core/cfwl_widget.cpp b/xfa/fwl/core/cfwl_widget.cpp
index 5914ce5..e2de866 100644
--- a/xfa/fwl/core/cfwl_widget.cpp
+++ b/xfa/fwl/core/cfwl_widget.cpp
@@ -6,97 +6,797 @@
 
 #include "xfa/fwl/core/cfwl_widget.h"
 
+#include <algorithm>
+#include <utility>
+
 #include "xfa/fde/tto/fde_textout.h"
 #include "xfa/fwl/core/cfwl_app.h"
+#include "xfa/fwl/core/cfwl_combobox.h"
+#include "xfa/fwl/core/cfwl_evtkey.h"
+#include "xfa/fwl/core/cfwl_evtkillfocus.h"
+#include "xfa/fwl/core/cfwl_evtmouse.h"
+#include "xfa/fwl/core/cfwl_evtmousewheel.h"
+#include "xfa/fwl/core/cfwl_evtsetfocus.h"
+#include "xfa/fwl/core/cfwl_evtsizechanged.h"
+#include "xfa/fwl/core/cfwl_form.h"
+#include "xfa/fwl/core/cfwl_msgkey.h"
+#include "xfa/fwl/core/cfwl_msgkillfocus.h"
+#include "xfa/fwl/core/cfwl_msgmouse.h"
+#include "xfa/fwl/core/cfwl_msgmousewheel.h"
+#include "xfa/fwl/core/cfwl_msgsetfocus.h"
 #include "xfa/fwl/core/cfwl_notedriver.h"
+#include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
 #include "xfa/fwl/core/cfwl_widgetmgr.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
+#include "xfa/fxfa/xfa_ffapp.h"
 
+#define FWL_STYLEEXT_MNU_Vert (1L << 0)
 #define FWL_WGT_CalcHeight 2048
 #define FWL_WGT_CalcWidth 2048
 #define FWL_WGT_CalcMultiLineDefWidth 120.0f
 
-CFWL_Widget::CFWL_Widget(const CFWL_App* app) : m_pApp(app) {}
+CFWL_Widget::CFWL_Widget(const CFWL_App* app,
+                         std::unique_ptr<CFWL_WidgetProperties> properties,
+                         CFWL_Widget* pOuter)
+    : m_pOwnerApp(app),
+      m_pWidgetMgr(app->GetWidgetMgr()),
+      m_pProperties(std::move(properties)),
+      m_pOuter(pOuter),
+      m_iLock(0),
+      m_pLayoutItem(nullptr),
+      m_nEventKey(0),
+      m_pDelegate(nullptr) {
+  ASSERT(m_pWidgetMgr);
 
-CFWL_Widget::~CFWL_Widget() {}
+  CFWL_Widget* pParent = m_pProperties->m_pParent;
+  m_pWidgetMgr->InsertWidget(pParent, this);
+  if (IsChild())
+    return;
 
-void CFWL_Widget::Initialize() {
-  ASSERT(m_pIface);
-  m_pIface->SetAssociateWidget(this);
+  CFWL_Widget* pOwner = m_pProperties->m_pOwner;
+  if (pOwner)
+    m_pWidgetMgr->SetOwner(pOwner, this);
+}
+
+CFWL_Widget::~CFWL_Widget() {
+  NotifyDriver();
+  m_pWidgetMgr->RemoveWidget(this);
+}
+
+bool CFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const {
+  return false;
 }
 
 void CFWL_Widget::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (m_pIface)
-    m_pIface->GetWidgetRect(rect, bAutoSize);
+  if (!bAutoSize) {
+    rect = m_pProperties->m_rtWidget;
+    return;
+  }
+
+  if (HasEdge()) {
+    FX_FLOAT fEdge = GetEdgeWidth();
+    rect.Inflate(fEdge, fEdge);
+  }
+  if (HasBorder()) {
+    FX_FLOAT fBorder = GetBorderSize();
+    rect.Inflate(fBorder, fBorder);
+  }
 }
 
 void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
-  if (m_pIface)
-    m_pIface->SetWidgetRect(rect);
+  CFX_RectF rtOld = m_pProperties->m_rtWidget;
+  m_pProperties->m_rtWidget = rect;
+  if (IsChild()) {
+    if (FXSYS_fabs(rtOld.width - rect.width) > 0.5f ||
+        FXSYS_fabs(rtOld.height - rect.height) > 0.5f) {
+      CFWL_EvtSizeChanged ev;
+      ev.m_pSrcTarget = this;
+      ev.m_rtOld = rtOld;
+      ev.m_rtNew = rect;
+
+      if (IFWL_WidgetDelegate* pDelegate = GetDelegate())
+        pDelegate->OnProcessEvent(&ev);
+    }
+    return;
+  }
+  m_pWidgetMgr->SetWidgetRect_Native(this, rect);
+}
+
+void CFWL_Widget::GetClientRect(CFX_RectF& rect) {
+  GetEdgeRect(rect);
+  if (HasEdge()) {
+    FX_FLOAT fEdge = GetEdgeWidth();
+    rect.Deflate(fEdge, fEdge);
+  }
+}
+
+void CFWL_Widget::SetParent(CFWL_Widget* pParent) {
+  m_pProperties->m_pParent = pParent;
+  m_pWidgetMgr->SetParent(pParent, this);
+}
+
+uint32_t CFWL_Widget::GetStyles() const {
+  return m_pProperties->m_dwStyles;
 }
 
 void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
                                uint32_t dwStylesRemoved) {
-  if (m_pIface)
-    m_pIface->ModifyStyles(dwStylesAdded, dwStylesRemoved);
+  m_pProperties->m_dwStyles =
+      (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
 }
 
-uint32_t CFWL_Widget::GetStylesEx() {
-  return m_pIface ? m_pIface->GetStylesEx() : 0;
+uint32_t CFWL_Widget::GetStylesEx() const {
+  return m_pProperties->m_dwStyleExes;
+}
+uint32_t CFWL_Widget::GetStates() const {
+  return m_pProperties->m_dwStates;
 }
 
 void CFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded,
                                  uint32_t dwStylesExRemoved) {
-  m_pIface->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
+  m_pProperties->m_dwStyleExes =
+      (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
 }
 
-uint32_t CFWL_Widget::GetStates() {
-  return m_pIface ? m_pIface->GetStates() : 0;
+static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr,
+                                  CFWL_Widget* widget,
+                                  CFWL_NoteDriver* noteDriver) {
+  CFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget);
+  while (child) {
+    noteDriver->NotifyTargetHide(child);
+    NotifyHideChildWidget(widgetMgr, child, noteDriver);
+    child = widgetMgr->GetNextSiblingWidget(child);
+  }
 }
 
 void CFWL_Widget::SetStates(uint32_t dwStates, bool bSet) {
-  if (m_pIface)
-    m_pIface->SetStates(dwStates, bSet);
-}
+  bSet ? (m_pProperties->m_dwStates |= dwStates)
+       : (m_pProperties->m_dwStates &= ~dwStates);
+  if (!(dwStates & FWL_WGTSTATE_Invisible) || !bSet)
+    return;
 
-void CFWL_Widget::SetLayoutItem(void* pItem) {
-  if (m_pIface)
-    m_pIface->SetLayoutItem(pItem);
-}
-
-void CFWL_Widget::Update() {
-  if (m_pIface)
-    m_pIface->Update();
-}
-
-void CFWL_Widget::LockUpdate() {
-  if (m_pIface)
-    m_pIface->LockUpdate();
-}
-
-void CFWL_Widget::UnlockUpdate() {
-  if (m_pIface)
-    m_pIface->UnlockUpdate();
+  CFWL_NoteDriver* noteDriver =
+      static_cast<CFWL_NoteDriver*>(GetOwnerApp()->GetNoteDriver());
+  CFWL_WidgetMgr* widgetMgr = GetOwnerApp()->GetWidgetMgr();
+  noteDriver->NotifyTargetHide(this);
+  CFWL_Widget* child = widgetMgr->GetFirstChildWidget(this);
+  while (child) {
+    noteDriver->NotifyTargetHide(child);
+    NotifyHideChildWidget(widgetMgr, child, noteDriver);
+    child = widgetMgr->GetNextSiblingWidget(child);
+  }
+  return;
 }
 
 FWL_WidgetHit CFWL_Widget::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  if (!m_pIface)
-    return FWL_WidgetHit::Unknown;
-  return m_pIface->HitTest(fx, fy);
+  CFX_RectF rtClient;
+  GetClientRect(rtClient);
+  if (rtClient.Contains(fx, fy))
+    return FWL_WidgetHit::Client;
+  if (HasEdge()) {
+    CFX_RectF rtEdge;
+    GetEdgeRect(rtEdge);
+    if (rtEdge.Contains(fx, fy))
+      return FWL_WidgetHit::Edge;
+  }
+  if (HasBorder()) {
+    CFX_RectF rtRelative;
+    GetRelativeRect(rtRelative);
+    if (rtRelative.Contains(fx, fy))
+      return FWL_WidgetHit::Border;
+  }
+  return FWL_WidgetHit::Unknown;
 }
 
-void CFWL_Widget::DrawWidget(CFX_Graphics* pGraphics,
+void CFWL_Widget::TransformTo(CFWL_Widget* pWidget,
+                              FX_FLOAT& fx,
+                              FX_FLOAT& fy) {
+  if (m_pWidgetMgr->IsFormDisabled()) {
+    CFX_SizeF szOffset;
+    if (IsParent(pWidget)) {
+      szOffset = GetOffsetFromParent(pWidget);
+    } else {
+      szOffset = pWidget->GetOffsetFromParent(this);
+      szOffset.x = -szOffset.x;
+      szOffset.y = -szOffset.y;
+    }
+    fx += szOffset.x;
+    fy += szOffset.y;
+    return;
+  }
+  CFX_RectF r;
+  CFX_Matrix m;
+  CFWL_Widget* parent = GetParent();
+  if (parent) {
+    GetWidgetRect(r);
+    fx += r.left;
+    fy += r.top;
+    GetMatrix(m, true);
+    m.TransformPoint(fx, fy);
+  }
+  CFWL_Widget* form1 = m_pWidgetMgr->GetSystemFormWidget(this);
+  if (!form1)
+    return;
+  if (!pWidget) {
+    form1->GetWidgetRect(r);
+    fx += r.left;
+    fy += r.top;
+    return;
+  }
+  CFWL_Widget* form2 = m_pWidgetMgr->GetSystemFormWidget(pWidget);
+  if (!form2)
+    return;
+  if (form1 != form2) {
+    form1->GetWidgetRect(r);
+    fx += r.left;
+    fy += r.top;
+    form2->GetWidgetRect(r);
+    fx -= r.left;
+    fy -= r.top;
+  }
+  parent = pWidget->GetParent();
+  if (parent) {
+    pWidget->GetMatrix(m, true);
+    CFX_Matrix m1;
+    m1.SetIdentity();
+    m1.SetReverse(m);
+    m1.TransformPoint(fx, fy);
+    pWidget->GetWidgetRect(r);
+    fx -= r.left;
+    fy -= r.top;
+  }
+}
+
+void CFWL_Widget::GetMatrix(CFX_Matrix& matrix, bool bGlobal) {
+  if (!m_pProperties)
+    return;
+  if (!bGlobal) {
+    matrix.SetIdentity();
+    return;
+  }
+
+  CFWL_Widget* parent = GetParent();
+  CFX_ArrayTemplate<CFWL_Widget*> parents;
+  while (parent) {
+    parents.Add(parent);
+    parent = parent->GetParent();
+  }
+  matrix.SetIdentity();
+  CFX_Matrix ctmOnParent;
+  CFX_RectF rect;
+  int32_t count = parents.GetSize();
+  for (int32_t i = count - 2; i >= 0; i--) {
+    parent = parents.GetAt(i);
+    parent->GetMatrix(ctmOnParent, false);
+    parent->GetWidgetRect(rect);
+    matrix.Concat(ctmOnParent, true);
+    matrix.Translate(rect.left, rect.top, true);
+  }
+  CFX_Matrix m;
+  m.SetIdentity();
+  matrix.Concat(m, true);
+  parents.RemoveAll();
+}
+
+IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const {
+  return m_pProperties->m_pThemeProvider;
+}
+
+void CFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
+  m_pProperties->m_pThemeProvider = pThemeProvider;
+}
+
+bool CFWL_Widget::IsEnabled() const {
+  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
+}
+
+bool CFWL_Widget::IsActive() const {
+  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) == 0;
+}
+
+bool CFWL_Widget::HasBorder() const {
+  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
+}
+
+bool CFWL_Widget::HasEdge() const {
+  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask);
+}
+
+bool CFWL_Widget::IsVisible() const {
+  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
+}
+
+bool CFWL_Widget::IsOverLapper() const {
+  return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
+         FWL_WGTSTYLE_OverLapper;
+}
+
+bool CFWL_Widget::IsPopup() const {
+  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
+}
+
+bool CFWL_Widget::IsChild() const {
+  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
+}
+
+bool CFWL_Widget::IsOffscreen() const {
+  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Offscreen);
+}
+
+void CFWL_Widget::GetEdgeRect(CFX_RectF& rtEdge) {
+  rtEdge = m_pProperties->m_rtWidget;
+  rtEdge.left = rtEdge.top = 0;
+  if (HasBorder()) {
+    FX_FLOAT fCX = GetBorderSize();
+    FX_FLOAT fCY = GetBorderSize(false);
+    rtEdge.Deflate(fCX, fCY);
+  }
+}
+
+FX_FLOAT CFWL_Widget::GetBorderSize(bool bCX) {
+  FX_FLOAT* pfBorder = static_cast<FX_FLOAT*>(GetThemeCapacity(
+      bCX ? CFWL_WidgetCapacity::CXBorder : CFWL_WidgetCapacity::CYBorder));
+  if (!pfBorder)
+    return 0;
+  return *pfBorder;
+}
+
+FX_FLOAT CFWL_Widget::GetEdgeWidth() {
+  CFWL_WidgetCapacity dwCapacity = CFWL_WidgetCapacity::None;
+  switch (m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask) {
+    case FWL_WGTSTYLE_EdgeFlat: {
+      dwCapacity = CFWL_WidgetCapacity::EdgeFlat;
+      break;
+    }
+    case FWL_WGTSTYLE_EdgeRaised: {
+      dwCapacity = CFWL_WidgetCapacity::EdgeRaised;
+      break;
+    }
+    case FWL_WGTSTYLE_EdgeSunken: {
+      dwCapacity = CFWL_WidgetCapacity::EdgeSunken;
+      break;
+    }
+  }
+  if (dwCapacity != CFWL_WidgetCapacity::None) {
+    FX_FLOAT* fRet = static_cast<FX_FLOAT*>(GetThemeCapacity(dwCapacity));
+    return fRet ? *fRet : 0;
+  }
+  return 0;
+}
+
+void CFWL_Widget::GetRelativeRect(CFX_RectF& rect) {
+  rect = m_pProperties->m_rtWidget;
+  rect.left = rect.top = 0;
+}
+
+void* CFWL_Widget::GetThemeCapacity(CFWL_WidgetCapacity dwCapacity) {
+  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
+  if (!pTheme)
+    return nullptr;
+
+  CFWL_ThemePart part;
+  part.m_pWidget = this;
+  return pTheme->GetCapacity(&part, dwCapacity);
+}
+
+IFWL_ThemeProvider* CFWL_Widget::GetAvailableTheme() {
+  if (m_pProperties->m_pThemeProvider)
+    return m_pProperties->m_pThemeProvider;
+
+  CFWL_Widget* pUp = this;
+  do {
+    pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
+              ? m_pWidgetMgr->GetOwnerWidget(pUp)
+              : m_pWidgetMgr->GetParentWidget(pUp);
+    if (pUp) {
+      IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
+      if (pRet)
+        return pRet;
+    }
+  } while (pUp);
+  return nullptr;
+}
+
+CFWL_Widget* CFWL_Widget::GetRootOuter() {
+  CFWL_Widget* pRet = m_pOuter;
+  if (!pRet)
+    return nullptr;
+
+  while (CFWL_Widget* pOuter = pRet->GetOuter())
+    pRet = pOuter;
+  return pRet;
+}
+
+CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText,
+                                    IFWL_ThemeProvider* pTheme,
+                                    bool bMultiLine,
+                                    int32_t iLineWidth) {
+  if (!pTheme)
+    return CFX_SizeF();
+
+  CFWL_ThemeText calPart;
+  calPart.m_pWidget = this;
+  calPart.m_wsText = wsText;
+  calPart.m_dwTTOStyles =
+      bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine;
+  calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
+  CFX_RectF rect;
+  FX_FLOAT fWidth = bMultiLine
+                        ? (iLineWidth > 0 ? (FX_FLOAT)iLineWidth
+                                          : FWL_WGT_CalcMultiLineDefWidth)
+                        : FWL_WGT_CalcWidth;
+  rect.Set(0, 0, fWidth, FWL_WGT_CalcHeight);
+  pTheme->CalcTextRect(&calPart, rect);
+  return CFX_SizeF(rect.width, rect.height);
+}
+
+void CFWL_Widget::CalcTextRect(const CFX_WideString& wsText,
+                               IFWL_ThemeProvider* pTheme,
+                               uint32_t dwTTOStyles,
+                               int32_t iTTOAlign,
+                               CFX_RectF& rect) {
+  CFWL_ThemeText calPart;
+  calPart.m_pWidget = this;
+  calPart.m_wsText = wsText;
+  calPart.m_dwTTOStyles = dwTTOStyles;
+  calPart.m_iTTOAlign = iTTOAlign;
+  pTheme->CalcTextRect(&calPart, rect);
+}
+
+void CFWL_Widget::SetFocus(bool bFocus) {
+  if (m_pWidgetMgr->IsFormDisabled())
+    return;
+
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pDriver =
+      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
+  if (!pDriver)
+    return;
+
+  CFWL_Widget* curFocus = pDriver->GetFocus();
+  if (bFocus && curFocus != this)
+    pDriver->SetFocus(this);
+  else if (!bFocus && curFocus == this)
+    pDriver->SetFocus(nullptr);
+}
+
+void CFWL_Widget::SetGrab(bool bSet) {
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pDriver =
+      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
+  pDriver->SetGrab(this, bSet);
+}
+
+void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight,
+                              FX_FLOAT fMaxHeight,
+                              const CFX_RectF& rtAnchor,
+                              CFX_RectF& rtPopup) {
+  if (GetClassID() == FWL_Type::ComboBox) {
+    if (m_pWidgetMgr->IsFormDisabled()) {
+      m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
+                                       rtPopup);
+      return;
+    }
+    GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
+    return;
+  }
+  if (GetClassID() == FWL_Type::DateTimePicker &&
+      m_pWidgetMgr->IsFormDisabled()) {
+    m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
+                                     rtPopup);
+    return;
+  }
+  GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
+}
+
+bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight,
+                                  FX_FLOAT fMaxHeight,
+                                  const CFX_RectF& rtAnchor,
+                                  CFX_RectF& rtPopup) {
+  FX_FLOAT fx = 0;
+  FX_FLOAT fy = 0;
+
+  if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
+    bool bLeft = m_pProperties->m_rtWidget.left < 0;
+    FX_FLOAT fRight = rtAnchor.right() + rtPopup.width;
+    TransformTo(nullptr, fx, fy);
+    if (fRight + fx > 0.0f || bLeft) {
+      rtPopup.Set(rtAnchor.left - rtPopup.width, rtAnchor.top, rtPopup.width,
+                  rtPopup.height);
+    } else {
+      rtPopup.Set(rtAnchor.right(), rtAnchor.top, rtPopup.width,
+                  rtPopup.height);
+    }
+  } else {
+    FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height;
+    TransformTo(nullptr, fx, fy);
+    if (fBottom + fy > 0.0f) {
+      rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
+                  rtPopup.height);
+    } else {
+      rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
+                  rtPopup.height);
+    }
+  }
+  rtPopup.Offset(fx, fy);
+  return true;
+}
+
+bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight,
+                                      FX_FLOAT fMaxHeight,
+                                      const CFX_RectF& rtAnchor,
+                                      CFX_RectF& rtPopup) {
+  FX_FLOAT fx = 0;
+  FX_FLOAT fy = 0;
+
+  FX_FLOAT fPopHeight = rtPopup.height;
+  if (rtPopup.height > fMaxHeight)
+    fPopHeight = fMaxHeight;
+  else if (rtPopup.height < fMinHeight)
+    fPopHeight = fMinHeight;
+
+  FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width);
+  FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight;
+  TransformTo(nullptr, fx, fy);
+  if (fBottom + fy > 0.0f)
+    rtPopup.Set(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
+  else
+    rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
+
+  rtPopup.Offset(fx, fy);
+  return true;
+}
+
+bool CFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight,
+                                     FX_FLOAT fMaxHeight,
+                                     const CFX_RectF& rtAnchor,
+                                     CFX_RectF& rtPopup) {
+  FX_FLOAT fx = 0;
+  FX_FLOAT fy = 0;
+
+  TransformTo(nullptr, fx, fy);
+  if (rtAnchor.bottom() + fy > 0.0f) {
+    rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
+                rtPopup.height);
+  } else {
+    rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
+                rtPopup.height);
+  }
+  rtPopup.Offset(fx, fy);
+  return true;
+}
+
+void CFWL_Widget::RegisterEventTarget(CFWL_Widget* pEventSource) {
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
+  if (!pNoteDriver)
+    return;
+
+  pNoteDriver->RegisterEventTarget(this, pEventSource);
+}
+
+void CFWL_Widget::UnregisterEventTarget() {
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
+  if (!pNoteDriver)
+    return;
+
+  pNoteDriver->UnregisterEventTarget(this);
+}
+
+void CFWL_Widget::DispatchKeyEvent(CFWL_MsgKey* pNote) {
+  if (!pNote)
+    return;
+
+  auto pEvent = pdfium::MakeUnique<CFWL_EvtKey>();
+  pEvent->m_pSrcTarget = this;
+  pEvent->m_dwCmd = pNote->m_dwCmd;
+  pEvent->m_dwKeyCode = pNote->m_dwKeyCode;
+  pEvent->m_dwFlags = pNote->m_dwFlags;
+  DispatchEvent(pEvent.get());
+}
+
+void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
+  if (m_pOuter) {
+    m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
+    return;
+  }
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
+  if (!pNoteDriver)
+    return;
+  pNoteDriver->SendEvent(pEvent);
+}
+
+void CFWL_Widget::Repaint(const CFX_RectF* pRect) {
+  if (pRect) {
+    m_pWidgetMgr->RepaintWidget(this, pRect);
+    return;
+  }
+  CFX_RectF rect;
+  rect = m_pProperties->m_rtWidget;
+  rect.left = rect.top = 0;
+  m_pWidgetMgr->RepaintWidget(this, &rect);
+}
+
+void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics,
+                                 CFWL_Part iPartBk,
+                                 IFWL_ThemeProvider* pTheme,
+                                 const CFX_Matrix* pMatrix) {
+  CFX_RectF rtRelative;
+  GetRelativeRect(rtRelative);
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = iPartBk;
+  param.m_pGraphics = pGraphics;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix, true);
+  param.m_rtPart = rtRelative;
+  pTheme->DrawBackground(&param);
+}
+
+void CFWL_Widget::DrawBorder(CFX_Graphics* pGraphics,
+                             CFWL_Part iPartBorder,
+                             IFWL_ThemeProvider* pTheme,
                              const CFX_Matrix* pMatrix) {
-  if (m_pIface)
-    m_pIface->DrawWidget(pGraphics, pMatrix);
+  CFX_RectF rtRelative;
+  GetRelativeRect(rtRelative);
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = iPartBorder;
+  param.m_pGraphics = pGraphics;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix, true);
+  param.m_rtPart = rtRelative;
+  pTheme->DrawBackground(&param);
 }
 
-IFWL_WidgetDelegate* CFWL_Widget::GetDelegate() const {
-  return m_pIface ? m_pIface->GetDelegate() : nullptr;
+void CFWL_Widget::DrawEdge(CFX_Graphics* pGraphics,
+                           CFWL_Part iPartEdge,
+                           IFWL_ThemeProvider* pTheme,
+                           const CFX_Matrix* pMatrix) {
+  CFX_RectF rtEdge;
+  GetEdgeRect(rtEdge);
+  CFWL_ThemeBackground param;
+  param.m_pWidget = this;
+  param.m_iPart = iPartEdge;
+  param.m_pGraphics = pGraphics;
+  if (pMatrix)
+    param.m_matrix.Concat(*pMatrix, true);
+  param.m_rtPart = rtEdge;
+  pTheme->DrawBackground(&param);
 }
 
-void CFWL_Widget::SetDelegate(IFWL_WidgetDelegate* pDelegate) {
-  if (m_pIface)
-    m_pIface->SetDelegate(pDelegate);
+void CFWL_Widget::NotifyDriver() {
+  const CFWL_App* pApp = GetOwnerApp();
+  if (!pApp)
+    return;
+
+  CFWL_NoteDriver* pDriver =
+      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
+  if (!pDriver)
+    return;
+
+  pDriver->NotifyTargetDestroy(this);
 }
+
+CFX_SizeF CFWL_Widget::GetOffsetFromParent(CFWL_Widget* pParent) {
+  if (pParent == this)
+    return CFX_SizeF();
+
+  CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
+  if (!pWidgetMgr)
+    return CFX_SizeF();
+
+  CFX_SizeF szRet(m_pProperties->m_rtWidget.left,
+                  m_pProperties->m_rtWidget.top);
+
+  CFWL_Widget* pDstWidget = GetParent();
+  while (pDstWidget && pDstWidget != pParent) {
+    CFX_RectF rtDst;
+    pDstWidget->GetWidgetRect(rtDst);
+    szRet += CFX_SizeF(rtDst.left, rtDst.top);
+    pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget);
+  }
+  return szRet;
+}
+
+bool CFWL_Widget::IsParent(CFWL_Widget* pParent) {
+  CFWL_Widget* pUpWidget = GetParent();
+  while (pUpWidget) {
+    if (pUpWidget == pParent)
+      return true;
+    pUpWidget = pUpWidget->GetParent();
+  }
+  return false;
+}
+
+void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) {
+  if (!pMessage->m_pDstTarget)
+    return;
+
+  CFWL_Widget* pWidget = pMessage->m_pDstTarget;
+  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
+  switch (dwMsgCode) {
+    case CFWL_MessageType::Mouse: {
+      CFWL_MsgMouse* pMsgMouse = static_cast<CFWL_MsgMouse*>(pMessage);
+      CFWL_EvtMouse evt;
+      evt.m_pSrcTarget = pWidget;
+      evt.m_pDstTarget = pWidget;
+      evt.m_dwCmd = pMsgMouse->m_dwCmd;
+      evt.m_dwFlags = pMsgMouse->m_dwFlags;
+      evt.m_fx = pMsgMouse->m_fx;
+      evt.m_fy = pMsgMouse->m_fy;
+      pWidget->DispatchEvent(&evt);
+      break;
+    }
+    case CFWL_MessageType::MouseWheel: {
+      CFWL_MsgMouseWheel* pMsgMouseWheel =
+          static_cast<CFWL_MsgMouseWheel*>(pMessage);
+      CFWL_EvtMouseWheel evt;
+      evt.m_pSrcTarget = pWidget;
+      evt.m_pDstTarget = pWidget;
+      evt.m_dwFlags = pMsgMouseWheel->m_dwFlags;
+      evt.m_fDeltaX = pMsgMouseWheel->m_fDeltaX;
+      evt.m_fDeltaY = pMsgMouseWheel->m_fDeltaY;
+      evt.m_fx = pMsgMouseWheel->m_fx;
+      evt.m_fy = pMsgMouseWheel->m_fy;
+      pWidget->DispatchEvent(&evt);
+      break;
+    }
+    case CFWL_MessageType::Key: {
+      CFWL_MsgKey* pMsgKey = static_cast<CFWL_MsgKey*>(pMessage);
+      CFWL_EvtKey evt;
+      evt.m_pSrcTarget = pWidget;
+      evt.m_pDstTarget = pWidget;
+      evt.m_dwKeyCode = pMsgKey->m_dwKeyCode;
+      evt.m_dwFlags = pMsgKey->m_dwFlags;
+      evt.m_dwCmd = pMsgKey->m_dwCmd;
+      pWidget->DispatchEvent(&evt);
+      break;
+    }
+    case CFWL_MessageType::SetFocus: {
+      CFWL_MsgSetFocus* pMsgSetFocus = static_cast<CFWL_MsgSetFocus*>(pMessage);
+      CFWL_EvtSetFocus evt;
+      evt.m_pSrcTarget = pMsgSetFocus->m_pDstTarget;
+      evt.m_pDstTarget = pMsgSetFocus->m_pDstTarget;
+      evt.m_pSetFocus = pWidget;
+      pWidget->DispatchEvent(&evt);
+      break;
+    }
+    case CFWL_MessageType::KillFocus: {
+      CFWL_MsgKillFocus* pMsgKillFocus =
+          static_cast<CFWL_MsgKillFocus*>(pMessage);
+      CFWL_EvtKillFocus evt;
+      evt.m_pSrcTarget = pMsgKillFocus->m_pDstTarget;
+      evt.m_pDstTarget = pMsgKillFocus->m_pDstTarget;
+      evt.m_pKillFocus = pWidget;
+      pWidget->DispatchEvent(&evt);
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}
+
+void CFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics,
+                               const CFX_Matrix* pMatrix) {}
diff --git a/xfa/fwl/core/cfwl_widget.h b/xfa/fwl/core/cfwl_widget.h
index abb8d54..7a993e5 100644
--- a/xfa/fwl/core/cfwl_widget.h
+++ b/xfa/fwl/core/cfwl_widget.h
@@ -6,52 +6,190 @@
 
 #ifndef XFA_FWL_CORE_CFWL_WIDGET_H_
 #define XFA_FWL_CORE_CFWL_WIDGET_H_
-
 #include <memory>
 
+#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_system.h"
 #include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_themepart.h"
+#include "xfa/fwl/core/cfwl_widgetmgr.h"
+#include "xfa/fwl/core/fwl_widgethit.h"
+#include "xfa/fwl/core/ifwl_widgetdelegate.h"
+#include "xfa/fwl/theme/cfwl_widgettp.h"
 
-class CFWL_Event;
-class CFWL_Message;
+enum class FWL_Type {
+  Unknown = 0,
+
+  Barcode,
+  Caret,
+  CheckBox,
+  ComboBox,
+  DateTimePicker,
+  Edit,
+  Form,
+  FormProxy,
+  ListBox,
+  MonthCalendar,
+  PictureBox,
+  PushButton,
+  ScrollBar,
+  SpinButton,
+  ToolTip
+};
+
+class CFWL_App;
+class CFWL_AppImp;
+class CFWL_MsgKey;
 class CFWL_Widget;
-class CFWL_WidgetDelegate;
 class CFWL_WidgetMgr;
+class CFWL_WidgetProperties;
+class IFWL_ThemeProvider;
 
-class CFWL_Widget {
+class CFWL_Widget : public IFWL_WidgetDelegate {
  public:
-  explicit CFWL_Widget(const CFWL_App*);
-  virtual ~CFWL_Widget();
+  ~CFWL_Widget() override;
 
-  IFWL_Widget* GetWidget() { return m_pIface.get(); }
-  IFWL_Widget* GetWidget() const { return m_pIface.get(); }
+  virtual FWL_Type GetClassID() const = 0;
+  virtual bool IsInstance(const CFX_WideStringC& wsClass) const;
+  virtual void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false);
+  virtual void GetClientRect(CFX_RectF& rect);
+  virtual void ModifyStylesEx(uint32_t dwStylesExAdded,
+                              uint32_t dwStylesExRemoved);
+  virtual void SetStates(uint32_t dwStates, bool bSet = true);
+  virtual void Update() = 0;
+  virtual FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy);
+  virtual void DrawWidget(CFX_Graphics* pGraphics,
+                          const CFX_Matrix* pMatrix = nullptr) = 0;
+  virtual void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider);
 
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false);
+  // IFWL_WidgetDelegate.
+  void OnProcessMessage(CFWL_Message* pMessage) override;
+  void OnProcessEvent(CFWL_Event* pEvent) override;
+  void OnDrawWidget(CFX_Graphics* pGraphics,
+                    const CFX_Matrix* pMatrix = nullptr) override;
+
   void SetWidgetRect(const CFX_RectF& rect);
 
+  void SetParent(CFWL_Widget* pParent);
+
+  CFWL_Widget* GetOwner() { return m_pWidgetMgr->GetOwnerWidget(this); }
+  CFWL_Widget* GetOuter() const { return m_pOuter; }
+
+  uint32_t GetStyles() const;
   void ModifyStyles(uint32_t dwStylesAdded, uint32_t dwStylesRemoved);
-  uint32_t GetStylesEx();
-  void ModifyStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved);
+  uint32_t GetStylesEx() const;
+  uint32_t GetStates() const;
 
-  uint32_t GetStates();
-  void SetStates(uint32_t dwStates, bool bSet = true);
-  void SetLayoutItem(void* pItem);
+  void LockUpdate() { m_iLock++; }
+  void UnlockUpdate() {
+    if (IsLocked())
+      m_iLock--;
+  }
 
-  void Update();
-  void LockUpdate();
-  void UnlockUpdate();
+  void TransformTo(CFWL_Widget* pWidget, FX_FLOAT& fx, FX_FLOAT& fy);
+  void GetMatrix(CFX_Matrix& matrix, bool bGlobal = false);
+  IFWL_ThemeProvider* GetThemeProvider() const;
 
-  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy);
-  void DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix = nullptr);
+  void SetDelegate(IFWL_WidgetDelegate* delegate) { m_pDelegate = delegate; }
+  IFWL_WidgetDelegate* GetDelegate() {
+    return m_pDelegate ? m_pDelegate : this;
+  }
+  const IFWL_WidgetDelegate* GetDelegate() const {
+    return m_pDelegate ? m_pDelegate : this;
+  }
 
-  IFWL_WidgetDelegate* GetDelegate() const;
-  void SetDelegate(IFWL_WidgetDelegate*);
+  const CFWL_App* GetOwnerApp() const { return m_pOwnerApp; }
+  uint32_t GetEventKey() const { return m_nEventKey; }
+  void SetEventKey(uint32_t key) { m_nEventKey = key; }
+
+  void* GetLayoutItem() const { return m_pLayoutItem; }
+  void SetLayoutItem(void* pItem) { m_pLayoutItem = pItem; }
+
+  void SetFocus(bool bFocus);
+  void Repaint(const CFX_RectF* pRect = nullptr);
 
  protected:
-  void Initialize();
+  CFWL_Widget(const CFWL_App* app,
+              std::unique_ptr<CFWL_WidgetProperties> properties,
+              CFWL_Widget* pOuter);
 
-  const CFWL_App* m_pApp;
-  std::unique_ptr<IFWL_Widget> m_pIface;
+  bool IsEnabled() const;
+  bool IsActive() const;
+  bool IsLocked() const { return m_iLock > 0; }
+  bool HasBorder() const;
+  bool HasEdge() const;
+  void GetEdgeRect(CFX_RectF& rtEdge);
+  FX_FLOAT GetBorderSize(bool bCX = true);
+  FX_FLOAT GetEdgeWidth();
+  void GetRelativeRect(CFX_RectF& rect);
+  void* GetThemeCapacity(CFWL_WidgetCapacity dwCapacity);
+  IFWL_ThemeProvider* GetAvailableTheme();
+  CFX_SizeF CalcTextSize(const CFX_WideString& wsText,
+                         IFWL_ThemeProvider* pTheme,
+                         bool bMultiLine = false,
+                         int32_t iLineWidth = -1);
+  void CalcTextRect(const CFX_WideString& wsText,
+                    IFWL_ThemeProvider* pTheme,
+                    uint32_t dwTTOStyles,
+                    int32_t iTTOAlign,
+                    CFX_RectF& rect);
+  void SetGrab(bool bSet);
+  void GetPopupPos(FX_FLOAT fMinHeight,
+                   FX_FLOAT fMaxHeight,
+                   const CFX_RectF& rtAnchor,
+                   CFX_RectF& rtPopup);
+  void RegisterEventTarget(CFWL_Widget* pEventSource);
+  void UnregisterEventTarget();
+  void DispatchKeyEvent(CFWL_MsgKey* pNote);
+  void DispatchEvent(CFWL_Event* pEvent);
+  void DrawBorder(CFX_Graphics* pGraphics,
+                  CFWL_Part iPartBorder,
+                  IFWL_ThemeProvider* pTheme,
+                  const CFX_Matrix* pMatrix = nullptr);
+  void DrawEdge(CFX_Graphics* pGraphics,
+                CFWL_Part iPartEdge,
+                IFWL_ThemeProvider* pTheme,
+                const CFX_Matrix* pMatrix = nullptr);
+
+  const CFWL_App* const m_pOwnerApp;
+  CFWL_WidgetMgr* const m_pWidgetMgr;
+  std::unique_ptr<CFWL_WidgetProperties> m_pProperties;
+  CFWL_Widget* m_pOuter;
+  int32_t m_iLock;
+
+ private:
+  CFWL_Widget* GetParent() { return m_pWidgetMgr->GetParentWidget(this); }
+  CFX_SizeF GetOffsetFromParent(CFWL_Widget* pParent);
+
+  bool IsVisible() const;
+  bool IsOverLapper() const;
+  bool IsPopup() const;
+  bool IsChild() const;
+  bool IsOffscreen() const;
+  CFWL_Widget* GetRootOuter();
+  bool GetPopupPosMenu(FX_FLOAT fMinHeight,
+                       FX_FLOAT fMaxHeight,
+                       const CFX_RectF& rtAnchor,
+                       CFX_RectF& rtPopup);
+  bool GetPopupPosComboBox(FX_FLOAT fMinHeight,
+                           FX_FLOAT fMaxHeight,
+                           const CFX_RectF& rtAnchor,
+                           CFX_RectF& rtPopup);
+  bool GetPopupPosGeneral(FX_FLOAT fMinHeight,
+                          FX_FLOAT fMaxHeight,
+                          const CFX_RectF& rtAnchor,
+                          CFX_RectF& rtPopup);
+  bool GetScreenSize(FX_FLOAT& fx, FX_FLOAT& fy);
+  void DrawBackground(CFX_Graphics* pGraphics,
+                      CFWL_Part iPartBk,
+                      IFWL_ThemeProvider* pTheme,
+                      const CFX_Matrix* pMatrix = nullptr);
+  void NotifyDriver();
+  bool IsParent(CFWL_Widget* pParent);
+
+  void* m_pLayoutItem;
+  uint32_t m_nEventKey;
+  IFWL_WidgetDelegate* m_pDelegate;  // Not owned.
 };
 
 #endif  // XFA_FWL_CORE_CFWL_WIDGET_H_
diff --git a/xfa/fwl/core/cfwl_widgetmgr.cpp b/xfa/fwl/core/cfwl_widgetmgr.cpp
index 8a658b5..1514aee 100644
--- a/xfa/fwl/core/cfwl_widgetmgr.cpp
+++ b/xfa/fwl/core/cfwl_widgetmgr.cpp
@@ -28,7 +28,7 @@
 
 }  // namespace
 
-bool FWL_UseOffscreen(IFWL_Widget* pWidget) {
+bool FWL_UseOffscreen(CFWL_Widget* pWidget) {
 #if (_FX_OS_ == _FX_MACOSX_)
   return false;
 #else
@@ -47,17 +47,17 @@
 
 CFWL_WidgetMgr::~CFWL_WidgetMgr() {}
 
-IFWL_Widget* CFWL_WidgetMgr::GetParentWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   return pItem && pItem->pParent ? pItem->pParent->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   return pItem && pItem->pOwner ? pItem->pOwner->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   if (!pItem)
     return nullptr;
@@ -68,22 +68,22 @@
   return pItem ? pItem->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   return pItem && pItem->pPrevious ? pItem->pPrevious->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   return pItem && pItem->pNext ? pItem->pNext->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   return pItem && pItem->pChild ? pItem->pChild->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   if (!pItem)
     return nullptr;
@@ -94,7 +94,7 @@
   return pItem ? pItem->pWidget : nullptr;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(IFWL_Widget* pWidget) const {
+CFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   while (pItem) {
     if (IsAbleNative(pItem->pWidget))
@@ -104,7 +104,7 @@
   return nullptr;
 }
 
-void CFWL_WidgetMgr::SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex) {
+void CFWL_WidgetMgr::SetWidgetIndex(CFWL_Widget* pWidget, int32_t nIndex) {
   Item* pItem = GetWidgetMgrItem(pWidget);
   if (!pItem)
     return;
@@ -173,15 +173,15 @@
   }
 }
 
-void CFWL_WidgetMgr::RepaintWidget(IFWL_Widget* pWidget,
+void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
                                    const CFX_RectF* pRect) {
   if (!m_pAdapter)
     return;
 
-  IFWL_Widget* pNative = pWidget;
+  CFWL_Widget* pNative = pWidget;
   CFX_RectF rect(*pRect);
   if (IsFormDisabled()) {
-    IFWL_Widget* pOuter = pWidget->GetOuter();
+    CFWL_Widget* pOuter = pWidget->GetOuter();
     while (pOuter) {
       CFX_RectF rtTemp;
       pNative->GetWidgetRect(rtTemp);
@@ -201,8 +201,8 @@
   m_pAdapter->RepaintWidget(pNative, &rect);
 }
 
-void CFWL_WidgetMgr::InsertWidget(IFWL_Widget* pParent,
-                                  IFWL_Widget* pChild,
+void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent,
+                                  CFWL_Widget* pChild,
                                   int32_t nIndex) {
   Item* pParentItem = GetWidgetMgrItem(pParent);
   if (!pParentItem) {
@@ -232,7 +232,7 @@
   SetWidgetIndex(pChild, nIndex);
 }
 
-void CFWL_WidgetMgr::RemoveWidget(IFWL_Widget* pWidget) {
+void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
   Item* pItem = GetWidgetMgrItem(pWidget);
   if (!pItem)
     return;
@@ -252,7 +252,7 @@
   m_mapWidgetItem.erase(pWidget);
 }
 
-void CFWL_WidgetMgr::SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned) {
+void CFWL_WidgetMgr::SetOwner(CFWL_Widget* pOwner, CFWL_Widget* pOwned) {
   Item* pParentItem = GetWidgetMgrItem(pOwner);
   if (!pParentItem) {
     auto item = pdfium::MakeUnique<Item>(pOwner);
@@ -271,7 +271,7 @@
   }
   pItem->pOwner = pParentItem;
 }
-void CFWL_WidgetMgr::SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild) {
+void CFWL_WidgetMgr::SetParent(CFWL_Widget* pParent, CFWL_Widget* pChild) {
   Item* pParentItem = GetWidgetMgrItem(pParent);
   Item* pItem = GetWidgetMgrItem(pChild);
   if (!pItem)
@@ -291,7 +291,7 @@
   SetWidgetIndex(pChild, -1);
 }
 
-void CFWL_WidgetMgr::SetWidgetRect_Native(IFWL_Widget* pWidget,
+void CFWL_WidgetMgr::SetWidgetRect_Native(CFWL_Widget* pWidget,
                                           const CFX_RectF& rect) {
   if (!FWL_UseOffscreen(pWidget))
     return;
@@ -313,7 +313,7 @@
 #endif
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(IFWL_Widget* parent,
+CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
                                               FX_FLOAT x,
                                               FX_FLOAT y) {
   if (!parent)
@@ -321,7 +321,7 @@
 
   FX_FLOAT x1;
   FX_FLOAT y1;
-  IFWL_Widget* child = GetLastChildWidget(parent);
+  CFWL_Widget* child = GetLastChildWidget(parent);
   while (child) {
     if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) {
       x1 = x;
@@ -345,18 +345,18 @@
   return parent;
 }
 
-void CFWL_WidgetMgr::NotifySizeChanged(IFWL_Widget* pForm,
+void CFWL_WidgetMgr::NotifySizeChanged(CFWL_Widget* pForm,
                                        FX_FLOAT fx,
                                        FX_FLOAT fy) {
   if (FWL_UseOffscreen(pForm))
     GetWidgetMgrItem(pForm)->pOffscreen.reset();
 }
 
-IFWL_Widget* CFWL_WidgetMgr::NextTab(IFWL_Widget* parent,
-                                     IFWL_Widget* focus,
+CFWL_Widget* CFWL_WidgetMgr::NextTab(CFWL_Widget* parent,
+                                     CFWL_Widget* focus,
                                      bool& bFind) {
   CFWL_WidgetMgr* pMgr = parent->GetOwnerApp()->GetWidgetMgr();
-  IFWL_Widget* child = pMgr->GetFirstChildWidget(parent);
+  CFWL_Widget* child = pMgr->GetFirstChildWidget(parent);
   while (child) {
     if (focus == child)
       bFind = true;
@@ -365,7 +365,7 @@
         (!focus || (focus != child && bFind))) {
       return child;
     }
-    IFWL_Widget* bRet = NextTab(child, focus, bFind);
+    CFWL_Widget* bRet = NextTab(child, focus, bFind);
     if (bRet)
       return bRet;
 
@@ -374,9 +374,9 @@
   return nullptr;
 }
 
-int32_t CFWL_WidgetMgr::CountRadioButtonGroup(IFWL_Widget* pFirst) const {
+int32_t CFWL_WidgetMgr::CountRadioButtonGroup(CFWL_Widget* pFirst) const {
   int32_t iRet = 0;
-  IFWL_Widget* pChild = pFirst;
+  CFWL_Widget* pChild = pFirst;
   while (pChild) {
     pChild = GetNextSiblingWidget(pChild);
     ++iRet;
@@ -384,18 +384,18 @@
   return iRet;
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader(
-    IFWL_Widget* pRadioButton) const {
-  IFWL_Widget* pNext = pRadioButton;
+CFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader(
+    CFWL_Widget* pRadioButton) const {
+  CFWL_Widget* pNext = pRadioButton;
   if (pNext && (pNext->GetStyles() & FWL_WGTSTYLE_Group))
     return pNext;
   return nullptr;
 }
 
 void CFWL_WidgetMgr::GetSameGroupRadioButton(
-    IFWL_Widget* pRadioButton,
-    CFX_ArrayTemplate<IFWL_Widget*>& group) const {
-  IFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton);
+    CFWL_Widget* pRadioButton,
+    CFX_ArrayTemplate<CFWL_Widget*>& group) const {
+  CFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton);
   if (!pFirst)
     pFirst = pRadioButton;
 
@@ -405,20 +405,20 @@
   group.Add(GetRadioButtonGroupHeader(pRadioButton));
 }
 
-IFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(IFWL_Widget* pParent) const {
+CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
   if ((pParent->GetClassID() == FWL_Type::PushButton) &&
       (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
     return pParent;
   }
 
-  IFWL_Widget* child =
+  CFWL_Widget* child =
       pParent->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pParent);
   while (child) {
     if ((child->GetClassID() == FWL_Type::PushButton) &&
         (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
       return child;
     }
-    if (IFWL_Widget* find = GetDefaultButton(child))
+    if (CFWL_Widget* find = GetDefaultButton(child))
       return find;
 
     child = child->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(child);
@@ -426,22 +426,22 @@
   return nullptr;
 }
 
-void CFWL_WidgetMgr::AddRedrawCounts(IFWL_Widget* pWidget) {
+void CFWL_WidgetMgr::AddRedrawCounts(CFWL_Widget* pWidget) {
   GetWidgetMgrItem(pWidget)->iRedrawCounter++;
 }
 
-void CFWL_WidgetMgr::ResetRedrawCounts(IFWL_Widget* pWidget) {
+void CFWL_WidgetMgr::ResetRedrawCounts(CFWL_Widget* pWidget) {
   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
 }
 
 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
-    IFWL_Widget* pWidget) const {
+    CFWL_Widget* pWidget) const {
   auto it = m_mapWidgetItem.find(pWidget);
   return it != m_mapWidgetItem.end() ? static_cast<Item*>(it->second.get())
                                      : nullptr;
 }
 
-bool CFWL_WidgetMgr::IsAbleNative(IFWL_Widget* pWidget) const {
+bool CFWL_WidgetMgr::IsAbleNative(CFWL_Widget* pWidget) const {
   if (!pWidget)
     return false;
   if (!pWidget->IsInstance(FX_WSTRC(FWL_CLASS_Form)))
@@ -453,7 +453,7 @@
          (dwStyles & FWL_WGTSTYLE_Popup);
 }
 
-void CFWL_WidgetMgr::GetAdapterPopupPos(IFWL_Widget* pWidget,
+void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
                                         FX_FLOAT fMinHeight,
                                         FX_FLOAT fMaxHeight,
                                         const CFX_RectF& rtAnchor,
@@ -471,7 +471,7 @@
   if (!pMessage->m_pDstTarget)
     return;
 
-  IFWL_Widget* pDstWidget = pMessage->m_pDstTarget;
+  CFWL_Widget* pDstWidget = pMessage->m_pDstTarget;
   const CFWL_App* pApp = pDstWidget->GetOwnerApp();
   if (!pApp)
     return;
@@ -494,7 +494,7 @@
 #endif
 }
 
-void CFWL_WidgetMgr::OnDrawWidget(IFWL_Widget* pWidget,
+void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
                                   CFX_Graphics* pGraphics,
                                   const CFX_Matrix* pMatrix) {
   if (!pWidget || !pGraphics)
@@ -540,7 +540,7 @@
   ResetRedrawCounts(pWidget);
 }
 
-void CFWL_WidgetMgr::DrawChild(IFWL_Widget* parent,
+void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent,
                                const CFX_RectF& rtClip,
                                CFX_Graphics* pGraphics,
                                const CFX_Matrix* pMatrix) {
@@ -548,9 +548,9 @@
     return;
 
   bool bFormDisable = IsFormDisabled();
-  IFWL_Widget* pNextChild = GetFirstChildWidget(parent);
+  CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
   while (pNextChild) {
-    IFWL_Widget* child = pNextChild;
+    CFWL_Widget* child = pNextChild;
     pNextChild = GetNextSiblingWidget(child);
     if (child->GetStates() & FWL_WGTSTATE_Invisible)
       continue;
@@ -591,7 +591,7 @@
   }
 }
 
-CFX_Graphics* CFWL_WidgetMgr::DrawWidgetBefore(IFWL_Widget* pWidget,
+CFX_Graphics* CFWL_WidgetMgr::DrawWidgetBefore(CFWL_Widget* pWidget,
                                                CFX_Graphics* pGraphics,
                                                const CFX_Matrix* pMatrix) {
   if (!FWL_UseOffscreen(pWidget))
@@ -611,7 +611,7 @@
   return pItem->pOffscreen.get();
 }
 
-void CFWL_WidgetMgr::DrawWidgetAfter(IFWL_Widget* pWidget,
+void CFWL_WidgetMgr::DrawWidgetAfter(CFWL_Widget* pWidget,
                                      CFX_Graphics* pGraphics,
                                      CFX_RectF& rtClip,
                                      const CFX_Matrix* pMatrix) {
@@ -627,7 +627,7 @@
   pItem->iRedrawCounter = 0;
 }
 
-bool CFWL_WidgetMgr::IsNeedRepaint(IFWL_Widget* pWidget,
+bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget,
                                    CFX_Matrix* pMatrix,
                                    const CFX_RectF& rtDirty) {
   Item* pItem = GetWidgetMgrItem(pWidget);
@@ -643,7 +643,7 @@
   if (!rtWidget.IntersectWith(rtDirty))
     return false;
 
-  IFWL_Widget* pChild =
+  CFWL_Widget* pChild =
       pWidget->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pWidget);
   if (!pChild)
     return true;
@@ -727,7 +727,7 @@
   return true;
 }
 
-bool CFWL_WidgetMgr::UseOffscreenDirect(IFWL_Widget* pWidget) const {
+bool CFWL_WidgetMgr::UseOffscreenDirect(CFWL_Widget* pWidget) const {
   Item* pItem = GetWidgetMgrItem(pWidget);
   if (!FWL_UseOffscreen(pWidget) || !(pItem->pOffscreen))
     return false;
@@ -750,7 +750,7 @@
 
 CFWL_WidgetMgr::Item::Item() : CFWL_WidgetMgr::Item(nullptr) {}
 
-CFWL_WidgetMgr::Item::Item(IFWL_Widget* widget)
+CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget)
     : pParent(nullptr),
       pOwner(nullptr),
       pChild(nullptr),
diff --git a/xfa/fwl/core/cfwl_widgetmgr.h b/xfa/fwl/core/cfwl_widgetmgr.h
index 0c6a184..70d8b7e 100644
--- a/xfa/fwl/core/cfwl_widgetmgr.h
+++ b/xfa/fwl/core/cfwl_widgetmgr.h
@@ -22,53 +22,53 @@
 class CXFA_FWLAdapterWidgetMgr;
 class CFX_Graphics;
 class CFX_Matrix;
-class IFWL_Widget;
+class CFWL_Widget;
 
-class CFWL_WidgetMgr : public IFWL_WidgetMgrDelegate {
+class CFWL_WidgetMgr : public CFWL_WidgetMgrDelegate {
  public:
   explicit CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative);
   ~CFWL_WidgetMgr();
 
-  // IFWL_WidgetMgrDelegate
+  // CFWL_WidgetMgrDelegate
   void OnSetCapability(uint32_t dwCapability) override;
   void OnProcessMessageToForm(CFWL_Message* pMessage) override;
-  void OnDrawWidget(IFWL_Widget* pWidget,
+  void OnDrawWidget(CFWL_Widget* pWidget,
                     CFX_Graphics* pGraphics,
                     const CFX_Matrix* pMatrix) override;
 
-  IFWL_Widget* GetParentWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetOwnerWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetNextSiblingWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetFirstChildWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetSystemFormWidget(IFWL_Widget* pWidget) const;
+  CFWL_Widget* GetParentWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetOwnerWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetNextSiblingWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetFirstChildWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetSystemFormWidget(CFWL_Widget* pWidget) const;
 
-  void RepaintWidget(IFWL_Widget* pWidget, const CFX_RectF* pRect = nullptr);
+  void RepaintWidget(CFWL_Widget* pWidget, const CFX_RectF* pRect = nullptr);
 
-  void InsertWidget(IFWL_Widget* pParent,
-                    IFWL_Widget* pChild,
+  void InsertWidget(CFWL_Widget* pParent,
+                    CFWL_Widget* pChild,
                     int32_t nIndex = -1);
-  void RemoveWidget(IFWL_Widget* pWidget);
-  void SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned);
-  void SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild);
+  void RemoveWidget(CFWL_Widget* pWidget);
+  void SetOwner(CFWL_Widget* pOwner, CFWL_Widget* pOwned);
+  void SetParent(CFWL_Widget* pParent, CFWL_Widget* pChild);
 
-  void SetWidgetRect_Native(IFWL_Widget* pWidget, const CFX_RectF& rect);
+  void SetWidgetRect_Native(CFWL_Widget* pWidget, const CFX_RectF& rect);
 
-  IFWL_Widget* GetWidgetAtPoint(IFWL_Widget* pParent, FX_FLOAT fx, FX_FLOAT fy);
+  CFWL_Widget* GetWidgetAtPoint(CFWL_Widget* pParent, FX_FLOAT fx, FX_FLOAT fy);
 
-  void NotifySizeChanged(IFWL_Widget* pForm, FX_FLOAT fx, FX_FLOAT fy);
+  void NotifySizeChanged(CFWL_Widget* pForm, FX_FLOAT fx, FX_FLOAT fy);
 
-  IFWL_Widget* NextTab(IFWL_Widget* parent, IFWL_Widget* focus, bool& bFind);
+  CFWL_Widget* NextTab(CFWL_Widget* parent, CFWL_Widget* focus, bool& bFind);
 
-  void GetSameGroupRadioButton(IFWL_Widget* pRadioButton,
-                               CFX_ArrayTemplate<IFWL_Widget*>& group) const;
-  IFWL_Widget* GetDefaultButton(IFWL_Widget* pParent) const;
-  void AddRedrawCounts(IFWL_Widget* pWidget);
+  void GetSameGroupRadioButton(CFWL_Widget* pRadioButton,
+                               CFX_ArrayTemplate<CFWL_Widget*>& group) const;
+  CFWL_Widget* GetDefaultButton(CFWL_Widget* pParent) const;
+  void AddRedrawCounts(CFWL_Widget* pWidget);
 
   bool IsFormDisabled() const {
     return !!(m_dwCapability & FWL_WGTMGR_DisableForm);
   }
 
-  void GetAdapterPopupPos(IFWL_Widget* pWidget,
+  void GetAdapterPopupPos(CFWL_Widget* pWidget,
                           FX_FLOAT fMinHeight,
                           FX_FLOAT fMaxHeight,
                           const CFX_RectF& rtAnchor,
@@ -78,7 +78,7 @@
   class Item {
    public:
     Item();
-    explicit Item(IFWL_Widget* widget);
+    explicit Item(CFWL_Widget* widget);
     ~Item();
 
     Item* pParent;
@@ -86,7 +86,7 @@
     Item* pChild;
     Item* pPrevious;
     Item* pNext;
-    IFWL_Widget* const pWidget;
+    CFWL_Widget* const pWidget;
     std::unique_ptr<CFX_Graphics> pOffscreen;
     int32_t iRedrawCounter;
 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
@@ -94,38 +94,38 @@
 #endif
   };
 
-  IFWL_Widget* GetFirstSiblingWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetPriorSiblingWidget(IFWL_Widget* pWidget) const;
-  IFWL_Widget* GetLastChildWidget(IFWL_Widget* pWidget) const;
-  Item* GetWidgetMgrItem(IFWL_Widget* pWidget) const;
+  CFWL_Widget* GetFirstSiblingWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetPriorSiblingWidget(CFWL_Widget* pWidget) const;
+  CFWL_Widget* GetLastChildWidget(CFWL_Widget* pWidget) const;
+  Item* GetWidgetMgrItem(CFWL_Widget* pWidget) const;
 
-  void SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex);
+  void SetWidgetIndex(CFWL_Widget* pWidget, int32_t nIndex);
 
-  int32_t CountRadioButtonGroup(IFWL_Widget* pFirst) const;
-  IFWL_Widget* GetRadioButtonGroupHeader(IFWL_Widget* pRadioButton) const;
+  int32_t CountRadioButtonGroup(CFWL_Widget* pFirst) const;
+  CFWL_Widget* GetRadioButtonGroupHeader(CFWL_Widget* pRadioButton) const;
 
-  void ResetRedrawCounts(IFWL_Widget* pWidget);
+  void ResetRedrawCounts(CFWL_Widget* pWidget);
 
-  void DrawChild(IFWL_Widget* pParent,
+  void DrawChild(CFWL_Widget* pParent,
                  const CFX_RectF& rtClip,
                  CFX_Graphics* pGraphics,
                  const CFX_Matrix* pMatrix);
-  CFX_Graphics* DrawWidgetBefore(IFWL_Widget* pWidget,
+  CFX_Graphics* DrawWidgetBefore(CFWL_Widget* pWidget,
                                  CFX_Graphics* pGraphics,
                                  const CFX_Matrix* pMatrix);
-  void DrawWidgetAfter(IFWL_Widget* pWidget,
+  void DrawWidgetAfter(CFWL_Widget* pWidget,
                        CFX_Graphics* pGraphics,
                        CFX_RectF& rtClip,
                        const CFX_Matrix* pMatrix);
-  bool IsNeedRepaint(IFWL_Widget* pWidget,
+  bool IsNeedRepaint(CFWL_Widget* pWidget,
                      CFX_Matrix* pMatrix,
                      const CFX_RectF& rtDirty);
-  bool UseOffscreenDirect(IFWL_Widget* pWidget) const;
+  bool UseOffscreenDirect(CFWL_Widget* pWidget) const;
 
-  bool IsAbleNative(IFWL_Widget* pWidget) const;
+  bool IsAbleNative(CFWL_Widget* pWidget) const;
 
   uint32_t m_dwCapability;
-  std::map<IFWL_Widget*, std::unique_ptr<Item>> m_mapWidgetItem;
+  std::map<CFWL_Widget*, std::unique_ptr<Item>> m_mapWidgetItem;
   CXFA_FWLAdapterWidgetMgr* const m_pAdapter;
 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
   CFX_RectF m_rtScreen;
diff --git a/xfa/fwl/core/cfwl_widgetproperties.h b/xfa/fwl/core/cfwl_widgetproperties.h
index c8746f5..d7bf72e 100644
--- a/xfa/fwl/core/cfwl_widgetproperties.h
+++ b/xfa/fwl/core/cfwl_widgetproperties.h
@@ -9,11 +9,11 @@
 
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_system.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/fwl_widgetdef.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 
 class IFWL_ThemeProvider;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CFWL_WidgetProperties {
  public:
@@ -25,8 +25,8 @@
   uint32_t m_dwStyleExes;
   uint32_t m_dwStates;
   IFWL_ThemeProvider* m_pThemeProvider;
-  IFWL_Widget* m_pParent;
-  IFWL_Widget* m_pOwner;
+  CFWL_Widget* m_pParent;
+  CFWL_Widget* m_pOwner;
 };
 
 #endif  // XFA_FWL_CORE_CFWL_WIDGETPROPERTIES_H_
diff --git a/xfa/fwl/core/ifwl_barcode.cpp b/xfa/fwl/core/ifwl_barcode.cpp
deleted file mode 100644
index b4cd13a..0000000
--- a/xfa/fwl/core/ifwl_barcode.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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/core/ifwl_barcode.h"
-
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fgas/font/cfgas_gefont.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfx_barcode.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-IFWL_Barcode::IFWL_Barcode(const CFWL_App* app,
-                           std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Edit(app, std::move(properties), nullptr),
-      m_dwStatus(0),
-      m_type(BC_UNKNOWN) {}
-
-IFWL_Barcode::~IFWL_Barcode() {}
-
-FWL_Type IFWL_Barcode::GetClassID() const {
-  return FWL_Type::Barcode;
-}
-
-void IFWL_Barcode::Update() {
-  if (IsLocked())
-    return;
-
-  IFWL_Edit::Update();
-  GenerateBarcodeImageCache();
-}
-
-void IFWL_Barcode::DrawWidget(CFX_Graphics* pGraphics,
-                              const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) {
-    GenerateBarcodeImageCache();
-    if (!m_pBarcodeEngine || (m_dwStatus & XFA_BCS_EncodeSuccess) == 0)
-      return;
-
-    CFX_Matrix mt;
-    mt.e = GetRTClient().left;
-    mt.f = GetRTClient().top;
-    if (pMatrix)
-      mt.Concat(*pMatrix);
-
-    int32_t errorCode = 0;
-    m_pBarcodeEngine->RenderDevice(pGraphics->GetRenderDevice(), pMatrix,
-                                   errorCode);
-    return;
-  }
-  IFWL_Edit::DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_Barcode::GenerateBarcodeImageCache() {
-  if ((m_dwStatus & XFA_BCS_NeedUpdate) == 0)
-    return;
-
-  m_dwStatus = 0;
-  CreateBarcodeEngine();
-  if (!m_pBarcodeEngine)
-    return;
-
-  CFX_WideString wsText;
-  GetText(wsText);
-
-  CFWL_ThemePart part;
-  part.m_pWidget = this;
-
-  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
-  CFGAS_GEFont* pFont = static_cast<CFGAS_GEFont*>(
-      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::Font));
-  CFX_Font* pCXFont = pFont ? pFont->GetDevFont() : nullptr;
-  if (pCXFont)
-    m_pBarcodeEngine->SetFont(pCXFont);
-
-  FX_FLOAT* pFontSize = static_cast<FX_FLOAT*>(
-      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::FontSize));
-  if (pFontSize)
-    m_pBarcodeEngine->SetFontSize(*pFontSize);
-
-  FX_ARGB* pFontColor = static_cast<FX_ARGB*>(
-      pTheme->GetCapacity(&part, CFWL_WidgetCapacity::TextColor));
-  if (pFontColor)
-    m_pBarcodeEngine->SetFontColor(*pFontColor);
-
-  m_pBarcodeEngine->SetHeight(int32_t(GetRTClient().height));
-  m_pBarcodeEngine->SetWidth(int32_t(GetRTClient().width));
-  uint32_t dwAttributeMask = m_pDataProvider->GetBarcodeAttributeMask();
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_CHARENCODING)
-    m_pBarcodeEngine->SetCharEncoding(m_pDataProvider->GetCharEncoding());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_MODULEHEIGHT)
-    m_pBarcodeEngine->SetModuleHeight(m_pDataProvider->GetModuleHeight());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_MODULEWIDTH)
-    m_pBarcodeEngine->SetModuleWidth(m_pDataProvider->GetModuleWidth());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_DATALENGTH)
-    m_pBarcodeEngine->SetDataLength(m_pDataProvider->GetDataLength());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_CALCHECKSUM)
-    m_pBarcodeEngine->SetCalChecksum(m_pDataProvider->GetCalChecksum());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_PRINTCHECKSUM)
-    m_pBarcodeEngine->SetPrintChecksum(m_pDataProvider->GetPrintChecksum());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_TEXTLOCATION)
-    m_pBarcodeEngine->SetTextLocation(m_pDataProvider->GetTextLocation());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_WIDENARROWRATIO)
-    m_pBarcodeEngine->SetWideNarrowRatio(m_pDataProvider->GetWideNarrowRatio());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_STARTCHAR)
-    m_pBarcodeEngine->SetStartChar(m_pDataProvider->GetStartChar());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_ENDCHAR)
-    m_pBarcodeEngine->SetEndChar(m_pDataProvider->GetEndChar());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_VERSION)
-    m_pBarcodeEngine->SetVersion(m_pDataProvider->GetVersion());
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_ECLEVEL) {
-    m_pBarcodeEngine->SetErrorCorrectionLevel(
-        m_pDataProvider->GetErrorCorrectionLevel());
-  }
-  if (dwAttributeMask & FWL_BCDATTRIBUTE_TRUNCATED)
-    m_pBarcodeEngine->SetTruncated(m_pDataProvider->GetTruncated());
-
-  int32_t errorCode = 0;
-  m_dwStatus = m_pBarcodeEngine->Encode(wsText.AsStringC(), true, errorCode)
-                   ? XFA_BCS_EncodeSuccess
-                   : 0;
-}
-
-void IFWL_Barcode::CreateBarcodeEngine() {
-  if (m_pBarcodeEngine || m_type == BC_UNKNOWN)
-    return;
-
-  std::unique_ptr<CFX_Barcode> pBarcode(new CFX_Barcode);
-  if (pBarcode->Create(m_type))
-    m_pBarcodeEngine = std::move(pBarcode);
-}
-
-void IFWL_Barcode::SetType(BC_TYPE type) {
-  if (m_type == type)
-    return;
-
-  m_pBarcodeEngine.reset();
-  m_type = type;
-  m_dwStatus = XFA_BCS_NeedUpdate;
-}
-
-void IFWL_Barcode::SetText(const CFX_WideString& wsText) {
-  m_pBarcodeEngine.reset();
-  m_dwStatus = XFA_BCS_NeedUpdate;
-  IFWL_Edit::SetText(wsText);
-}
-
-bool IFWL_Barcode::IsProtectedType() const {
-  if (!m_pBarcodeEngine)
-    return true;
-
-  BC_TYPE tEngineType = m_pBarcodeEngine->GetType();
-  if (tEngineType == BC_QR_CODE || tEngineType == BC_PDF417 ||
-      tEngineType == BC_DATAMATRIX) {
-    return true;
-  }
-  return false;
-}
-
-void IFWL_Barcode::OnProcessEvent(CFWL_Event* pEvent) {
-  if (pEvent->GetClassID() == CFWL_EventType::TextChanged) {
-    m_pBarcodeEngine.reset();
-    m_dwStatus = XFA_BCS_NeedUpdate;
-  }
-  IFWL_Edit::OnProcessEvent(pEvent);
-}
diff --git a/xfa/fwl/core/ifwl_barcode.h b/xfa/fwl/core/ifwl_barcode.h
deleted file mode 100644
index 38f798f..0000000
--- a/xfa/fwl/core/ifwl_barcode.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_BARCODE_H_
-#define XFA_FWL_CORE_IFWL_BARCODE_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_scrollbar.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-#include "xfa/fxbarcode/BC_Library.h"
-
-class CFWL_WidgetProperties;
-class CFX_Barcode;
-class IFWL_Widget;
-
-#define XFA_BCS_NeedUpdate 0x0001
-#define XFA_BCS_EncodeSuccess 0x0002
-
-enum FWL_BCDAttribute {
-  FWL_BCDATTRIBUTE_NONE = 0,
-  FWL_BCDATTRIBUTE_CHARENCODING = 1 << 0,
-  FWL_BCDATTRIBUTE_MODULEHEIGHT = 1 << 1,
-  FWL_BCDATTRIBUTE_MODULEWIDTH = 1 << 2,
-  FWL_BCDATTRIBUTE_DATALENGTH = 1 << 3,
-  FWL_BCDATTRIBUTE_CALCHECKSUM = 1 << 4,
-  FWL_BCDATTRIBUTE_PRINTCHECKSUM = 1 << 5,
-  FWL_BCDATTRIBUTE_TEXTLOCATION = 1 << 6,
-  FWL_BCDATTRIBUTE_WIDENARROWRATIO = 1 << 7,
-  FWL_BCDATTRIBUTE_STARTCHAR = 1 << 8,
-  FWL_BCDATTRIBUTE_ENDCHAR = 1 << 9,
-  FWL_BCDATTRIBUTE_VERSION = 1 << 10,
-  FWL_BCDATTRIBUTE_ECLEVEL = 1 << 11,
-  FWL_BCDATTRIBUTE_TRUNCATED = 1 << 12
-};
-
-class IFWL_Barcode : public IFWL_Edit {
- public:
-  class DataProvider {
-   public:
-    virtual BC_CHAR_ENCODING GetCharEncoding() const = 0;
-    virtual int32_t GetModuleHeight() const = 0;
-    virtual int32_t GetModuleWidth() const = 0;
-    virtual int32_t GetDataLength() const = 0;
-    virtual bool GetCalChecksum() const = 0;
-    virtual bool GetPrintChecksum() const = 0;
-    virtual BC_TEXT_LOC GetTextLocation() const = 0;
-    virtual int32_t GetWideNarrowRatio() const = 0;
-    virtual FX_CHAR GetStartChar() const = 0;
-    virtual FX_CHAR GetEndChar() const = 0;
-    virtual int32_t GetVersion() const = 0;
-    virtual int32_t GetErrorCorrectionLevel() const = 0;
-    virtual bool GetTruncated() const = 0;
-    virtual uint32_t GetBarcodeAttributeMask() const = 0;
-  };
-
-  IFWL_Barcode(const CFWL_App* app,
-               std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_Barcode() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void Update() override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void OnProcessEvent(CFWL_Event* pEvent) override;
-
-  // IFWL_Edit
-  void SetText(const CFX_WideString& wsText) override;
-
-  void SetType(BC_TYPE type);
-  bool IsProtectedType() const;
-
-  void SetDataProvider(IFWL_Barcode::DataProvider* provider) {
-    m_pDataProvider = provider;
-  }
-
- private:
-  void GenerateBarcodeImageCache();
-  void CreateBarcodeEngine();
-
-  std::unique_ptr<CFX_Barcode> m_pBarcodeEngine;
-  IFWL_Barcode::DataProvider* m_pDataProvider;  // Not owned.
-  uint32_t m_dwStatus;
-  BC_TYPE m_type;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_BARCODE_H_
diff --git a/xfa/fwl/core/ifwl_checkbox.cpp b/xfa/fwl/core/ifwl_checkbox.cpp
deleted file mode 100644
index b33eaa6..0000000
--- a/xfa/fwl/core/ifwl_checkbox.cpp
+++ /dev/null
@@ -1,483 +0,0 @@
-// 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/core/ifwl_checkbox.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fde/tto/fde_textout.h"
-#include "xfa/fwl/core/cfwl_app.h"
-#include "xfa/fwl/core/cfwl_evtcheckstatechanged.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-namespace {
-
-const int kCaptionMargin = 5;
-
-}  // namespace
-
-IFWL_CheckBox::IFWL_CheckBox(const CFWL_App* app,
-                             std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr),
-      m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
-      m_iTTOAlign(FDE_TTOALIGNMENT_Center),
-      m_bBtnDown(false) {
-  m_rtClient.Reset();
-  m_rtBox.Reset();
-  m_rtCaption.Reset();
-  m_rtFocus.Reset();
-}
-
-IFWL_CheckBox::~IFWL_CheckBox() {}
-
-FWL_Type IFWL_CheckBox::GetClassID() const {
-  return FWL_Type::CheckBox;
-}
-
-void IFWL_CheckBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Set(0, 0, 0, 0);
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  CFX_SizeF sz = CalcTextSize(
-      L"Check box", m_pProperties->m_pThemeProvider,
-      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine));
-  rect.Set(0, 0, sz.x, sz.y);
-  rect.Inflate(kCaptionMargin, kCaptionMargin);
-
-  FX_FLOAT fCheckBox = m_pDataProvider->GetBoxSize(this);
-  rect.width += fCheckBox;
-  rect.height = std::max(rect.height, fCheckBox);
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_CheckBox::Update() {
-  if (IsLocked())
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  UpdateTextOutStyles();
-  Layout();
-}
-
-void IFWL_CheckBox::DrawWidget(CFX_Graphics* pGraphics,
-                               const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  if (HasBorder()) {
-    DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
-               pMatrix);
-  }
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-
-  int32_t dwStates = GetPartStates();
-
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = CFWL_Part::Background;
-  param.m_dwStates = dwStates;
-  param.m_pGraphics = pGraphics;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix);
-  param.m_rtPart = m_rtClient;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-    param.m_pData = &m_rtFocus;
-  pTheme->DrawBackground(&param);
-
-  param.m_iPart = CFWL_Part::CheckBox;
-  param.m_rtPart = m_rtBox;
-  pTheme->DrawBackground(&param);
-
-  CFWL_ThemeText textParam;
-  textParam.m_pWidget = this;
-  textParam.m_iPart = CFWL_Part::Caption;
-  textParam.m_dwStates = dwStates;
-  textParam.m_pGraphics = pGraphics;
-  if (pMatrix)
-    textParam.m_matrix.Concat(*pMatrix);
-  textParam.m_rtPart = m_rtCaption;
-  textParam.m_wsText = L"Check box";
-  textParam.m_dwTTOStyles = m_dwTTOStyles;
-  textParam.m_iTTOAlign = m_iTTOAlign;
-  pTheme->DrawText(&textParam);
-}
-
-void IFWL_CheckBox::SetCheckState(int32_t iCheck) {
-  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
-  switch (iCheck) {
-    case 1:
-      m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
-      break;
-    case 2:
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;
-      break;
-    default:
-      break;
-  }
-  Repaint(&m_rtClient);
-}
-
-void IFWL_CheckBox::Layout() {
-  m_pProperties->m_rtWidget.width =
-      FXSYS_round(m_pProperties->m_rtWidget.width);
-  m_pProperties->m_rtWidget.height =
-      FXSYS_round(m_pProperties->m_rtWidget.height);
-  GetClientRect(m_rtClient);
-
-  FX_FLOAT fBoxTop = m_rtClient.top;
-  FX_FLOAT fClientBottom = m_rtClient.bottom();
-
-  FX_FLOAT fCheckBox = m_pDataProvider->GetBoxSize(this);
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) {
-    case FWL_STYLEEXT_CKB_Top:
-      break;
-    case FWL_STYLEEXT_CKB_Bottom: {
-      fBoxTop = fClientBottom - fCheckBox;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_VCenter:
-    default: {
-      fBoxTop = m_rtClient.top + (m_rtClient.height - fCheckBox) / 2;
-      fBoxTop = FXSYS_floor(fBoxTop);
-      break;
-    }
-  }
-
-  FX_FLOAT fBoxLeft = m_rtClient.left;
-  FX_FLOAT fTextLeft = 0.0;
-  FX_FLOAT fTextRight = 0.0;
-  FX_FLOAT fClientRight = m_rtClient.right();
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_LeftText) {
-    fBoxLeft = fClientRight - fCheckBox;
-    fTextLeft = m_rtClient.left;
-    fTextRight = fBoxLeft;
-  } else {
-    fTextLeft = fBoxLeft + fCheckBox;
-    fTextRight = fClientRight;
-  }
-  m_rtBox.Set(fBoxLeft, fBoxTop, fCheckBox, fCheckBox);
-  m_rtCaption.Set(fTextLeft, m_rtClient.top, fTextRight - fTextLeft,
-                  m_rtClient.height);
-  m_rtCaption.Inflate(-kCaptionMargin, -kCaptionMargin);
-
-  CFX_RectF rtFocus;
-  rtFocus.Set(m_rtCaption.left, m_rtCaption.top, m_rtCaption.width,
-              m_rtCaption.height);
-
-  CalcTextRect(L"Check box", m_pProperties->m_pThemeProvider, m_dwTTOStyles,
-               m_iTTOAlign, rtFocus);
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine) == 0) {
-    FX_FLOAT fWidth = std::max(m_rtCaption.width, rtFocus.width);
-    FX_FLOAT fHeight = std::min(m_rtCaption.height, rtFocus.height);
-    FX_FLOAT fLeft = m_rtCaption.left;
-    FX_FLOAT fTop = m_rtCaption.top;
-    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) ==
-        FWL_STYLEEXT_CKB_Center) {
-      fLeft = m_rtCaption.left + (m_rtCaption.width - fWidth) / 2;
-    } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_HLayoutMask) ==
-               FWL_STYLEEXT_CKB_Right) {
-      fLeft = m_rtCaption.right() - fWidth;
-    }
-    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) ==
-        FWL_STYLEEXT_CKB_VCenter) {
-      fTop = m_rtCaption.top + (m_rtCaption.height - fHeight) / 2;
-    } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_VLayoutMask) ==
-               FWL_STYLEEXT_CKB_Bottom) {
-      fTop = m_rtCaption.bottom() - fHeight;
-    }
-    m_rtFocus.Set(fLeft, fTop, fWidth, fHeight);
-  } else {
-    m_rtFocus.Set(rtFocus.left, rtFocus.top, rtFocus.width, rtFocus.height);
-  }
-  m_rtFocus.Inflate(1, 1);
-}
-
-uint32_t IFWL_CheckBox::GetPartStates() const {
-  int32_t dwStates = CFWL_PartState_Normal;
-  if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
-      FWL_STATE_CKB_Neutral) {
-    dwStates = CFWL_PartState_Neutral;
-  } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
-             FWL_STATE_CKB_Checked) {
-    dwStates = CFWL_PartState_Checked;
-  }
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    dwStates |= CFWL_PartState_Disabled;
-  else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)
-    dwStates |= CFWL_PartState_Hovered;
-  else if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed)
-    dwStates |= CFWL_PartState_Pressed;
-  else
-    dwStates |= CFWL_PartState_Normal;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-    dwStates |= CFWL_PartState_Focused;
-  return dwStates;
-}
-
-void IFWL_CheckBox::UpdateTextOutStyles() {
-  switch (m_pProperties->m_dwStyleExes &
-          (FWL_STYLEEXT_CKB_HLayoutMask | FWL_STYLEEXT_CKB_VLayoutMask)) {
-    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_VCenter: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_VCenter: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Left | FWL_STYLEEXT_CKB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Right | FWL_STYLEEXT_CKB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;
-      break;
-    }
-    case FWL_STYLEEXT_CKB_Center | FWL_STYLEEXT_CKB_VCenter:
-    default: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_Center;
-      break;
-    }
-  }
-  m_dwTTOStyles = 0;
-  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
-    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_MultiLine)
-    m_dwTTOStyles |= FDE_TTOSTYLE_LineWrap;
-  else
-    m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;
-}
-
-void IFWL_CheckBox::NextStates() {
-  uint32_t dwFirststate = m_pProperties->m_dwStates;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_RadioButton) {
-    if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
-        FWL_STATE_CKB_Unchecked) {
-      CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
-      if (!pWidgetMgr->IsFormDisabled()) {
-        CFX_ArrayTemplate<IFWL_Widget*> radioarr;
-        pWidgetMgr->GetSameGroupRadioButton(this, radioarr);
-        IFWL_CheckBox* pCheckBox = nullptr;
-        int32_t iCount = radioarr.GetSize();
-        for (int32_t i = 0; i < iCount; i++) {
-          pCheckBox = static_cast<IFWL_CheckBox*>(radioarr[i]);
-          if (pCheckBox != this &&
-              pCheckBox->GetStates() & FWL_STATE_CKB_Checked) {
-            pCheckBox->SetCheckState(0);
-            CFX_RectF rt;
-            pCheckBox->GetWidgetRect(rt);
-            rt.left = rt.top = 0;
-            m_pWidgetMgr->RepaintWidget(pCheckBox, &rt);
-            break;
-          }
-        }
-      }
-      m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
-    }
-  } else {
-    if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
-        FWL_STATE_CKB_Neutral) {
-      m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
-    } else if ((m_pProperties->m_dwStates & FWL_STATE_CKB_CheckMask) ==
-               FWL_STATE_CKB_Checked) {
-      m_pProperties->m_dwStates &= ~FWL_STATE_CKB_CheckMask;
-    } else {
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CKB_3State)
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Neutral;
-      else
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Checked;
-    }
-  }
-
-  Repaint(&m_rtClient);
-  if (dwFirststate == m_pProperties->m_dwStates)
-    return;
-
-  CFWL_EvtCheckStateChanged wmCheckBoxState;
-  wmCheckBoxState.m_pSrcTarget = this;
-  DispatchEvent(&wmCheckBoxState);
-}
-
-void IFWL_CheckBox::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-
-  switch (pMessage->GetClassID()) {
-    case CFWL_MessageType::SetFocus:
-      OnFocusChanged(true);
-      break;
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(false);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown();
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        case FWL_MouseCommand::Move:
-          OnMouseMove(pMsg);
-          break;
-        case FWL_MouseCommand::Leave:
-          OnMouseLeave();
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
-      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
-        OnKeyDown(pKey);
-      break;
-    }
-    default:
-      break;
-  }
-
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_CheckBox::OnDrawWidget(CFX_Graphics* pGraphics,
-                                 const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_CheckBox::OnFocusChanged(bool bSet) {
-  if (bSet)
-    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
-  else
-    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
-
-  Repaint(&m_rtClient);
-}
-
-void IFWL_CheckBox::OnLButtonDown() {
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    return;
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    SetFocus(true);
-
-  m_bBtnDown = true;
-  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
-  m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;
-  Repaint(&m_rtClient);
-}
-
-void IFWL_CheckBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  if (!m_bBtnDown)
-    return;
-
-  m_bBtnDown = false;
-  if (!m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy))
-    return;
-
-  m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
-  m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;
-  NextStates();
-}
-
-void IFWL_CheckBox::OnMouseMove(CFWL_MsgMouse* pMsg) {
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    return;
-
-  bool bRepaint = false;
-  if (m_bBtnDown) {
-    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
-      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) == 0) {
-        bRepaint = true;
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Pressed;
-      }
-      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered)) {
-        bRepaint = true;
-        m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
-      }
-    } else {
-      if (m_pProperties->m_dwStates & FWL_STATE_CKB_Pressed) {
-        bRepaint = true;
-        m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Pressed;
-      }
-      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {
-        bRepaint = true;
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
-      }
-    }
-  } else {
-    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
-      if ((m_pProperties->m_dwStates & FWL_STATE_CKB_Hovered) == 0) {
-        bRepaint = true;
-        m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
-      }
-    }
-  }
-  if (bRepaint)
-    Repaint(&m_rtBox);
-}
-
-void IFWL_CheckBox::OnMouseLeave() {
-  if (m_bBtnDown)
-    m_pProperties->m_dwStates |= FWL_STATE_CKB_Hovered;
-  else
-    m_pProperties->m_dwStates &= ~FWL_STATE_CKB_Hovered;
-
-  Repaint(&m_rtBox);
-}
-
-void IFWL_CheckBox::OnKeyDown(CFWL_MsgKey* pMsg) {
-  if (pMsg->m_dwKeyCode == FWL_VKEY_Tab) {
-    DispatchKeyEvent(pMsg);
-    return;
-  }
-  if (pMsg->m_dwKeyCode == FWL_VKEY_Return ||
-      pMsg->m_dwKeyCode == FWL_VKEY_Space) {
-    NextStates();
-  }
-}
diff --git a/xfa/fwl/core/ifwl_checkbox.h b/xfa/fwl/core/ifwl_checkbox.h
deleted file mode 100644
index 3a5b83c..0000000
--- a/xfa/fwl/core/ifwl_checkbox.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_CHECKBOX_H_
-#define XFA_FWL_CORE_IFWL_CHECKBOX_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-
-#define FWL_STYLEEXT_CKB_Left (0L << 0)
-#define FWL_STYLEEXT_CKB_Center (1L << 0)
-#define FWL_STYLEEXT_CKB_Right (2L << 0)
-#define FWL_STYLEEXT_CKB_Top (0L << 2)
-#define FWL_STYLEEXT_CKB_VCenter (1L << 2)
-#define FWL_STYLEEXT_CKB_Bottom (2L << 2)
-#define FWL_STYLEEXT_CKB_LeftText (1L << 4)
-#define FWL_STYLEEXT_CKB_MultiLine (1L << 5)
-#define FWL_STYLEEXT_CKB_3State (1L << 6)
-#define FWL_STYLEEXT_CKB_RadioButton (1L << 7)
-#define FWL_STYLEEXT_CKB_ShapeSolidSquare (0L << 8)
-#define FWL_STYLEEXT_CKB_ShapeSunkenSquare (1L << 8)
-#define FWL_STYLEEXT_CKB_ShapeSolidCircle (2L << 8)
-#define FWL_STYLEEXT_CKB_ShapeSunkenCircle (3L << 8)
-#define FWL_STYLEEXT_CKB_SignShapeCheck (0L << 10)
-#define FWL_STYLEEXT_CKB_SignShapeCircle (1L << 10)
-#define FWL_STYLEEXT_CKB_SignShapeCross (2L << 10)
-#define FWL_STYLEEXT_CKB_SignShapeDiamond (3L << 10)
-#define FWL_STYLEEXT_CKB_SignShapeSquare (4L << 10)
-#define FWL_STYLEEXT_CKB_SignShapeStar (5L << 10)
-#define FWL_STYLEEXT_CKB_HLayoutMask (3L << 0)
-#define FWL_STYLEEXT_CKB_VLayoutMask (3L << 2)
-#define FWL_STYLEEXT_CKB_ShapeMask (3L << 8)
-#define FWL_STYLEEXT_CKB_SignShapeMask (7L << 10)
-#define FWL_STATE_CKB_Hovered (1 << FWL_WGTSTATE_MAX)
-#define FWL_STATE_CKB_Pressed (1 << (FWL_WGTSTATE_MAX + 1))
-#define FWL_STATE_CKB_Unchecked (0 << (FWL_WGTSTATE_MAX + 2))
-#define FWL_STATE_CKB_Checked (1 << (FWL_WGTSTATE_MAX + 2))
-#define FWL_STATE_CKB_Neutral (2 << (FWL_WGTSTATE_MAX + 2))
-#define FWL_STATE_CKB_CheckMask (3L << (FWL_WGTSTATE_MAX + 2))
-
-class CFWL_MsgMouse;
-class CFWL_WidgetProperties;
-class IFWL_Widget;
-
-class IFWL_CheckBox : public IFWL_Widget {
- public:
-  class DataProvider {
-   public:
-    virtual FX_FLOAT GetBoxSize(IFWL_Widget* pWidget) = 0;
-  };
-
-  IFWL_CheckBox(const CFWL_App* app,
-                std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_CheckBox() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void Update() override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
-  void SetDataProvider(IFWL_CheckBox::DataProvider* pProvider) {
-    m_pDataProvider = pProvider;
-  }
-
- private:
-  void SetCheckState(int32_t iCheck);
-  void Layout();
-  uint32_t GetPartStates() const;
-  void UpdateTextOutStyles();
-  void NextStates();
-  void OnFocusChanged(bool bSet);
-  void OnLButtonDown();
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnMouseMove(CFWL_MsgMouse* pMsg);
-  void OnMouseLeave();
-  void OnKeyDown(CFWL_MsgKey* pMsg);
-
-  IFWL_CheckBox::DataProvider* m_pDataProvider;  // Not owned.
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtBox;
-  CFX_RectF m_rtCaption;
-  CFX_RectF m_rtFocus;
-  uint32_t m_dwTTOStyles;
-  int32_t m_iTTOAlign;
-  bool m_bBtnDown;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_CHECKBOX_H_
diff --git a/xfa/fwl/core/ifwl_combobox.cpp b/xfa/fwl/core/ifwl_combobox.cpp
deleted file mode 100644
index 07fa64c..0000000
--- a/xfa/fwl/core/ifwl_combobox.cpp
+++ /dev/null
@@ -1,1130 +0,0 @@
-// 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/core/ifwl_combobox.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fde/tto/fde_textout.h"
-#include "xfa/fwl/core/cfwl_app.h"
-#include "xfa/fwl/core/cfwl_evteditchanged.h"
-#include "xfa/fwl/core/cfwl_evtpostdropdown.h"
-#include "xfa/fwl/core/cfwl_evtpredropdown.h"
-#include "xfa/fwl/core/cfwl_evtselectchanged.h"
-#include "xfa/fwl/core/cfwl_evttextchanged.h"
-#include "xfa/fwl/core/cfwl_formproxy.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgkillfocus.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_msgsetfocus.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-IFWL_ComboBox::IFWL_ComboBox(const CFWL_App* app,
-                             std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr),
-      m_pComboBoxProxy(nullptr),
-      m_bLButtonDown(false),
-      m_iCurSel(-1),
-      m_iBtnState(CFWL_PartState_Normal),
-      m_fComboFormHandler(0) {
-  m_rtClient.Reset();
-  m_rtBtn.Reset();
-  m_rtHandler.Reset();
-
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_InitComboList();
-    DisForm_InitComboEdit();
-    return;
-  }
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-  prop->m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText)
-    prop->m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon;
-  m_pListBox =
-      pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this);
-
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) {
-    m_pEdit.reset(new CFWL_ComboEdit(
-        m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this));
-    m_pEdit->SetOuter(this);
-  }
-  if (m_pEdit)
-    m_pEdit->SetParent(this);
-
-  SetStates(m_pProperties->m_dwStates);
-}
-
-IFWL_ComboBox::~IFWL_ComboBox() {}
-
-FWL_Type IFWL_ComboBox::GetClassID() const {
-  return FWL_Type::ComboBox;
-}
-
-void IFWL_ComboBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Reset();
-  if (IsDropDownStyle() && m_pEdit) {
-    m_pEdit->GetWidgetRect(rect, true);
-  } else {
-    rect.width = 100;
-    rect.height = 16;
-  }
-  if (!m_pProperties->m_pThemeProvider)
-    ResetTheme();
-
-  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pFWidth)
-    return;
-
-  rect.Inflate(0, 0, *pFWidth, 0);
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_ComboBox::AddString(const CFX_WideStringC& wsText) {
-  m_pListBox->AddString(wsText);
-}
-
-bool IFWL_ComboBox::RemoveAt(int32_t iIndex) {
-  return m_pListBox->RemoveAt(iIndex);
-}
-
-void IFWL_ComboBox::RemoveAll() {
-  m_pListBox->DeleteAll();
-}
-
-void IFWL_ComboBox::ModifyStylesEx(uint32_t dwStylesExAdded,
-                                   uint32_t dwStylesExRemoved) {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
-    return;
-  }
-
-  bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown);
-  bool bRemoveDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown);
-  if (bAddDropDown && !m_pEdit) {
-    m_pEdit = pdfium::MakeUnique<CFWL_ComboEdit>(
-        m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
-    m_pEdit->SetOuter(this);
-    m_pEdit->SetParent(this);
-  } else if (bRemoveDropDown && m_pEdit) {
-    m_pEdit->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-  IFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
-}
-
-void IFWL_ComboBox::Update() {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_Update();
-    return;
-  }
-  if (IsLocked())
-    return;
-
-  ResetTheme();
-  if (IsDropDownStyle() && m_pEdit)
-    ResetEditAlignment();
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  Layout();
-  CFWL_ThemePart part;
-  part.m_pWidget = this;
-  m_fComboFormHandler =
-      *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity(
-          &part, CFWL_WidgetCapacity::ComboFormHandler));
-}
-
-FWL_WidgetHit IFWL_ComboBox::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_HitTest(fx, fy);
-  return IFWL_Widget::HitTest(fx, fy);
-}
-
-void IFWL_ComboBox::DrawWidget(CFX_Graphics* pGraphics,
-                               const CFX_Matrix* pMatrix) {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_DrawWidget(pGraphics, pMatrix);
-    return;
-  }
-
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  if (HasBorder())
-    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-
-  if (!IsDropDownStyle()) {
-    CFX_RectF rtTextBk(m_rtClient);
-    rtTextBk.width -= m_rtBtn.width;
-
-    CFWL_ThemeBackground param;
-    param.m_pWidget = this;
-    param.m_iPart = CFWL_Part::Background;
-    param.m_pGraphics = pGraphics;
-    if (pMatrix)
-      param.m_matrix.Concat(*pMatrix);
-    param.m_rtPart = rtTextBk;
-
-    if (m_iCurSel >= 0) {
-      if (void* p = m_pListBox->GetItemData(
-              m_pListBox.get(),
-              m_pListBox->GetItem(m_pListBox.get(), m_iCurSel))) {
-        param.m_pData = p;
-      }
-    }
-
-    if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
-      param.m_dwStates = CFWL_PartState_Disabled;
-    } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
-               (m_iCurSel >= 0)) {
-      param.m_dwStates = CFWL_PartState_Selected;
-    } else {
-      param.m_dwStates = CFWL_PartState_Normal;
-    }
-    pTheme->DrawBackground(&param);
-
-    if (m_iCurSel >= 0) {
-      if (!m_pListBox)
-        return;
-
-      CFX_WideString wsText;
-      CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-      m_pListBox->GetDataProviderItemText(hItem, wsText);
-
-      CFWL_ThemeText theme_text;
-      theme_text.m_pWidget = this;
-      theme_text.m_iPart = CFWL_Part::Caption;
-      theme_text.m_dwStates = m_iBtnState;
-      theme_text.m_pGraphics = pGraphics;
-      theme_text.m_matrix.Concat(*pMatrix);
-      theme_text.m_rtPart = rtTextBk;
-      theme_text.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-                                  ? CFWL_PartState_Selected
-                                  : CFWL_PartState_Normal;
-      theme_text.m_wsText = wsText;
-      theme_text.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
-      theme_text.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
-      pTheme->DrawText(&theme_text);
-    }
-  }
-
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = CFWL_Part::DropDownButton;
-  param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-                         ? CFWL_PartState_Disabled
-                         : m_iBtnState;
-  param.m_pGraphics = pGraphics;
-  param.m_matrix.Concat(*pMatrix);
-  param.m_rtPart = m_rtBtn;
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_ComboBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
-  if (!pThemeProvider)
-    return;
-
-  m_pProperties->m_pThemeProvider = pThemeProvider;
-  if (m_pListBox)
-    m_pListBox->SetThemeProvider(pThemeProvider);
-  if (m_pEdit)
-    m_pEdit->SetThemeProvider(pThemeProvider);
-}
-
-void IFWL_ComboBox::GetTextByIndex(int32_t iIndex,
-                                   CFX_WideString& wsText) const {
-  CFWL_ListItem* pItem = static_cast<CFWL_ListItem*>(
-      m_pListBox->GetItem(m_pListBox.get(), iIndex));
-  if (pItem)
-    wsText = pItem->m_wsText;
-}
-
-void IFWL_ComboBox::SetCurSel(int32_t iSel) {
-  int32_t iCount = m_pListBox->CountItems(nullptr);
-  bool bClearSel = iSel < 0 || iSel >= iCount;
-  if (IsDropDownStyle() && m_pEdit) {
-    if (bClearSel) {
-      m_pEdit->SetText(CFX_WideString());
-    } else {
-      CFX_WideString wsText;
-      CFWL_ListItem* hItem = m_pListBox->GetItem(this, iSel);
-      m_pListBox->GetDataProviderItemText(hItem, wsText);
-      m_pEdit->SetText(wsText);
-    }
-    m_pEdit->Update();
-  }
-  m_iCurSel = bClearSel ? -1 : iSel;
-}
-
-void IFWL_ComboBox::SetStates(uint32_t dwStates, bool bSet) {
-  if (IsDropDownStyle() && m_pEdit)
-    m_pEdit->SetStates(dwStates, bSet);
-  if (m_pListBox)
-    m_pListBox->SetStates(dwStates, bSet);
-  IFWL_Widget::SetStates(dwStates, bSet);
-}
-
-void IFWL_ComboBox::SetEditText(const CFX_WideString& wsText) {
-  if (!m_pEdit)
-    return;
-
-  m_pEdit->SetText(wsText);
-  m_pEdit->Update();
-}
-
-void IFWL_ComboBox::GetEditText(CFX_WideString& wsText,
-                                int32_t nStart,
-                                int32_t nCount) const {
-  if (m_pEdit) {
-    m_pEdit->GetText(wsText, nStart, nCount);
-    return;
-  }
-  if (!m_pListBox)
-    return;
-
-  CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-  m_pListBox->GetDataProviderItemText(hItem, wsText);
-}
-
-void IFWL_ComboBox::OpenDropDownList(bool bActivate) {
-  ShowDropList(bActivate);
-}
-
-void IFWL_ComboBox::GetBBox(CFX_RectF& rect) const {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_GetBBox(rect);
-    return;
-  }
-
-  rect = m_pProperties->m_rtWidget;
-  if (!m_pListBox || !IsDropListVisible())
-    return;
-
-  CFX_RectF rtList;
-  m_pListBox->GetWidgetRect(rtList);
-  rtList.Offset(rect.left, rect.top);
-  rect.Union(rtList);
-}
-
-void IFWL_ComboBox::EditModifyStylesEx(uint32_t dwStylesExAdded,
-                                       uint32_t dwStylesExRemoved) {
-  if (m_pEdit)
-    m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
-}
-
-void IFWL_ComboBox::DrawStretchHandler(CFX_Graphics* pGraphics,
-                                       const CFX_Matrix* pMatrix) {
-  CFWL_ThemeBackground param;
-  param.m_pGraphics = pGraphics;
-  param.m_iPart = CFWL_Part::StretchHandler;
-  param.m_dwStates = CFWL_PartState_Normal;
-  param.m_pWidget = this;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix);
-  param.m_rtPart = m_rtHandler;
-  m_pProperties->m_pThemeProvider->DrawBackground(&param);
-}
-
-void IFWL_ComboBox::ShowDropList(bool bActivate) {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_ShowDropList(bActivate);
-  if (IsDropListVisible() == bActivate)
-    return;
-  if (!m_pComboBoxProxy)
-    InitProxyForm();
-
-  m_pComboBoxProxy->Reset();
-  if (!bActivate) {
-    m_pComboBoxProxy->EndDoModal();
-
-    m_bLButtonDown = false;
-    m_pListBox->SetNotifyOwner(true);
-    SetFocus(true);
-    return;
-  }
-
-  m_pListBox->ChangeSelected(m_iCurSel);
-  ResetListItemAlignment();
-
-  uint32_t dwStyleAdd = m_pProperties->m_dwStyleExes &
-                        (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw);
-  m_pListBox->ModifyStylesEx(dwStyleAdd, 0);
-  m_pListBox->GetWidgetRect(m_rtList, true);
-
-  CFX_RectF rtAnchor;
-  rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
-               m_pProperties->m_rtWidget.height);
-
-  m_rtList.width = std::max(m_rtList.width, m_rtClient.width);
-  m_rtProxy = m_rtList;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag)
-    m_rtProxy.height += m_fComboFormHandler;
-
-  GetPopupPos(0, m_rtProxy.height, rtAnchor, m_rtProxy);
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
-    FX_FLOAT fx = 0;
-    FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2;
-    TransformTo(nullptr, fx, fy);
-
-    m_bUpFormHandler = fy > m_rtProxy.top;
-    if (m_bUpFormHandler) {
-      m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler);
-      m_rtList.top = m_fComboFormHandler;
-    } else {
-      m_rtHandler.Set(0, m_rtList.height, m_rtList.width, m_fComboFormHandler);
-    }
-  }
-  m_pComboBoxProxy->SetWidgetRect(m_rtProxy);
-  m_pComboBoxProxy->Update();
-  m_pListBox->SetWidgetRect(m_rtList);
-  m_pListBox->Update();
-
-  CFWL_EvtPreDropDown ev;
-  ev.m_pSrcTarget = this;
-  DispatchEvent(&ev);
-
-  m_fItemHeight = m_pListBox->GetItemHeight();
-  m_pListBox->SetFocus(true);
-  m_pComboBoxProxy->DoModal();
-  m_pListBox->SetFocus(false);
-}
-
-void IFWL_ComboBox::MatchEditText() {
-  CFX_WideString wsText;
-  m_pEdit->GetText(wsText);
-  int32_t iMatch = m_pListBox->MatchItem(wsText);
-  if (iMatch != m_iCurSel) {
-    m_pListBox->ChangeSelected(iMatch);
-    if (iMatch >= 0)
-      SyncEditText(iMatch);
-  } else if (iMatch >= 0) {
-    m_pEdit->SetSelected();
-  }
-  m_iCurSel = iMatch;
-}
-
-void IFWL_ComboBox::SyncEditText(int32_t iListItem) {
-  CFX_WideString wsText;
-  CFWL_ListItem* hItem = m_pListBox->GetItem(this, iListItem);
-  m_pListBox->GetDataProviderItemText(hItem, wsText);
-  m_pEdit->SetText(wsText);
-  m_pEdit->Update();
-  m_pEdit->SetSelected();
-}
-
-void IFWL_ComboBox::Layout() {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_Layout();
-
-  GetClientRect(m_rtClient);
-  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pFWidth)
-    return;
-
-  FX_FLOAT fBtn = *pFWidth;
-  m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn,
-              m_rtClient.height);
-  if (!IsDropDownStyle() || !m_pEdit)
-    return;
-
-  CFX_RectF rtEdit;
-  rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
-             m_rtClient.height);
-  m_pEdit->SetWidgetRect(rtEdit);
-
-  if (m_iCurSel >= 0) {
-    CFX_WideString wsText;
-    CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-    m_pListBox->GetDataProviderItemText(hItem, wsText);
-    m_pEdit->LockUpdate();
-    m_pEdit->SetText(wsText);
-    m_pEdit->UnlockUpdate();
-  }
-  m_pEdit->Update();
-}
-
-void IFWL_ComboBox::ResetTheme() {
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  if (!pTheme) {
-    pTheme = GetAvailableTheme();
-    m_pProperties->m_pThemeProvider = pTheme;
-  }
-  if (m_pListBox && !m_pListBox->GetThemeProvider())
-    m_pListBox->SetThemeProvider(pTheme);
-  if (m_pEdit && !m_pEdit->GetThemeProvider())
-    m_pEdit->SetThemeProvider(pTheme);
-}
-
-void IFWL_ComboBox::ResetEditAlignment() {
-  if (!m_pEdit)
-    return;
-
-  uint32_t dwAdd = 0;
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditHAlignMask) {
-    case FWL_STYLEEXT_CMB_EditHCenter: {
-      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
-      break;
-    }
-    case FWL_STYLEEXT_CMB_EditHFar: {
-      dwAdd |= FWL_STYLEEXT_EDT_HFar;
-      break;
-    }
-    default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; }
-  }
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditVAlignMask) {
-    case FWL_STYLEEXT_CMB_EditVCenter: {
-      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
-      break;
-    }
-    case FWL_STYLEEXT_CMB_EditVFar: {
-      dwAdd |= FWL_STYLEEXT_EDT_VFar;
-      break;
-    }
-    default: {
-      dwAdd |= FWL_STYLEEXT_EDT_VNear;
-      break;
-    }
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditJustified)
-    dwAdd |= FWL_STYLEEXT_EDT_Justified;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_EditDistributed)
-    dwAdd |= FWL_STYLEEXT_EDT_Distributed;
-
-  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
-                                     FWL_STYLEEXT_EDT_HAlignModeMask |
-                                     FWL_STYLEEXT_EDT_VAlignMask);
-}
-
-void IFWL_ComboBox::ResetListItemAlignment() {
-  if (!m_pListBox)
-    return;
-
-  uint32_t dwAdd = 0;
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemAlignMask) {
-    case FWL_STYLEEXT_CMB_ListItemCenterAlign: {
-      dwAdd |= FWL_STYLEEXT_LTB_CenterAlign;
-      break;
-    }
-    case FWL_STYLEEXT_CMB_ListItemRightAlign: {
-      dwAdd |= FWL_STYLEEXT_LTB_RightAlign;
-      break;
-    }
-    default: {
-      dwAdd |= FWL_STYLEEXT_LTB_LeftAlign;
-      break;
-    }
-  }
-  m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask);
-}
-
-void IFWL_ComboBox::ProcessSelChanged(bool bLButtonUp) {
-  m_iCurSel = m_pListBox->GetItemIndex(this, m_pListBox->GetSelItem(0));
-  if (!IsDropDownStyle()) {
-    Repaint(&m_rtClient);
-    return;
-  }
-
-  CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-  if (!hItem)
-    return;
-
-  CFX_WideString wsText;
-  m_pListBox->GetItemText(this, hItem, wsText);
-  if (m_pEdit) {
-    m_pEdit->SetText(wsText);
-    m_pEdit->Update();
-    m_pEdit->SetSelected();
-  }
-
-  CFWL_EvtSelectChanged ev;
-  ev.bLButtonUp = bLButtonUp;
-  ev.m_pSrcTarget = this;
-  DispatchEvent(&ev);
-}
-
-void IFWL_ComboBox::InitProxyForm() {
-  if (m_pComboBoxProxy)
-    return;
-  if (!m_pListBox)
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_pOwner = this;
-  prop->m_dwStyles = FWL_WGTSTYLE_Popup;
-  prop->m_dwStates = FWL_WGTSTATE_Invisible;
-
-  // TODO(dsinclair): Does this leak? I don't see a delete, but I'm not sure
-  // if the SetParent call is going to transfer ownership.
-  m_pComboBoxProxy = new CFWL_ComboBoxProxy(this, m_pOwnerApp, std::move(prop),
-                                            m_pListBox.get());
-  m_pListBox->SetParent(m_pComboBoxProxy);
-}
-
-void IFWL_ComboBox::DisForm_InitComboList() {
-  if (m_pListBox)
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_pParent = this;
-  prop->m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
-  prop->m_dwStates = FWL_WGTSTATE_Invisible;
-  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-  m_pListBox =
-      pdfium::MakeUnique<CFWL_ComboList>(m_pOwnerApp, std::move(prop), this);
-}
-
-void IFWL_ComboBox::DisForm_InitComboEdit() {
-  if (m_pEdit)
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_pParent = this;
-  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-
-  m_pEdit =
-      pdfium::MakeUnique<CFWL_ComboEdit>(m_pOwnerApp, std::move(prop), this);
-  m_pEdit->SetOuter(this);
-}
-
-void IFWL_ComboBox::DisForm_ShowDropList(bool bActivate) {
-  if (DisForm_IsDropListVisible() == bActivate)
-    return;
-
-  if (bActivate) {
-    CFWL_EvtPreDropDown preEvent;
-    preEvent.m_pSrcTarget = this;
-    DispatchEvent(&preEvent);
-
-    CFWL_ComboList* pComboList = m_pListBox.get();
-    int32_t iItems = pComboList->CountItems(nullptr);
-    if (iItems < 1)
-      return;
-
-    ResetListItemAlignment();
-    pComboList->ChangeSelected(m_iCurSel);
-
-    FX_FLOAT fItemHeight = pComboList->CalcItemHeight();
-    FX_FLOAT fBorder = GetBorderSize();
-    FX_FLOAT fPopupMin = 0.0f;
-    if (iItems > 3)
-      fPopupMin = fItemHeight * 3 + fBorder * 2;
-
-    FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2;
-    CFX_RectF rtList;
-    rtList.left = m_rtClient.left;
-    rtList.width = m_pProperties->m_rtWidget.width;
-    rtList.top = 0;
-    rtList.height = 0;
-    GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList);
-
-    m_pListBox->SetWidgetRect(rtList);
-    m_pListBox->Update();
-  } else {
-    SetFocus(true);
-  }
-
-  m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
-  if (bActivate) {
-    CFWL_EvtPostDropDown postEvent;
-    postEvent.m_pSrcTarget = this;
-    DispatchEvent(&postEvent);
-  }
-
-  CFX_RectF rect;
-  m_pListBox->GetWidgetRect(rect);
-  rect.Inflate(2, 2);
-  Repaint(&rect);
-}
-
-void IFWL_ComboBox::DisForm_ModifyStylesEx(uint32_t dwStylesExAdded,
-                                           uint32_t dwStylesExRemoved) {
-  if (!m_pEdit)
-    DisForm_InitComboEdit();
-
-  bool bAddDropDown = !!(dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown);
-  bool bDelDropDown = !!(dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown);
-
-  dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown;
-  m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown;
-
-  if (bAddDropDown)
-    m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly);
-  else if (bDelDropDown)
-    m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0);
-  IFWL_Widget::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
-}
-
-void IFWL_ComboBox::DisForm_Update() {
-  if (m_iLock)
-    return;
-  if (m_pEdit)
-    ResetEditAlignment();
-  ResetTheme();
-  Layout();
-}
-
-FWL_WidgetHit IFWL_ComboBox::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  CFX_RectF rect;
-  rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width,
-           m_pProperties->m_rtWidget.height);
-  if (rect.Contains(fx, fy))
-    return FWL_WidgetHit::Edit;
-  if (m_rtBtn.Contains(fx, fy))
-    return FWL_WidgetHit::Client;
-  if (DisForm_IsDropListVisible()) {
-    m_pListBox->GetWidgetRect(rect);
-    if (rect.Contains(fx, fy))
-      return FWL_WidgetHit::Client;
-  }
-  return FWL_WidgetHit::Unknown;
-}
-
-void IFWL_ComboBox::DisForm_DrawWidget(CFX_Graphics* pGraphics,
-                                       const CFX_Matrix* pMatrix) {
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  CFX_Matrix mtOrg;
-  mtOrg.Set(1, 0, 0, 1, 0, 0);
-  if (pMatrix)
-    mtOrg = *pMatrix;
-
-  pGraphics->SaveGraphState();
-  pGraphics->ConcatMatrix(&mtOrg);
-  if (!m_rtBtn.IsEmpty(0.1f)) {
-    CFWL_ThemeBackground param;
-    param.m_pWidget = this;
-    param.m_iPart = CFWL_Part::DropDownButton;
-    param.m_dwStates = m_iBtnState;
-    param.m_pGraphics = pGraphics;
-    param.m_rtPart = m_rtBtn;
-    pTheme->DrawBackground(&param);
-  }
-  pGraphics->RestoreGraphState();
-
-  if (m_pEdit) {
-    CFX_RectF rtEdit;
-    m_pEdit->GetWidgetRect(rtEdit);
-    CFX_Matrix mt;
-    mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
-    mt.Concat(mtOrg);
-    m_pEdit->DrawWidget(pGraphics, &mt);
-  }
-  if (m_pListBox && DisForm_IsDropListVisible()) {
-    CFX_RectF rtList;
-    m_pListBox->GetWidgetRect(rtList);
-    CFX_Matrix mt;
-    mt.Set(1, 0, 0, 1, rtList.left, rtList.top);
-    mt.Concat(mtOrg);
-    m_pListBox->DrawWidget(pGraphics, &mt);
-  }
-}
-
-void IFWL_ComboBox::DisForm_GetBBox(CFX_RectF& rect) const {
-  rect = m_pProperties->m_rtWidget;
-  if (!m_pListBox || !DisForm_IsDropListVisible())
-    return;
-
-  CFX_RectF rtList;
-  m_pListBox->GetWidgetRect(rtList);
-  rtList.Offset(rect.left, rect.top);
-  rect.Union(rtList);
-}
-
-void IFWL_ComboBox::DisForm_Layout() {
-  GetClientRect(m_rtClient);
-  m_rtContent = m_rtClient;
-  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pFWidth)
-    return;
-
-  FX_FLOAT borderWidth = 1;
-  FX_FLOAT fBtn = *pFWidth;
-  if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) {
-    m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth,
-                fBtn - borderWidth, m_rtClient.height - 2 * borderWidth);
-  }
-
-  CFX_RectF* pUIMargin =
-      static_cast<CFX_RectF*>(GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
-  if (pUIMargin) {
-    m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
-                        pUIMargin->height);
-  }
-
-  if (!IsDropDownStyle() || !m_pEdit)
-    return;
-
-  CFX_RectF rtEdit;
-  rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn,
-             m_rtContent.height);
-  m_pEdit->SetWidgetRect(rtEdit);
-
-  if (m_iCurSel >= 0) {
-    CFX_WideString wsText;
-    CFWL_ListItem* hItem = m_pListBox->GetItem(this, m_iCurSel);
-    m_pListBox->GetDataProviderItemText(hItem, wsText);
-    m_pEdit->LockUpdate();
-    m_pEdit->SetText(wsText);
-    m_pEdit->UnlockUpdate();
-  }
-  m_pEdit->Update();
-}
-
-void IFWL_ComboBox::OnProcessMessage(CFWL_Message* pMessage) {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_OnProcessMessage(pMessage);
-    return;
-  }
-  if (!pMessage)
-    return;
-
-  switch (pMessage->GetClassID()) {
-    case CFWL_MessageType::SetFocus:
-      OnFocusChanged(pMessage, true);
-      break;
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(pMessage, false);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        case FWL_MouseCommand::Move:
-          OnMouseMove(pMsg);
-          break;
-        case FWL_MouseCommand::Leave:
-          OnMouseLeave(pMsg);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key:
-      OnKey(static_cast<CFWL_MsgKey*>(pMessage));
-      break;
-    default:
-      break;
-  }
-
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_ComboBox::OnProcessEvent(CFWL_Event* pEvent) {
-  CFWL_EventType dwFlag = pEvent->GetClassID();
-  if (dwFlag == CFWL_EventType::Scroll) {
-    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
-    CFWL_EvtScroll pScrollEv;
-    pScrollEv.m_pSrcTarget = this;
-    pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode;
-    pScrollEv.m_fPos = pScrollEvent->m_fPos;
-    DispatchEvent(&pScrollEv);
-  } else if (dwFlag == CFWL_EventType::TextChanged) {
-    CFWL_EvtEditChanged pTemp;
-    pTemp.m_pSrcTarget = this;
-    DispatchEvent(&pTemp);
-  }
-}
-
-void IFWL_ComboBox::OnDrawWidget(CFX_Graphics* pGraphics,
-                                 const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_ComboBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  if (bSet) {
-    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
-    if (IsDropDownStyle() && pMsg->m_pSrcTarget != m_pListBox.get()) {
-      if (!m_pEdit)
-        return;
-      m_pEdit->SetSelected();
-      return;
-    }
-
-    Repaint(&m_rtClient);
-    return;
-  }
-
-  m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
-  if (!IsDropDownStyle() || pMsg->m_pDstTarget == m_pListBox.get()) {
-    Repaint(&m_rtClient);
-    return;
-  }
-  if (!m_pEdit)
-    return;
-
-  m_pEdit->FlagFocus(false);
-  m_pEdit->ClearSelected();
-}
-
-void IFWL_ComboBox::OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    return;
-
-  CFX_RectF& rtBtn = IsDropDownStyle() ? m_rtBtn : m_rtClient;
-  if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    return;
-
-  if (IsDropDownStyle() && m_pEdit)
-    MatchEditText();
-
-  m_bLButtonDown = true;
-  m_iBtnState = CFWL_PartState_Pressed;
-  Repaint(&m_rtClient);
-
-  ShowDropList(true);
-  m_iBtnState = CFWL_PartState_Normal;
-  Repaint(&m_rtClient);
-}
-
-void IFWL_ComboBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  m_bLButtonDown = false;
-  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    m_iBtnState = CFWL_PartState_Hovered;
-  else
-    m_iBtnState = CFWL_PartState_Normal;
-
-  Repaint(&m_rtBtn);
-}
-
-void IFWL_ComboBox::OnMouseMove(CFWL_MsgMouse* pMsg) {
-  int32_t iOldState = m_iBtnState;
-  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
-    m_iBtnState =
-        m_bLButtonDown ? CFWL_PartState_Pressed : CFWL_PartState_Hovered;
-  } else {
-    m_iBtnState = CFWL_PartState_Normal;
-  }
-  if ((iOldState != m_iBtnState) &&
-      !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
-        FWL_WGTSTATE_Disabled)) {
-    Repaint(&m_rtBtn);
-  }
-}
-
-void IFWL_ComboBox::OnMouseLeave(CFWL_MsgMouse* pMsg) {
-  if (!IsDropListVisible() &&
-      !((m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
-        FWL_WGTSTATE_Disabled)) {
-    m_iBtnState = CFWL_PartState_Normal;
-    Repaint(&m_rtBtn);
-  }
-}
-
-void IFWL_ComboBox::OnKey(CFWL_MsgKey* pMsg) {
-  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
-  if (dwKeyCode == FWL_VKEY_Tab) {
-    DispatchKeyEvent(pMsg);
-    return;
-  }
-  if (pMsg->m_pDstTarget == this)
-    DoSubCtrlKey(pMsg);
-}
-
-void IFWL_ComboBox::DoSubCtrlKey(CFWL_MsgKey* pMsg) {
-  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
-  const bool bUp = dwKeyCode == FWL_VKEY_Up;
-  const bool bDown = dwKeyCode == FWL_VKEY_Down;
-  if (bUp || bDown) {
-    int32_t iCount = m_pListBox->CountItems(nullptr);
-    if (iCount < 1)
-      return;
-
-    bool bMatchEqual = false;
-    int32_t iCurSel = m_iCurSel;
-    bool bDropDown = IsDropDownStyle();
-    if (bDropDown && m_pEdit) {
-      CFX_WideString wsText;
-      m_pEdit->GetText(wsText);
-      iCurSel = m_pListBox->MatchItem(wsText);
-      if (iCurSel >= 0) {
-        CFX_WideString wsTemp;
-        CFWL_ListItem* hItem = m_pListBox->GetItem(this, iCurSel);
-        m_pListBox->GetDataProviderItemText(hItem, wsTemp);
-        bMatchEqual = wsText == wsTemp;
-      }
-    }
-    if (iCurSel < 0) {
-      iCurSel = 0;
-    } else if (!bDropDown || bMatchEqual) {
-      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1))
-        return;
-      if (bUp)
-        iCurSel--;
-      else
-        iCurSel++;
-    }
-    m_iCurSel = iCurSel;
-    if (bDropDown && m_pEdit)
-      SyncEditText(m_iCurSel);
-    else
-      Repaint(&m_rtClient);
-    return;
-  }
-
-  if (IsDropDownStyle())
-    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
-}
-
-void IFWL_ComboBox::DisForm_OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-
-  bool backDefault = true;
-  switch (pMessage->GetClassID()) {
-    case CFWL_MessageType::SetFocus: {
-      backDefault = false;
-      DisForm_OnFocusChanged(pMessage, true);
-      break;
-    }
-    case CFWL_MessageType::KillFocus: {
-      backDefault = false;
-      DisForm_OnFocusChanged(pMessage, false);
-      break;
-    }
-    case CFWL_MessageType::Mouse: {
-      backDefault = false;
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          DisForm_OnLButtonDown(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      backDefault = false;
-      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
-      if (pKey->m_dwCmd == FWL_KeyCommand::KeyUp)
-        break;
-      if (DisForm_IsDropListVisible() &&
-          pKey->m_dwCmd == FWL_KeyCommand::KeyDown) {
-        bool bListKey = pKey->m_dwKeyCode == FWL_VKEY_Up ||
-                        pKey->m_dwKeyCode == FWL_VKEY_Down ||
-                        pKey->m_dwKeyCode == FWL_VKEY_Return ||
-                        pKey->m_dwKeyCode == FWL_VKEY_Escape;
-        if (bListKey) {
-          m_pListBox->GetDelegate()->OnProcessMessage(pMessage);
-          break;
-        }
-      }
-      DisForm_OnKey(pKey);
-      break;
-    }
-    default:
-      break;
-  }
-  if (backDefault)
-    IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_ComboBox::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  bool bDropDown = DisForm_IsDropListVisible();
-  CFX_RectF& rtBtn = bDropDown ? m_rtBtn : m_rtClient;
-  if (!rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    return;
-
-  if (DisForm_IsDropListVisible()) {
-    DisForm_ShowDropList(false);
-    return;
-  }
-  if (m_pEdit)
-    MatchEditText();
-  DisForm_ShowDropList(true);
-}
-
-void IFWL_ComboBox::DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  if (bSet) {
-    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
-    if ((m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) {
-      CFWL_MsgSetFocus msg;
-      msg.m_pDstTarget = m_pEdit.get();
-      msg.m_pSrcTarget = nullptr;
-      m_pEdit->GetDelegate()->OnProcessMessage(&msg);
-    }
-  } else {
-    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
-    DisForm_ShowDropList(false);
-    CFWL_MsgKillFocus msg;
-    msg.m_pDstTarget = nullptr;
-    msg.m_pSrcTarget = m_pEdit.get();
-    m_pEdit->GetDelegate()->OnProcessMessage(&msg);
-  }
-}
-
-void IFWL_ComboBox::DisForm_OnKey(CFWL_MsgKey* pMsg) {
-  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
-  const bool bUp = dwKeyCode == FWL_VKEY_Up;
-  const bool bDown = dwKeyCode == FWL_VKEY_Down;
-  if (bUp || bDown) {
-    CFWL_ComboList* pComboList = m_pListBox.get();
-    int32_t iCount = pComboList->CountItems(nullptr);
-    if (iCount < 1)
-      return;
-
-    bool bMatchEqual = false;
-    int32_t iCurSel = m_iCurSel;
-    if (m_pEdit) {
-      CFX_WideString wsText;
-      m_pEdit->GetText(wsText);
-      iCurSel = pComboList->MatchItem(wsText);
-      if (iCurSel >= 0) {
-        CFX_WideString wsTemp;
-        CFWL_ListItem* item = m_pListBox->GetSelItem(iCurSel);
-        m_pListBox->GetDataProviderItemText(item, wsTemp);
-        bMatchEqual = wsText == wsTemp;
-      }
-    }
-    if (iCurSel < 0) {
-      iCurSel = 0;
-    } else if (bMatchEqual) {
-      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1))
-        return;
-      if (bUp)
-        iCurSel--;
-      else
-        iCurSel++;
-    }
-    m_iCurSel = iCurSel;
-    SyncEditText(m_iCurSel);
-    return;
-  }
-  if (m_pEdit)
-    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
-}
diff --git a/xfa/fwl/core/ifwl_combobox.h b/xfa/fwl/core/ifwl_combobox.h
deleted file mode 100644
index 26d0c0f..0000000
--- a/xfa/fwl/core/ifwl_combobox.h
+++ /dev/null
@@ -1,176 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_COMBOBOX_H_
-#define XFA_FWL_CORE_IFWL_COMBOBOX_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_comboboxproxy.h"
-#include "xfa/fwl/core/cfwl_comboedit.h"
-#include "xfa/fwl/core/cfwl_combolist.h"
-#include "xfa/fwl/core/cfwl_form.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fxgraphics/cfx_graphics.h"
-
-class CFWL_WidgetProperties;
-class IFWL_ComboBox;
-class CFWL_ComboBoxProxy;
-class CFWL_FormProxy;
-class IFWL_ListBox;
-class IFWL_Widget;
-
-#define FWL_STYLEEXT_CMB_DropList (0L << 0)
-#define FWL_STYLEEXT_CMB_DropDown (1L << 0)
-#define FWL_STYLEEXT_CMB_Sort (1L << 1)
-#define FWL_STYLEEXT_CMB_ListDrag (1L << 2)
-#define FWL_STYLEEXT_CMB_OwnerDraw (1L << 3)
-#define FWL_STYLEEXT_CMB_EditHNear (0L << 4)
-#define FWL_STYLEEXT_CMB_EditHCenter (1L << 4)
-#define FWL_STYLEEXT_CMB_EditHFar (2L << 4)
-#define FWL_STYLEEXT_CMB_EditVNear (0L << 6)
-#define FWL_STYLEEXT_CMB_EditVCenter (1L << 6)
-#define FWL_STYLEEXT_CMB_EditVFar (2L << 6)
-#define FWL_STYLEEXT_CMB_EditJustified (1L << 8)
-#define FWL_STYLEEXT_CMB_EditDistributed (2L << 8)
-#define FWL_STYLEEXT_CMB_EditHAlignMask (3L << 4)
-#define FWL_STYLEEXT_CMB_EditVAlignMask (3L << 6)
-#define FWL_STYLEEXT_CMB_EditHAlignModeMask (3L << 8)
-#define FWL_STYLEEXT_CMB_ListItemLeftAlign (0L << 10)
-#define FWL_STYLEEXT_CMB_ListItemCenterAlign (1L << 10)
-#define FWL_STYLEEXT_CMB_ListItemRightAlign (2L << 10)
-#define FWL_STYLEEXT_CMB_ListItemAlignMask (3L << 10)
-#define FWL_STYLEEXT_CMB_ListItemText (0L << 12)
-#define FWL_STYLEEXT_CMB_ListItemIconText (1L << 12)
-#define FWL_STYLEEXT_CMB_ReadOnly (1L << 13)
-
-class IFWL_ComboBox : public IFWL_Widget {
- public:
-  explicit IFWL_ComboBox(const CFWL_App* app,
-                         std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_ComboBox() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void ModifyStylesEx(uint32_t dwStylesExAdded,
-                      uint32_t dwStylesExRemoved) override;
-  void SetStates(uint32_t dwStates, bool bSet = true) override;
-  void Update() override;
-  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnProcessEvent(CFWL_Event* pEvent) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
-  void GetTextByIndex(int32_t iIndex, CFX_WideString& wsText) const;
-  int32_t GetCurSel() const { return m_iCurSel; }
-  void SetCurSel(int32_t iSel);
-
-  void AddString(const CFX_WideStringC& wsText);
-  bool RemoveAt(int32_t iIndex);  // Returns false iff |iIndex| out of range.
-  void RemoveAll();
-
-  void SetEditText(const CFX_WideString& wsText);
-  void GetEditText(CFX_WideString& wsText,
-                   int32_t nStart = 0,
-                   int32_t nCount = -1) const;
-
-  void OpenDropDownList(bool bActivate);
-
-  bool EditCanUndo() const { return m_pEdit->CanUndo(); }
-  bool EditCanRedo() const { return m_pEdit->CanRedo(); }
-  bool EditUndo() { return m_pEdit->Undo(); }
-  bool EditRedo() { return m_pEdit->Redo(); }
-  bool EditCanCopy() const { return m_pEdit->CountSelRanges() > 0; }
-  bool EditCanCut() const {
-    if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)
-      return false;
-    return EditCanCopy();
-  }
-  bool EditCanSelectAll() const { return m_pEdit->GetTextLength() > 0; }
-  bool EditCopy(CFX_WideString& wsCopy) const { return m_pEdit->Copy(wsCopy); }
-  bool EditCut(CFX_WideString& wsCut) { return m_pEdit->Cut(wsCut); }
-  bool EditPaste(const CFX_WideString& wsPaste) {
-    return m_pEdit->Paste(wsPaste);
-  }
-  void EditSelectAll() { m_pEdit->AddSelRange(0); }
-  void EditDelete() { m_pEdit->ClearText(); }
-  void EditDeSelect() { m_pEdit->ClearSelections(); }
-
-  void GetBBox(CFX_RectF& rect) const;
-  void EditModifyStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved);
-
-  void DrawStretchHandler(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix);
-  bool IsDropListVisible() const {
-    return m_pComboBoxProxy &&
-           !(m_pComboBoxProxy->GetStates() & FWL_WGTSTATE_Invisible);
-  }
-  void ShowDropList(bool bActivate);
-
-  CFWL_ComboEdit* GetComboEdit() const { return m_pEdit.get(); }
-
-  void ProcessSelChanged(bool bLButtonUp);
-  int32_t GetCurrentSelection() const { return m_iCurSel; }
-
- private:
-  bool IsDropDownStyle() const {
-    return !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown);
-  }
-  void MatchEditText();
-  void SyncEditText(int32_t iListItem);
-  void Layout();
-  void ResetTheme();
-  void ResetEditAlignment();
-  void ResetListItemAlignment();
-  void InitProxyForm();
-  void DisForm_InitComboList();
-  void DisForm_InitComboEdit();
-  void DisForm_ShowDropList(bool bActivate);
-  bool DisForm_IsDropListVisible() const {
-    return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible);
-  }
-  void DisForm_ModifyStylesEx(uint32_t dwStylesExAdded,
-                              uint32_t dwStylesExRemoved);
-  void DisForm_Update();
-  FWL_WidgetHit DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy);
-  void DisForm_DrawWidget(CFX_Graphics* pGraphics,
-                          const CFX_Matrix* pMatrix = nullptr);
-  void DisForm_GetBBox(CFX_RectF& rect) const;
-  void DisForm_Layout();
-  void OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
-  void OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnMouseMove(CFWL_MsgMouse* pMsg);
-  void OnMouseLeave(CFWL_MsgMouse* pMsg);
-  void OnKey(CFWL_MsgKey* pMsg);
-  void DoSubCtrlKey(CFWL_MsgKey* pMsg);
-  void DisForm_OnProcessMessage(CFWL_Message* pMessage);
-  void DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
-  void DisForm_OnKey(CFWL_MsgKey* pMsg);
-
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtContent;
-  CFX_RectF m_rtBtn;
-  CFX_RectF m_rtList;
-  CFX_RectF m_rtProxy;
-  CFX_RectF m_rtHandler;
-  std::unique_ptr<CFWL_ComboEdit> m_pEdit;
-  std::unique_ptr<CFWL_ComboList> m_pListBox;
-  CFWL_ComboBoxProxy* m_pComboBoxProxy;  // Can this be a unique_ptr?
-  bool m_bLButtonDown;
-  bool m_bUpFormHandler;
-  int32_t m_iCurSel;
-  int32_t m_iBtnState;
-  FX_FLOAT m_fComboFormHandler;
-  FX_FLOAT m_fItemHeight;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_COMBOBOX_H_
diff --git a/xfa/fwl/core/ifwl_datetimepicker.cpp b/xfa/fwl/core/ifwl_datetimepicker.cpp
deleted file mode 100644
index 787be0c..0000000
--- a/xfa/fwl/core/ifwl_datetimepicker.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-// 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/core/ifwl_datetimepicker.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fwl/core/cfwl_evteditchanged.h"
-#include "xfa/fwl/core/cfwl_evtselectchanged.h"
-#include "xfa/fwl/core/cfwl_formproxy.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_msgsetfocus.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_spinbutton.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-namespace {
-
-const int kDateTimePickerWidth = 100;
-const int kDateTimePickerHeight = 20;
-
-}  // namespace
-
-IFWL_DateTimePicker::IFWL_DateTimePicker(
-    const CFWL_App* app,
-    std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr),
-      m_iBtnState(1),
-      m_iYear(-1),
-      m_iMonth(-1),
-      m_iDay(-1),
-      m_bLBtnDown(false) {
-  m_rtBtn.Set(0, 0, 0, 0);
-
-  m_pProperties->m_dwStyleExes = FWL_STYLEEXT_DTP_ShortDateFormat;
-
-  auto monthProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  monthProp->m_dwStyles = FWL_WGTSTYLE_Popup | FWL_WGTSTYLE_Border;
-  monthProp->m_dwStates = FWL_WGTSTATE_Invisible;
-  monthProp->m_pParent = this;
-  monthProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-  m_pMonthCal.reset(
-      new CFWL_MonthCalendar(m_pOwnerApp, std::move(monthProp), this));
-
-  CFX_RectF rtMonthCal;
-  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
-  rtMonthCal.Set(0, 0, rtMonthCal.width, rtMonthCal.height);
-  m_pMonthCal->SetWidgetRect(rtMonthCal);
-
-  auto editProp = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  editProp->m_pParent = this;
-  editProp->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-
-  m_pEdit.reset(new CFWL_DateTimeEdit(m_pOwnerApp, std::move(editProp), this));
-  RegisterEventTarget(m_pMonthCal.get());
-  RegisterEventTarget(m_pEdit.get());
-}
-
-IFWL_DateTimePicker::~IFWL_DateTimePicker() {
-  UnregisterEventTarget();
-}
-
-FWL_Type IFWL_DateTimePicker::GetClassID() const {
-  return FWL_Type::DateTimePicker;
-}
-
-void IFWL_DateTimePicker::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_GetWidgetRect(rect, bAutoSize);
-    return;
-  }
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Set(0, 0, kDateTimePickerWidth, kDateTimePickerHeight);
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_DateTimePicker::Update() {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_Update();
-    return;
-  }
-  if (m_iLock)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
-  GetClientRect(m_rtClient);
-  FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pFWidth)
-    return;
-
-  FX_FLOAT fBtn = *pFWidth;
-  m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn - 1,
-              m_rtClient.height - 1);
-
-  CFX_RectF rtEdit;
-  rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
-             m_rtClient.height);
-  m_pEdit->SetWidgetRect(rtEdit);
-  ResetEditAlignment();
-  m_pEdit->Update();
-  if (!(m_pMonthCal->GetThemeProvider()))
-    m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
-
-  CFX_RectF rtMonthCal;
-  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
-  CFX_RectF rtPopUp;
-  rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
-              rtMonthCal.width, rtMonthCal.height);
-  m_pMonthCal->SetWidgetRect(rtPopUp);
-  m_pMonthCal->Update();
-  return;
-}
-
-FWL_WidgetHit IFWL_DateTimePicker::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_HitTest(fx, fy);
-  if (m_rtClient.Contains(fx, fy))
-    return FWL_WidgetHit::Client;
-  if (IsMonthCalendarVisible()) {
-    CFX_RectF rect;
-    m_pMonthCal->GetWidgetRect(rect);
-    if (rect.Contains(fx, fy))
-      return FWL_WidgetHit::Client;
-  }
-  return FWL_WidgetHit::Unknown;
-}
-
-void IFWL_DateTimePicker::DrawWidget(CFX_Graphics* pGraphics,
-                                     const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  if (HasBorder())
-    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-  if (!m_rtBtn.IsEmpty())
-    DrawDropDownButton(pGraphics, pTheme, pMatrix);
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_DrawWidget(pGraphics, pMatrix);
-    return;
-  }
-}
-
-void IFWL_DateTimePicker::SetThemeProvider(IFWL_ThemeProvider* pTP) {
-  m_pProperties->m_pThemeProvider = pTP;
-  m_pMonthCal->SetThemeProvider(pTP);
-}
-
-void IFWL_DateTimePicker::GetCurSel(int32_t& iYear,
-                                    int32_t& iMonth,
-                                    int32_t& iDay) {
-  iYear = m_iYear;
-  iMonth = m_iMonth;
-  iDay = m_iDay;
-}
-
-void IFWL_DateTimePicker::SetCurSel(int32_t iYear,
-                                    int32_t iMonth,
-                                    int32_t iDay) {
-  if (iYear <= 0 || iYear >= 3000)
-    return;
-  if (iMonth <= 0 || iMonth >= 13)
-    return;
-  if (iDay <= 0 || iDay >= 32)
-    return;
-
-  m_iYear = iYear;
-  m_iMonth = iMonth;
-  m_iDay = iDay;
-  m_pMonthCal->SetSelect(iYear, iMonth, iDay);
-}
-
-void IFWL_DateTimePicker::SetEditText(const CFX_WideString& wsText) {
-  if (!m_pEdit)
-    return;
-
-  m_pEdit->SetText(wsText);
-  Repaint(&m_rtClient);
-
-  CFWL_EvtEditChanged ev;
-  DispatchEvent(&ev);
-}
-
-void IFWL_DateTimePicker::GetEditText(CFX_WideString& wsText,
-                                      int32_t nStart,
-                                      int32_t nCount) const {
-  if (m_pEdit)
-    m_pEdit->GetText(wsText, nStart, nCount);
-}
-
-void IFWL_DateTimePicker::GetBBox(CFX_RectF& rect) const {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    DisForm_GetBBox(rect);
-    return;
-  }
-
-  rect = m_pProperties->m_rtWidget;
-  if (IsMonthCalendarVisible()) {
-    CFX_RectF rtMonth;
-    m_pMonthCal->GetWidgetRect(rtMonth);
-    rtMonth.Offset(m_pProperties->m_rtWidget.left,
-                   m_pProperties->m_rtWidget.top);
-    rect.Union(rtMonth);
-  }
-}
-
-void IFWL_DateTimePicker::ModifyEditStylesEx(uint32_t dwStylesExAdded,
-                                             uint32_t dwStylesExRemoved) {
-  m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
-}
-
-void IFWL_DateTimePicker::DrawDropDownButton(CFX_Graphics* pGraphics,
-                                             IFWL_ThemeProvider* pTheme,
-                                             const CFX_Matrix* pMatrix) {
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_Spin) ==
-      FWL_STYLEEXT_DTP_Spin) {
-    return;
-  }
-
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = CFWL_Part::DropDownButton;
-  param.m_dwStates = m_iBtnState;
-  param.m_pGraphics = pGraphics;
-  param.m_rtPart = m_rtBtn;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix);
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_DateTimePicker::FormatDateString(int32_t iYear,
-                                           int32_t iMonth,
-                                           int32_t iDay,
-                                           CFX_WideString& wsText) {
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_ShortDateFormat) ==
-      FWL_STYLEEXT_DTP_ShortDateFormat) {
-    wsText.Format(L"%d-%d-%d", iYear, iMonth, iDay);
-  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_LongDateFormat) ==
-             FWL_STYLEEXT_DTP_LongDateFormat) {
-    wsText.Format(L"%d Year %d Month %d Day", iYear, iMonth, iDay);
-  }
-}
-
-void IFWL_DateTimePicker::ShowMonthCalendar(bool bActivate) {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_ShowMonthCalendar(bActivate);
-  if (IsMonthCalendarVisible() == bActivate)
-    return;
-  if (!m_pForm)
-    InitProxyForm();
-
-  if (!bActivate) {
-    m_pForm->EndDoModal();
-    return;
-  }
-
-  CFX_RectF rtMonth;
-  m_pMonthCal->GetWidgetRect(rtMonth);
-
-  CFX_RectF rtAnchor;
-  rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
-               m_pProperties->m_rtWidget.height);
-  GetPopupPos(0, rtMonth.height, rtAnchor, rtMonth);
-  m_pForm->SetWidgetRect(rtMonth);
-
-  rtMonth.left = rtMonth.top = 0;
-  m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
-  m_pMonthCal->SetWidgetRect(rtMonth);
-  m_pMonthCal->Update();
-  m_pForm->DoModal();
-}
-
-bool IFWL_DateTimePicker::IsMonthCalendarVisible() const {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_IsMonthCalendarVisible();
-  if (!m_pForm)
-    return false;
-  return !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
-}
-
-void IFWL_DateTimePicker::ResetEditAlignment() {
-  if (!m_pEdit)
-    return;
-
-  uint32_t dwAdd = 0;
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditHAlignMask) {
-    case FWL_STYLEEXT_DTP_EditHCenter: {
-      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
-      break;
-    }
-    case FWL_STYLEEXT_DTP_EditHFar: {
-      dwAdd |= FWL_STYLEEXT_EDT_HFar;
-      break;
-    }
-    default: {
-      dwAdd |= FWL_STYLEEXT_EDT_HNear;
-      break;
-    }
-  }
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditVAlignMask) {
-    case FWL_STYLEEXT_DTP_EditVCenter: {
-      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
-      break;
-    }
-    case FWL_STYLEEXT_DTP_EditVFar: {
-      dwAdd |= FWL_STYLEEXT_EDT_VFar;
-      break;
-    }
-    default: {
-      dwAdd |= FWL_STYLEEXT_EDT_VNear;
-      break;
-    }
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditJustified)
-    dwAdd |= FWL_STYLEEXT_EDT_Justified;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_EditDistributed)
-    dwAdd |= FWL_STYLEEXT_EDT_Distributed;
-
-  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
-                                     FWL_STYLEEXT_EDT_HAlignModeMask |
-                                     FWL_STYLEEXT_EDT_VAlignMask);
-}
-
-void IFWL_DateTimePicker::ProcessSelChanged(int32_t iYear,
-                                            int32_t iMonth,
-                                            int32_t iDay) {
-  m_iYear = iYear;
-  m_iMonth = iMonth;
-  m_iDay = iDay;
-
-  CFX_WideString wsText;
-  FormatDateString(m_iYear, m_iMonth, m_iDay, wsText);
-  m_pEdit->SetText(wsText);
-  m_pEdit->Update();
-  Repaint(&m_rtClient);
-
-  CFWL_EvtSelectChanged ev;
-  ev.m_pSrcTarget = this;
-  ev.iYear = m_iYear;
-  ev.iMonth = m_iMonth;
-  ev.iDay = m_iDay;
-  DispatchEvent(&ev);
-}
-
-void IFWL_DateTimePicker::InitProxyForm() {
-  if (m_pForm)
-    return;
-  if (!m_pMonthCal)
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_dwStyles = FWL_WGTSTYLE_Popup;
-  prop->m_dwStates = FWL_WGTSTATE_Invisible;
-  prop->m_pOwner = this;
-
-  m_pForm = pdfium::MakeUnique<CFWL_FormProxy>(m_pOwnerApp, std::move(prop),
-                                               m_pMonthCal.get());
-  m_pMonthCal->SetParent(m_pForm.get());
-}
-
-bool IFWL_DateTimePicker::DisForm_IsMonthCalendarVisible() const {
-  if (!m_pMonthCal)
-    return false;
-  return !(m_pMonthCal->GetStates() & FWL_WGTSTATE_Invisible);
-}
-
-void IFWL_DateTimePicker::DisForm_ShowMonthCalendar(bool bActivate) {
-  if (IsMonthCalendarVisible() == bActivate)
-    return;
-
-  if (bActivate) {
-    CFX_RectF rtMonthCal;
-    m_pMonthCal->GetWidgetRect(rtMonthCal, true);
-    FX_FLOAT fPopupMin = rtMonthCal.height;
-    FX_FLOAT fPopupMax = rtMonthCal.height;
-    CFX_RectF rtAnchor(m_pProperties->m_rtWidget);
-    rtAnchor.width = rtMonthCal.width;
-    rtMonthCal.left = m_rtClient.left;
-    rtMonthCal.top = rtAnchor.Height();
-    GetPopupPos(fPopupMin, fPopupMax, rtAnchor, rtMonthCal);
-    m_pMonthCal->SetWidgetRect(rtMonthCal);
-    if (m_iYear > 0 && m_iMonth > 0 && m_iDay > 0)
-      m_pMonthCal->SetSelect(m_iYear, m_iMonth, m_iDay);
-    m_pMonthCal->Update();
-  }
-  m_pMonthCal->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
-
-  if (bActivate) {
-    CFWL_MsgSetFocus msg;
-    msg.m_pDstTarget = m_pMonthCal.get();
-    msg.m_pSrcTarget = m_pEdit.get();
-    m_pEdit->GetDelegate()->OnProcessMessage(&msg);
-  }
-
-  CFX_RectF rtInvalidate, rtCal;
-  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
-                   m_pProperties->m_rtWidget.height);
-  m_pMonthCal->GetWidgetRect(rtCal);
-  rtInvalidate.Union(rtCal);
-  rtInvalidate.Inflate(2, 2);
-  Repaint(&rtInvalidate);
-}
-
-FWL_WidgetHit IFWL_DateTimePicker::DisForm_HitTest(FX_FLOAT fx,
-                                                   FX_FLOAT fy) const {
-  CFX_RectF rect;
-  rect.Set(0, 0, m_pProperties->m_rtWidget.width,
-           m_pProperties->m_rtWidget.height);
-  if (rect.Contains(fx, fy))
-    return FWL_WidgetHit::Edit;
-  if (DisForm_IsNeedShowButton())
-    rect.width += m_fBtn;
-  if (rect.Contains(fx, fy))
-    return FWL_WidgetHit::Client;
-  if (IsMonthCalendarVisible()) {
-    m_pMonthCal->GetWidgetRect(rect);
-    if (rect.Contains(fx, fy))
-      return FWL_WidgetHit::Client;
-  }
-  return FWL_WidgetHit::Unknown;
-}
-
-bool IFWL_DateTimePicker::DisForm_IsNeedShowButton() const {
-  return m_pProperties->m_dwStates & FWL_WGTSTATE_Focused ||
-         m_pMonthCal->GetStates() & FWL_WGTSTATE_Focused ||
-         m_pEdit->GetStates() & FWL_WGTSTATE_Focused;
-}
-
-void IFWL_DateTimePicker::DisForm_Update() {
-  if (m_iLock)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  m_pEdit->SetThemeProvider(m_pProperties->m_pThemeProvider);
-  GetClientRect(m_rtClient);
-  m_pEdit->SetWidgetRect(m_rtClient);
-  ResetEditAlignment();
-  m_pEdit->Update();
-
-  if (!m_pMonthCal->GetThemeProvider())
-    m_pMonthCal->SetThemeProvider(m_pProperties->m_pThemeProvider);
-
-  FX_FLOAT* pWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pWidth)
-    return;
-
-  m_fBtn = *pWidth;
-  CFX_RectF rtMonthCal;
-  m_pMonthCal->GetWidgetRect(rtMonthCal, true);
-
-  CFX_RectF rtPopUp;
-  rtPopUp.Set(rtMonthCal.left, rtMonthCal.top + kDateTimePickerHeight,
-              rtMonthCal.width, rtMonthCal.height);
-  m_pMonthCal->SetWidgetRect(rtPopUp);
-  m_pMonthCal->Update();
-}
-
-void IFWL_DateTimePicker::DisForm_GetWidgetRect(CFX_RectF& rect,
-                                                bool bAutoSize) {
-  rect = m_pProperties->m_rtWidget;
-  if (DisForm_IsNeedShowButton())
-    rect.width += m_fBtn;
-}
-
-void IFWL_DateTimePicker::DisForm_GetBBox(CFX_RectF& rect) const {
-  rect = m_pProperties->m_rtWidget;
-  if (DisForm_IsNeedShowButton())
-    rect.width += m_fBtn;
-  if (!IsMonthCalendarVisible())
-    return;
-
-  CFX_RectF rtMonth;
-  m_pMonthCal->GetWidgetRect(rtMonth);
-  rtMonth.Offset(m_pProperties->m_rtWidget.left, m_pProperties->m_rtWidget.top);
-  rect.Union(rtMonth);
-}
-
-void IFWL_DateTimePicker::DisForm_DrawWidget(CFX_Graphics* pGraphics,
-                                             const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (m_pEdit) {
-    CFX_RectF rtEdit;
-    m_pEdit->GetWidgetRect(rtEdit);
-
-    CFX_Matrix mt;
-    mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
-    if (pMatrix)
-      mt.Concat(*pMatrix);
-    m_pEdit->DrawWidget(pGraphics, &mt);
-  }
-  if (!IsMonthCalendarVisible())
-    return;
-
-  CFX_RectF rtMonth;
-  m_pMonthCal->GetWidgetRect(rtMonth);
-  CFX_Matrix mt;
-  mt.Set(1, 0, 0, 1, rtMonth.left, rtMonth.top);
-  if (pMatrix)
-    mt.Concat(*pMatrix);
-  m_pMonthCal->DrawWidget(pGraphics, &mt);
-}
-
-void IFWL_DateTimePicker::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-
-  switch (pMessage->GetClassID()) {
-    case CFWL_MessageType::SetFocus:
-      OnFocusChanged(pMessage, true);
-      break;
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(pMessage, false);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMouse = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMouse->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown(pMouse);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMouse);
-          break;
-        case FWL_MouseCommand::Move:
-          OnMouseMove(pMouse);
-          break;
-        case FWL_MouseCommand::Leave:
-          OnMouseLeave(pMouse);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
-        m_pEdit->GetDelegate()->OnProcessMessage(pMessage);
-        return;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_DateTimePicker::OnDrawWidget(CFX_Graphics* pGraphics,
-                                       const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_DateTimePicker::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  if (!pMsg)
-    return;
-  if (m_pWidgetMgr->IsFormDisabled())
-    return DisForm_OnFocusChanged(pMsg, bSet);
-
-  if (bSet) {
-    m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
-    Repaint(&m_rtClient);
-  } else {
-    m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
-    Repaint(&m_rtClient);
-  }
-  if (pMsg->m_pSrcTarget == m_pMonthCal.get() && IsMonthCalendarVisible()) {
-    ShowMonthCalendar(false);
-  }
-  Repaint(&m_rtClient);
-}
-
-void IFWL_DateTimePicker::OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  if (!pMsg)
-    return;
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    SetFocus(true);
-  if (!m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    return;
-
-  if (IsMonthCalendarVisible()) {
-    ShowMonthCalendar(false);
-    return;
-  }
-  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_DTP_TimeFormat))
-    ShowMonthCalendar(true);
-
-  m_bLBtnDown = true;
-  Repaint(&m_rtClient);
-}
-
-void IFWL_DateTimePicker::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  if (!pMsg)
-    return;
-
-  m_bLBtnDown = false;
-  if (m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    m_iBtnState = CFWL_PartState_Hovered;
-  else
-    m_iBtnState = CFWL_PartState_Normal;
-  Repaint(&m_rtBtn);
-}
-
-void IFWL_DateTimePicker::OnMouseMove(CFWL_MsgMouse* pMsg) {
-  if (!m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy))
-    m_iBtnState = CFWL_PartState_Normal;
-  Repaint(&m_rtBtn);
-}
-
-void IFWL_DateTimePicker::OnMouseLeave(CFWL_MsgMouse* pMsg) {
-  if (!pMsg)
-    return;
-  m_iBtnState = CFWL_PartState_Normal;
-  Repaint(&m_rtBtn);
-}
-
-void IFWL_DateTimePicker::DisForm_OnFocusChanged(CFWL_Message* pMsg,
-                                                 bool bSet) {
-  CFX_RectF rtInvalidate(m_rtBtn);
-  if (bSet) {
-    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
-    if (m_pEdit && !(m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)) {
-      m_rtBtn.Set(m_pProperties->m_rtWidget.width, 0, m_fBtn,
-                  m_pProperties->m_rtWidget.height - 1);
-    }
-    rtInvalidate = m_rtBtn;
-    pMsg->m_pDstTarget = m_pEdit.get();
-    m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
-  } else {
-    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
-    m_rtBtn.Set(0, 0, 0, 0);
-    if (DisForm_IsMonthCalendarVisible())
-      ShowMonthCalendar(false);
-    if (m_pEdit->GetStates() & FWL_WGTSTATE_Focused) {
-      pMsg->m_pSrcTarget = m_pEdit.get();
-      m_pEdit->GetDelegate()->OnProcessMessage(pMsg);
-    }
-  }
-  rtInvalidate.Inflate(2, 2);
-  Repaint(&rtInvalidate);
-}
diff --git a/xfa/fwl/core/ifwl_datetimepicker.h b/xfa/fwl/core/ifwl_datetimepicker.h
deleted file mode 100644
index b8bec96..0000000
--- a/xfa/fwl/core/ifwl_datetimepicker.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_DATETIMEPICKER_H_
-#define XFA_FWL_CORE_IFWL_DATETIMEPICKER_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_datetimeedit.h"
-#include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/cfwl_monthcalendar.h"
-#include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-
-#define FWL_STYLEEXT_DTP_AllowEdit (1L << 0)
-#define FWL_STYLEEXT_DTP_LongDateFormat (0L << 1)
-#define FWL_STYLEEXT_DTP_ShortDateFormat (1L << 1)
-#define FWL_STYLEEXT_DTP_TimeFormat (2L << 1)
-#define FWL_STYLEEXT_DTP_Spin (1L << 3)
-#define FWL_STYLEEXT_DTP_EditHNear (0L << 4)
-#define FWL_STYLEEXT_DTP_EditHCenter (1L << 4)
-#define FWL_STYLEEXT_DTP_EditHFar (2L << 4)
-#define FWL_STYLEEXT_DTP_EditVNear (0L << 6)
-#define FWL_STYLEEXT_DTP_EditVCenter (1L << 6)
-#define FWL_STYLEEXT_DTP_EditVFar (2L << 6)
-#define FWL_STYLEEXT_DTP_EditJustified (1L << 8)
-#define FWL_STYLEEXT_DTP_EditDistributed (2L << 8)
-#define FWL_STYLEEXT_DTP_EditHAlignMask (3L << 4)
-#define FWL_STYLEEXT_DTP_EditVAlignMask (3L << 6)
-#define FWL_STYLEEXT_DTP_EditHAlignModeMask (3L << 8)
-
-class CFWL_DateTimeEdit;
-class CFWL_FormProxy;
-
-class IFWL_DateTimePicker : public IFWL_Widget {
- public:
-  explicit IFWL_DateTimePicker(
-      const CFWL_App* app,
-      std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_DateTimePicker() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void Update() override;
-  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void SetThemeProvider(IFWL_ThemeProvider* pTP) override;
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
-  void GetCurSel(int32_t& iYear, int32_t& iMonth, int32_t& iDay);
-  void SetCurSel(int32_t iYear, int32_t iMonth, int32_t iDay);
-
-  void SetEditText(const CFX_WideString& wsText);
-  void GetEditText(CFX_WideString& wsText,
-                   int32_t nStart = 0,
-                   int32_t nCount = -1) const;
-
-  int32_t CountSelRanges() const { return m_pEdit->CountSelRanges(); }
-  int32_t GetSelRange(int32_t nIndex, int32_t& nStart) const {
-    return m_pEdit->GetSelRange(nIndex, nStart);
-  }
-
-  void GetBBox(CFX_RectF& rect) const;
-  void SetEditLimit(int32_t nLimit) { m_pEdit->SetLimit(nLimit); }
-  void ModifyEditStylesEx(uint32_t dwStylesExAdded, uint32_t dwStylesExRemoved);
-
-  bool IsMonthCalendarVisible() const;
-  void ShowMonthCalendar(bool bActivate);
-  void ProcessSelChanged(int32_t iYear, int32_t iMonth, int32_t iDay);
-
-  CFWL_FormProxy* GetFormProxy() const { return m_pForm.get(); }
-
- private:
-  void DrawDropDownButton(CFX_Graphics* pGraphics,
-                          IFWL_ThemeProvider* pTheme,
-                          const CFX_Matrix* pMatrix);
-  void FormatDateString(int32_t iYear,
-                        int32_t iMonth,
-                        int32_t iDay,
-                        CFX_WideString& wsText);
-  void ResetEditAlignment();
-  void InitProxyForm();
-
-  bool DisForm_IsMonthCalendarVisible() const;
-  void DisForm_ShowMonthCalendar(bool bActivate);
-  FWL_WidgetHit DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) const;
-  bool DisForm_IsNeedShowButton() const;
-  void DisForm_Update();
-  void DisForm_GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false);
-  void DisForm_GetBBox(CFX_RectF& rect) const;
-  void DisForm_DrawWidget(CFX_Graphics* pGraphics,
-                          const CFX_Matrix* pMatrix = nullptr);
-  void DisForm_OnFocusChanged(CFWL_Message* pMsg, bool bSet);
-  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
-  void OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnMouseMove(CFWL_MsgMouse* pMsg);
-  void OnMouseLeave(CFWL_MsgMouse* pMsg);
-
-  CFX_RectF m_rtBtn;
-  CFX_RectF m_rtClient;
-  int32_t m_iBtnState;
-  int32_t m_iYear;
-  int32_t m_iMonth;
-  int32_t m_iDay;
-  bool m_bLBtnDown;
-  std::unique_ptr<CFWL_DateTimeEdit> m_pEdit;
-  std::unique_ptr<CFWL_MonthCalendar> m_pMonthCal;
-  std::unique_ptr<CFWL_FormProxy> m_pForm;
-  FX_FLOAT m_fBtn;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_DATETIMEPICKER_H_
diff --git a/xfa/fwl/core/ifwl_edit.cpp b/xfa/fwl/core/ifwl_edit.cpp
deleted file mode 100644
index af29745..0000000
--- a/xfa/fwl/core/ifwl_edit.cpp
+++ /dev/null
@@ -1,1661 +0,0 @@
-// 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/core/ifwl_edit.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fde/fde_gedevice.h"
-#include "xfa/fde/fde_render.h"
-#include "xfa/fde/ifde_txtedtpage.h"
-#include "xfa/fgas/font/cfgas_gefont.h"
-#include "xfa/fwl/core/cfwl_app.h"
-#include "xfa/fwl/core/cfwl_caret.h"
-#include "xfa/fwl/core/cfwl_evtcheckword.h"
-#include "xfa/fwl/core/cfwl_evttextchanged.h"
-#include "xfa/fwl/core/cfwl_evttextfull.h"
-#include "xfa/fwl/core/cfwl_evtvalidate.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fxfa/xfa_ffdoc.h"
-#include "xfa/fxfa/xfa_ffwidget.h"
-#include "xfa/fxgraphics/cfx_path.h"
-
-namespace {
-
-const int kEditMargin = 3;
-
-bool FX_EDIT_ISLATINWORD(FX_WCHAR c) {
-  return c == 0x2D || (c <= 0x005A && c >= 0x0041) ||
-         (c <= 0x007A && c >= 0x0061) || (c <= 0x02AF && c >= 0x00C0) ||
-         c == 0x0027;
-}
-
-void AddSquigglyPath(CFX_Path* pPathData,
-                     FX_FLOAT fStartX,
-                     FX_FLOAT fEndX,
-                     FX_FLOAT fY,
-                     FX_FLOAT fStep) {
-  pPathData->MoveTo(fStartX, fY);
-  int i = 1;
-  for (FX_FLOAT fx = fStartX + fStep; fx < fEndX; fx += fStep, ++i)
-    pPathData->LineTo(fx, fY + (i & 1) * fStep);
-}
-
-}  // namespace
-
-IFWL_Edit::IFWL_Edit(const CFWL_App* app,
-                     std::unique_ptr<CFWL_WidgetProperties> properties,
-                     IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
-      m_fVAlignOffset(0.0f),
-      m_fScrollOffsetX(0.0f),
-      m_fScrollOffsetY(0.0f),
-      m_bLButtonDown(false),
-      m_nSelStart(0),
-      m_nLimit(-1),
-      m_fFontSize(0),
-      m_bSetRange(false),
-      m_iMax(0xFFFFFFF),
-      m_iCurRecord(-1),
-      m_iMaxRecord(128) {
-  m_rtClient.Reset();
-  m_rtEngine.Reset();
-  m_rtStatic.Reset();
-
-  InitCaret();
-}
-
-IFWL_Edit::~IFWL_Edit() {
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-    ShowCaret(false);
-  ClearRecord();
-}
-
-FWL_Type IFWL_Edit::GetClassID() const {
-  return FWL_Type::Edit;
-}
-
-void IFWL_Edit::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-      if (IsShowScrollBar(true)) {
-        FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
-            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-        rect.width += *pfWidth;
-        rect.width += kEditMargin;
-      }
-      if (IsShowScrollBar(false)) {
-        FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
-            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-        rect.height += *pfWidth;
-        rect.height += kEditMargin;
-      }
-    }
-    return;
-  }
-
-  rect.Set(0, 0, 0, 0);
-
-  int32_t iTextLen = m_EdtEngine.GetTextLength();
-  if (iTextLen > 0) {
-    CFX_WideString wsText;
-    m_EdtEngine.GetText(wsText, 0);
-    CFX_SizeF sz = CalcTextSize(
-        wsText, m_pProperties->m_pThemeProvider,
-        !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine));
-    rect.Set(0, 0, sz.x, sz.y);
-  }
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_Edit::SetStates(uint32_t dwStates, bool bSet) {
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) ||
-      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
-    ShowCaret(false);
-  }
-  IFWL_Widget::SetStates(dwStates, bSet);
-}
-
-void IFWL_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 IFWL_Edit::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-    if (IsShowScrollBar(true)) {
-      CFX_RectF rect;
-      m_pVertScrollBar->GetWidgetRect(rect);
-      if (rect.Contains(fx, fy))
-        return FWL_WidgetHit::VScrollBar;
-    }
-    if (IsShowScrollBar(false)) {
-      CFX_RectF rect;
-      m_pHorzScrollBar->GetWidgetRect(rect);
-      if (rect.Contains(fx, fy))
-        return FWL_WidgetHit::HScrollBar;
-    }
-  }
-  if (m_rtClient.Contains(fx, fy))
-    return FWL_WidgetHit::Edit;
-  return FWL_WidgetHit::Unknown;
-}
-
-void IFWL_Edit::AddSpellCheckObj(CFX_Path& PathData,
-                                 int32_t nStart,
-                                 int32_t nCount,
-                                 FX_FLOAT fOffSetX,
-                                 FX_FLOAT fOffSetY) {
-  FX_FLOAT fStartX = 0.0f;
-  FX_FLOAT fEndX = 0.0f;
-  FX_FLOAT fY = 0.0f;
-  FX_FLOAT fStep = 0.0f;
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  CFX_RectFArray rectArray;
-  CFX_RectF rectText;
-  const FDE_TXTEDTPARAMS* txtEdtParams = m_EdtEngine.GetEditParams();
-  FX_FLOAT fAsent = static_cast<FX_FLOAT>(txtEdtParams->pFont->GetAscent()) *
-                    txtEdtParams->fFontSize / 1000;
-  pPage->CalcRangeRectArray(nStart, nCount, rectArray);
-
-  for (int i = 0; i < rectArray.GetSize(); i++) {
-    rectText = rectArray.GetAt(i);
-    fY = rectText.top + fAsent + fOffSetY;
-    fStep = txtEdtParams->fFontSize / 16.0f;
-    fStartX = rectText.left + fOffSetX;
-    fEndX = fStartX + rectText.Width();
-    AddSquigglyPath(&PathData, fStartX, fEndX, fY, fStep);
-  }
-}
-
-void IFWL_Edit::DrawSpellCheck(CFX_Graphics* pGraphics,
-                               const CFX_Matrix* pMatrix) {
-  pGraphics->SaveGraphState();
-  if (pMatrix)
-    pGraphics->ConcatMatrix(const_cast<CFX_Matrix*>(pMatrix));
-
-  CFX_Color crLine(0xFFFF0000);
-  CFWL_EvtCheckWord checkWordEvent;
-  checkWordEvent.m_pSrcTarget = this;
-
-  CFX_ByteString sLatinWord;
-  CFX_Path pathSpell;
-  pathSpell.Create();
-
-  int32_t nStart = 0;
-  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
-  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
-
-  CFX_WideString wsSpell;
-  GetText(wsSpell);
-  int32_t nContentLen = wsSpell.GetLength();
-  for (int i = 0; i < nContentLen; i++) {
-    if (FX_EDIT_ISLATINWORD(wsSpell[i])) {
-      if (sLatinWord.IsEmpty())
-        nStart = i;
-      sLatinWord += (FX_CHAR)wsSpell[i];
-      continue;
-    }
-    checkWordEvent.bsWord = sLatinWord;
-    checkWordEvent.bCheckWord = true;
-    DispatchEvent(&checkWordEvent);
-
-    if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
-      AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
-                       fOffSetY);
-    }
-    sLatinWord.clear();
-  }
-
-  checkWordEvent.bsWord = sLatinWord;
-  checkWordEvent.bCheckWord = true;
-  DispatchEvent(&checkWordEvent);
-
-  if (!sLatinWord.IsEmpty() && !checkWordEvent.bCheckWord) {
-    AddSpellCheckObj(pathSpell, nStart, sLatinWord.GetLength(), fOffSetX,
-                     fOffSetY);
-  }
-  if (!pathSpell.IsEmpty()) {
-    CFX_RectF rtClip = m_rtEngine;
-    CFX_Matrix mt;
-    mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
-    if (pMatrix) {
-      pMatrix->TransformRect(rtClip);
-      mt.Concat(*pMatrix);
-    }
-    pGraphics->SetClipRect(rtClip);
-    pGraphics->SetStrokeColor(&crLine);
-    pGraphics->SetLineWidth(0);
-    pGraphics->StrokePath(&pathSpell, nullptr);
-  }
-  pGraphics->RestoreGraphState();
-}
-
-void IFWL_Edit::DrawWidget(CFX_Graphics* pGraphics, const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-  if (m_rtClient.IsEmpty())
-    return;
-
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  if (!m_pWidgetMgr->IsFormDisabled())
-    DrawTextBk(pGraphics, pTheme, pMatrix);
-  DrawContent(pGraphics, pTheme, pMatrix);
-
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
-      !(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly)) {
-    DrawSpellCheck(pGraphics, pMatrix);
-  }
-  if (HasBorder())
-    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-}
-
-void IFWL_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 IFWL_Edit::SetText(const CFX_WideString& wsText) {
-  m_EdtEngine.SetText(wsText);
-}
-
-int32_t IFWL_Edit::GetTextLength() const {
-  return m_EdtEngine.GetTextLength();
-}
-
-void IFWL_Edit::GetText(CFX_WideString& wsText,
-                        int32_t nStart,
-                        int32_t nCount) const {
-  m_EdtEngine.GetText(wsText, nStart, nCount);
-}
-
-void IFWL_Edit::ClearText() {
-  m_EdtEngine.ClearText();
-}
-
-void IFWL_Edit::AddSelRange(int32_t nStart, int32_t nCount) {
-  m_EdtEngine.AddSelRange(nStart, nCount);
-}
-
-int32_t IFWL_Edit::CountSelRanges() const {
-  return m_EdtEngine.CountSelRanges();
-}
-
-int32_t IFWL_Edit::GetSelRange(int32_t nIndex, int32_t& nStart) const {
-  return m_EdtEngine.GetSelRange(nIndex, nStart);
-}
-
-void IFWL_Edit::ClearSelections() {
-  m_EdtEngine.ClearSelection();
-}
-
-int32_t IFWL_Edit::GetLimit() const {
-  return m_nLimit;
-}
-
-void IFWL_Edit::SetLimit(int32_t nLimit) {
-  m_nLimit = nLimit;
-  m_EdtEngine.SetLimit(nLimit);
-}
-
-void IFWL_Edit::SetAliasChar(FX_WCHAR wAlias) {
-  m_EdtEngine.SetAliasChar(wAlias);
-}
-
-bool IFWL_Edit::Copy(CFX_WideString& wsCopy) {
-  int32_t nCount = m_EdtEngine.CountSelRanges();
-  if (nCount == 0)
-    return false;
-
-  wsCopy.clear();
-  CFX_WideString wsTemp;
-  int32_t nStart, nLength;
-  for (int32_t i = 0; i < nCount; i++) {
-    nLength = m_EdtEngine.GetSelRange(i, nStart);
-    m_EdtEngine.GetText(wsTemp, nStart, nLength);
-    wsCopy += wsTemp;
-    wsTemp.clear();
-  }
-  return true;
-}
-
-bool IFWL_Edit::Cut(CFX_WideString& wsCut) {
-  int32_t nCount = m_EdtEngine.CountSelRanges();
-  if (nCount == 0)
-    return false;
-
-  wsCut.clear();
-  CFX_WideString wsTemp;
-  int32_t nStart, nLength;
-  for (int32_t i = 0; i < nCount; i++) {
-    nLength = m_EdtEngine.GetSelRange(i, nStart);
-    m_EdtEngine.GetText(wsTemp, nStart, nLength);
-    wsCut += wsTemp;
-    wsTemp.clear();
-  }
-  m_EdtEngine.Delete(0);
-  return true;
-}
-
-bool IFWL_Edit::Paste(const CFX_WideString& wsPaste) {
-  int32_t nCaret = m_EdtEngine.GetCaretPos();
-  int32_t iError =
-      m_EdtEngine.Insert(nCaret, wsPaste.c_str(), wsPaste.GetLength());
-  if (iError < 0) {
-    ProcessInsertError(iError);
-    return false;
-  }
-  return true;
-}
-
-bool IFWL_Edit::Redo(const IFDE_TxtEdtDoRecord* pRecord) {
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
-    return true;
-  return m_EdtEngine.Redo(pRecord);
-}
-
-bool IFWL_Edit::Undo(const IFDE_TxtEdtDoRecord* pRecord) {
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoRedoUndo)
-    return true;
-  return m_EdtEngine.Undo(pRecord);
-}
-
-bool IFWL_Edit::Undo() {
-  if (!CanUndo())
-    return false;
-  return Undo(m_DoRecords[m_iCurRecord--].get());
-}
-
-bool IFWL_Edit::Redo() {
-  if (!CanRedo())
-    return false;
-  return Redo(m_DoRecords[++m_iCurRecord].get());
-}
-
-bool IFWL_Edit::CanUndo() {
-  return m_iCurRecord >= 0;
-}
-
-bool IFWL_Edit::CanRedo() {
-  return m_iCurRecord < pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
-}
-
-void IFWL_Edit::SetOuter(IFWL_Widget* pOuter) {
-  m_pOuter = pOuter;
-}
-
-void IFWL_Edit::On_CaretChanged(CFDE_TxtEdtEngine* pEdit,
-                                int32_t nPage,
-                                bool bVisible) {
-  if (m_rtEngine.IsEmpty())
-    return;
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    return;
-
-  bool bRepaintContent = UpdateOffset();
-  UpdateCaret();
-  CFX_RectF rtInvalid;
-  rtInvalid.Set(0, 0, 0, 0);
-  bool bRepaintScroll = false;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
-    CFWL_ScrollBar* pScroll = UpdateScroll();
-    if (pScroll) {
-      pScroll->GetWidgetRect(rtInvalid);
-      bRepaintScroll = true;
-    }
-  }
-  if (bRepaintContent || bRepaintScroll) {
-    if (bRepaintContent)
-      rtInvalid.Union(m_rtEngine);
-    Repaint(&rtInvalid);
-  }
-}
-
-void IFWL_Edit::On_TextChanged(CFDE_TxtEdtEngine* pEdit,
-                               FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo) {
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VAlignMask)
-    UpdateVAlignment();
-
-  CFX_RectF rtTemp;
-  GetClientRect(rtTemp);
-
-  CFWL_EvtTextChanged event;
-  event.m_pSrcTarget = this;
-  event.nChangeType = ChangeInfo.nChangeType;
-  event.wsInsert = ChangeInfo.wsInsert;
-  event.wsDelete = ChangeInfo.wsDelete;
-  event.wsPrevText = ChangeInfo.wsPrevText;
-  DispatchEvent(&event);
-
-  LayoutScrollBar();
-  Repaint(&rtTemp);
-}
-
-void IFWL_Edit::On_SelChanged(CFDE_TxtEdtEngine* pEdit) {
-  CFX_RectF rtTemp;
-  GetClientRect(rtTemp);
-  Repaint(&rtTemp);
-}
-
-bool IFWL_Edit::On_PageLoad(CFDE_TxtEdtEngine* pEdit,
-                            int32_t nPageIndex,
-                            int32_t nPurpose) {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
-  if (!pPage)
-    return false;
-
-  pPage->LoadPage(nullptr, nullptr);
-  return true;
-}
-
-bool IFWL_Edit::On_PageUnload(CFDE_TxtEdtEngine* pEdit,
-                              int32_t nPageIndex,
-                              int32_t nPurpose) {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(nPageIndex);
-  if (!pPage)
-    return false;
-
-  pPage->UnloadPage(nullptr);
-  return true;
-}
-
-void IFWL_Edit::On_AddDoRecord(CFDE_TxtEdtEngine* pEdit,
-                               IFDE_TxtEdtDoRecord* pRecord) {
-  AddDoRecord(pRecord);
-}
-
-bool IFWL_Edit::On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText) {
-  IFWL_Widget* pDst = GetOuter();
-  if (!pDst)
-    pDst = this;
-
-  CFWL_EvtValidate event;
-  event.pDstWidget = pDst;
-  event.m_pSrcTarget = this;
-  event.wsInsert = wsText;
-  event.bValidate = true;
-  DispatchEvent(&event);
-  return event.bValidate;
-}
-
-void IFWL_Edit::SetScrollOffset(FX_FLOAT fScrollOffset) {
-  m_fScrollOffsetY = fScrollOffset;
-}
-
-void IFWL_Edit::DrawTextBk(CFX_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 rtScorll;
-  m_pHorzScrollBar->GetWidgetRect(rtScorll);
-
-  CFX_RectF rtStatic;
-  rtStatic.Set(m_rtClient.right() - rtScorll.height,
-               m_rtClient.bottom() - rtScorll.height, rtScorll.height,
-               rtScorll.height);
-  param.m_bStaticBackground = true;
-  param.m_bMaximize = true;
-  param.m_rtPart = rtStatic;
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_Edit::DrawContent(CFX_Graphics* pGraphics,
-                            IFWL_ThemeProvider* pTheme,
-                            const CFX_Matrix* pMatrix) {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return;
-
-  pGraphics->SaveGraphState();
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
-    pGraphics->SaveGraphState();
-
-  CFX_RectF rtClip = m_rtEngine;
-  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
-  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
-  CFX_Matrix mt;
-  mt.Set(1, 0, 0, 1, fOffSetX, fOffSetY);
-  if (pMatrix) {
-    pMatrix->TransformRect(rtClip);
-    mt.Concat(*pMatrix);
-  }
-
-  bool bShowSel = (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_NoHideSel) ||
-                  (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
-  if (bShowSel) {
-    IFWL_Widget* pForm = m_pWidgetMgr->GetSystemFormWidget(this);
-    if (pForm) {
-      bShowSel = (pForm->GetStates() & FWL_WGTSTATE_Deactivated) !=
-                 FWL_WGTSTATE_Deactivated;
-    }
-  }
-
-  int32_t nSelCount = m_EdtEngine.CountSelRanges();
-  if (bShowSel && nSelCount > 0) {
-    int32_t nPageCharStart = pPage->GetCharStart();
-    int32_t nPageCharCount = pPage->GetCharCount();
-    int32_t nPageCharEnd = nPageCharStart + nPageCharCount - 1;
-    int32_t nCharCount;
-    int32_t nCharStart;
-    CFX_RectFArray rectArr;
-    int32_t i = 0;
-    for (i = 0; i < nSelCount; i++) {
-      nCharCount = m_EdtEngine.GetSelRange(i, nCharStart);
-      int32_t nCharEnd = nCharStart + nCharCount - 1;
-      if (nCharEnd < nPageCharStart || nCharStart > nPageCharEnd)
-        continue;
-
-      int32_t nBgn = std::max(nCharStart, nPageCharStart);
-      int32_t nEnd = std::min(nCharEnd, nPageCharEnd);
-      pPage->CalcRangeRectArray(nBgn - nPageCharStart, nEnd - nBgn + 1,
-                                rectArr);
-    }
-
-    int32_t nCount = rectArr.GetSize();
-    CFX_Path path;
-    path.Create();
-    for (i = 0; i < nCount; i++) {
-      rectArr[i].left += fOffSetX;
-      rectArr[i].top += fOffSetY;
-      path.AddRectangle(rectArr[i].left, rectArr[i].top, rectArr[i].width,
-                        rectArr[i].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();
-  if (!pRenderDev)
-    return;
-
-  std::unique_ptr<CFDE_RenderDevice> pRenderDevice(
-      new CFDE_RenderDevice(pRenderDev, false));
-  std::unique_ptr<CFDE_RenderContext> pRenderContext(new CFDE_RenderContext);
-  pRenderDevice->SetClipRect(rtClip);
-  pRenderContext->StartRender(pRenderDevice.get(), pPage, mt);
-  pRenderContext->DoRender(nullptr);
-
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText) {
-    pGraphics->RestoreGraphState();
-    CFX_Path path;
-    path.Create();
-    int32_t iLimit = m_nLimit > 0 ? m_nLimit : 1;
-    FX_FLOAT fStep = m_rtEngine.width / iLimit;
-    FX_FLOAT fLeft = m_rtEngine.left + 1;
-    for (int32_t i = 1; i < iLimit; i++) {
-      fLeft += fStep;
-      path.AddLine(fLeft, m_rtClient.top, 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 IFWL_Edit::UpdateEditEngine() {
-  UpdateEditParams();
-  UpdateEditLayout();
-  if (m_nLimit > -1)
-    m_EdtEngine.SetLimit(m_nLimit);
-}
-
-void IFWL_Edit::UpdateEditParams() {
-  FDE_TXTEDTPARAMS params;
-  params.nHorzScale = 100;
-  params.fPlateWidth = m_rtEngine.width;
-  params.fPlateHeight = m_rtEngine.height;
-  if (m_pProperties->m_dwStyles & FWL_WGTSTYLE_RTLLayout)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_RTL;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalLayout)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_DocVertical;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VerticalChars)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CharVertial;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReverseLine)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LineReserve;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ArabicShapes)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ArabicShapes;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ExpandTab)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_ExpandTab;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_CombText)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_CombText;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_LastLineHeight)
-    params.dwLayoutStyles |= FDE_TEXTEDITLAYOUT_LastLineHeight;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Validate)
-    params.dwMode |= FDE_TEXTEDITMODE_Validate;
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Password)
-    params.dwMode |= FDE_TEXTEDITMODE_Password;
-
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignMask) {
-    case FWL_STYLEEXT_EDT_HNear: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Left;
-      break;
-    }
-    case FWL_STYLEEXT_EDT_HCenter: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Center;
-      break;
-    }
-    case FWL_STYLEEXT_EDT_HFar: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Right;
-      break;
-    }
-    default:
-      break;
-  }
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_HAlignModeMask) {
-    case FWL_STYLEEXT_EDT_Justified: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Justified;
-      break;
-    }
-    case FWL_STYLEEXT_EDT_Distributed: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Distributed;
-      break;
-    }
-    default: {
-      params.dwAlignment |= FDE_TEXTEDITALIGN_Normal;
-      break;
-    }
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) {
-    params.dwMode |= FDE_TEXTEDITMODE_MultiLines;
-    if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) == 0 &&
-        (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) == 0) {
-      params.dwMode |=
-          FDE_TEXTEDITMODE_AutoLineWrap | FDE_TEXTEDITMODE_LimitArea_Horz;
-    }
-    if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) == 0 &&
-        (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoVScroll) == 0) {
-      params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Vert;
-    } else {
-      params.fPlateHeight = 0x00FFFFFF;
-    }
-  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_AutoHScroll) ==
-             0) {
-    params.dwMode |= FDE_TEXTEDITMODE_LimitArea_Horz;
-  }
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
-      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
-    params.dwMode |= FDE_TEXTEDITMODE_ReadOnly;
-  }
-
-  FX_FLOAT* pFontSize =
-      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
-  if (!pFontSize)
-    return;
-
-  m_fFontSize = *pFontSize;
-  uint32_t* pFontColor =
-      static_cast<uint32_t*>(GetThemeCapacity(CFWL_WidgetCapacity::TextColor));
-  if (!pFontColor)
-    return;
-
-  params.dwFontColor = *pFontColor;
-  FX_FLOAT* pLineHeight =
-      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::LineHeight));
-  if (!pLineHeight)
-    return;
-
-  params.fLineSpace = *pLineHeight;
-  CFGAS_GEFont* pFont =
-      static_cast<CFGAS_GEFont*>(GetThemeCapacity(CFWL_WidgetCapacity::Font));
-  if (!pFont)
-    return;
-
-  params.pFont = pFont;
-  params.fFontSize = m_fFontSize;
-  params.nLineCount = (int32_t)(params.fPlateHeight / params.fLineSpace);
-  if (params.nLineCount <= 0)
-    params.nLineCount = 1;
-  params.fTabWidth = params.fFontSize * 1;
-  params.bTabEquidistant = true;
-  params.wLineBreakChar = L'\n';
-  params.nCharRotation = 0;
-  params.pEventSink = this;
-  m_EdtEngine.SetEditParams(params);
-}
-
-void IFWL_Edit::UpdateEditLayout() {
-  if (m_EdtEngine.GetTextLength() <= 0)
-    m_EdtEngine.SetTextByStream(nullptr);
-
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (pPage)
-    pPage->UnloadPage(nullptr);
-
-  m_EdtEngine.StartLayout();
-  m_EdtEngine.DoLayout(nullptr);
-  m_EdtEngine.EndLayout();
-  pPage = m_EdtEngine.GetPage(0);
-  if (pPage)
-    pPage->LoadPage(nullptr, nullptr);
-}
-
-bool IFWL_Edit::UpdateOffset() {
-  CFX_RectF rtCaret;
-  m_EdtEngine.GetCaretRect(rtCaret);
-  FX_FLOAT fOffSetX = m_rtEngine.left - m_fScrollOffsetX;
-  FX_FLOAT fOffSetY = m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset;
-  rtCaret.Offset(fOffSetX, fOffSetY);
-  const CFX_RectF& rtEidt = m_rtEngine;
-  if (rtEidt.Contains(rtCaret)) {
-    IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-    if (!pPage)
-      return false;
-
-    CFX_RectF rtFDE = pPage->GetContentsBox();
-    rtFDE.Offset(fOffSetX, fOffSetY);
-    if (rtFDE.right() < rtEidt.right() && m_fScrollOffsetX > 0) {
-      m_fScrollOffsetX += rtFDE.right() - rtEidt.right();
-      m_fScrollOffsetX = std::max(m_fScrollOffsetX, 0.0f);
-    }
-    if (rtFDE.bottom() < rtEidt.bottom() && m_fScrollOffsetY > 0) {
-      m_fScrollOffsetY += rtFDE.bottom() - rtEidt.bottom();
-      m_fScrollOffsetY = std::max(m_fScrollOffsetY, 0.0f);
-    }
-    return false;
-  }
-
-  FX_FLOAT offsetX = 0.0;
-  FX_FLOAT offsetY = 0.0;
-  if (rtCaret.left < rtEidt.left)
-    offsetX = rtCaret.left - rtEidt.left;
-  if (rtCaret.right() > rtEidt.right())
-    offsetX = rtCaret.right() - rtEidt.right();
-  if (rtCaret.top < rtEidt.top)
-    offsetY = rtCaret.top - rtEidt.top;
-  if (rtCaret.bottom() > rtEidt.bottom())
-    offsetY = rtCaret.bottom() - rtEidt.bottom();
-  m_fScrollOffsetX += offsetX;
-  m_fScrollOffsetY += offsetY;
-  if (m_fFontSize > m_rtEngine.height)
-    m_fScrollOffsetY = 0;
-  return true;
-}
-
-bool IFWL_Edit::UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged) {
-  if (pScrollBar == m_pHorzScrollBar.get())
-    m_fScrollOffsetX += fPosChanged;
-  else
-    m_fScrollOffsetY += fPosChanged;
-  return true;
-}
-
-void IFWL_Edit::UpdateVAlignment() {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return;
-
-  const CFX_RectF& rtFDE = pPage->GetContentsBox();
-  FX_FLOAT fOffsetY = 0.0f;
-  FX_FLOAT fSpaceAbove = 0.0f;
-  FX_FLOAT fSpaceBelow = 0.0f;
-  CFX_SizeF* pSpace = static_cast<CFX_SizeF*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::SpaceAboveBelow));
-  if (pSpace) {
-    fSpaceAbove = pSpace->x;
-    fSpaceBelow = pSpace->y;
-  }
-  if (fSpaceAbove < 0.1f)
-    fSpaceAbove = 0;
-  if (fSpaceBelow < 0.1f)
-    fSpaceBelow = 0;
-
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VCenter) {
-    fOffsetY = (m_rtEngine.height - rtFDE.height) / 2;
-    if (fOffsetY < (fSpaceAbove + fSpaceBelow) / 2 &&
-        fSpaceAbove < fSpaceBelow) {
-      return;
-    }
-    fOffsetY += (fSpaceAbove - fSpaceBelow) / 2;
-  } else if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_VFar) {
-    fOffsetY = (m_rtEngine.height - rtFDE.height);
-    fOffsetY -= fSpaceBelow;
-  } else {
-    fOffsetY += fSpaceAbove;
-  }
-  m_fVAlignOffset = std::max(fOffsetY, 0.0f);
-}
-
-void IFWL_Edit::UpdateCaret() {
-  CFX_RectF rtFDE;
-  m_EdtEngine.GetCaretRect(rtFDE);
-
-  rtFDE.Offset(m_rtEngine.left - m_fScrollOffsetX,
-               m_rtEngine.top - m_fScrollOffsetY + m_fVAlignOffset);
-  CFX_RectF rtCaret;
-  rtCaret.Set(rtFDE.left, rtFDE.top, rtFDE.width, rtFDE.height);
-
-  CFX_RectF rtClient;
-  GetClientRect(rtClient);
-  rtCaret.Intersect(rtClient);
-
-  if (rtCaret.left > rtClient.right()) {
-    FX_FLOAT right = rtCaret.right();
-    rtCaret.left = rtClient.right() - 1;
-    rtCaret.width = right - rtCaret.left;
-  }
-
-  bool bShow =
-      m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && !rtCaret.IsEmpty();
-  ShowCaret(bShow, &rtCaret);
-}
-
-CFWL_ScrollBar* IFWL_Edit::UpdateScroll() {
-  bool bShowHorz =
-      m_pHorzScrollBar &&
-      ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
-  bool bShowVert =
-      m_pVertScrollBar &&
-      ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Invisible) == 0);
-  if (!bShowHorz && !bShowVert)
-    return nullptr;
-
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return nullptr;
-
-  const CFX_RectF& rtFDE = pPage->GetContentsBox();
-  CFWL_ScrollBar* pRepaint = nullptr;
-  if (bShowHorz) {
-    CFX_RectF rtScroll;
-    m_pHorzScrollBar->GetWidgetRect(rtScroll);
-    if (rtScroll.width < rtFDE.width) {
-      m_pHorzScrollBar->LockUpdate();
-      FX_FLOAT fRange = rtFDE.width - rtScroll.width;
-      m_pHorzScrollBar->SetRange(0.0f, fRange);
-
-      FX_FLOAT fPos = std::min(std::max(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->SetStates(FWL_WGTSTATE_Disabled, false);
-      m_pHorzScrollBar->UnlockUpdate();
-      m_pHorzScrollBar->Update();
-      pRepaint = m_pHorzScrollBar.get();
-    } else if ((m_pHorzScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
-      m_pHorzScrollBar->LockUpdate();
-      m_pHorzScrollBar->SetRange(0, -1);
-      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Disabled, true);
-      m_pHorzScrollBar->UnlockUpdate();
-      m_pHorzScrollBar->Update();
-      pRepaint = m_pHorzScrollBar.get();
-    }
-  }
-
-  if (bShowVert) {
-    CFX_RectF rtScroll;
-    m_pVertScrollBar->GetWidgetRect(rtScroll);
-    if (rtScroll.height < rtFDE.height) {
-      m_pVertScrollBar->LockUpdate();
-      FX_FLOAT fStep = m_EdtEngine.GetEditParams()->fLineSpace;
-      FX_FLOAT fRange = std::max(rtFDE.height - m_rtEngine.height, fStep);
-
-      m_pVertScrollBar->SetRange(0.0f, fRange);
-      FX_FLOAT fPos = std::min(std::max(m_fScrollOffsetY, 0.0f), fRange);
-      m_pVertScrollBar->SetPos(fPos);
-      m_pVertScrollBar->SetTrackPos(fPos);
-      m_pVertScrollBar->SetPageSize(rtScroll.height);
-      m_pVertScrollBar->SetStepSize(fStep);
-      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, false);
-      m_pVertScrollBar->UnlockUpdate();
-      m_pVertScrollBar->Update();
-      pRepaint = m_pVertScrollBar.get();
-    } else if ((m_pVertScrollBar->GetStates() & FWL_WGTSTATE_Disabled) == 0) {
-      m_pVertScrollBar->LockUpdate();
-      m_pVertScrollBar->SetRange(0, -1);
-      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Disabled, true);
-      m_pVertScrollBar->UnlockUpdate();
-      m_pVertScrollBar->Update();
-      pRepaint = m_pVertScrollBar.get();
-    }
-  }
-  return pRepaint;
-}
-
-bool IFWL_Edit::IsShowScrollBar(bool bVert) {
-  bool bShow =
-      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus)
-          ? (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) ==
-                FWL_WGTSTATE_Focused
-          : true;
-  if (bVert) {
-    return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll) &&
-           (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine) &&
-           IsContentHeightOverflow();
-  }
-  return bShow && (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) &&
-         (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_MultiLine);
-}
-
-bool IFWL_Edit::IsContentHeightOverflow() {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return false;
-  return pPage->GetContentsBox().height > m_rtEngine.height + 1.0f;
-}
-
-int32_t IFWL_Edit::AddDoRecord(IFDE_TxtEdtDoRecord* pRecord) {
-  int32_t nCount = pdfium::CollectionSize<int32_t>(m_DoRecords);
-  if (m_iCurRecord == nCount - 1) {
-    if (nCount == m_iMaxRecord) {
-      m_DoRecords.pop_front();
-      m_iCurRecord--;
-    }
-  } else {
-    m_DoRecords.erase(m_DoRecords.begin() + m_iCurRecord + 1,
-                      m_DoRecords.end());
-  }
-
-  m_DoRecords.push_back(std::unique_ptr<IFDE_TxtEdtDoRecord>(pRecord));
-  m_iCurRecord = pdfium::CollectionSize<int32_t>(m_DoRecords) - 1;
-  return m_iCurRecord;
-}
-
-void IFWL_Edit::Layout() {
-  GetClientRect(m_rtClient);
-  m_rtEngine = m_rtClient;
-  FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pfWidth)
-    return;
-
-  FX_FLOAT fWidth = *pfWidth;
-  if (!m_pOuter) {
-    CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
-        GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
-    if (pUIMargin) {
-      m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
-                         pUIMargin->height);
-    }
-  } else if (m_pOuter->GetClassID() == FWL_Type::DateTimePicker) {
-    CFWL_ThemePart part;
-    part.m_pWidget = m_pOuter;
-    CFX_RectF* pUIMargin =
-        static_cast<CFX_RectF*>(m_pOuter->GetThemeProvider()->GetCapacity(
-            &part, CFWL_WidgetCapacity::UIMargin));
-    if (pUIMargin) {
-      m_rtEngine.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
-                         pUIMargin->height);
-    }
-  }
-
-  bool bShowVertScrollbar = IsShowScrollBar(true);
-  bool bShowHorzScrollbar = IsShowScrollBar(false);
-  if (bShowVertScrollbar) {
-    InitScrollBar();
-
-    CFX_RectF rtVertScr;
-    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-      rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
-                    m_rtClient.height);
-    } else {
-      rtVertScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
-    m_pVertScrollBar->Update();
-  } else if (m_pVertScrollBar) {
-    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-
-  if (bShowHorzScrollbar) {
-    InitScrollBar(false);
-
-    CFX_RectF rtHoriScr;
-    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-      rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
-                    m_rtClient.width, fWidth);
-    } else {
-      rtHoriScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
-    m_pHorzScrollBar->Update();
-  } else if (m_pHorzScrollBar) {
-    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-}
-
-void IFWL_Edit::LayoutScrollBar() {
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ShowScrollbarFocus) ==
-      0) {
-    return;
-  }
-
-  FX_FLOAT* pfWidth = nullptr;
-  bool bShowVertScrollbar = IsShowScrollBar(true);
-  bool bShowHorzScrollbar = IsShowScrollBar(false);
-  if (bShowVertScrollbar) {
-    if (!m_pVertScrollBar) {
-      pfWidth = static_cast<FX_FLOAT*>(
-          GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-      FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
-      InitScrollBar();
-      CFX_RectF rtVertScr;
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-        rtVertScr.Set(m_rtClient.right() + kEditMargin, m_rtClient.top, fWidth,
-                      m_rtClient.height);
-      } else {
-        rtVertScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
-  } else if (m_pVertScrollBar) {
-    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-
-  if (bShowHorzScrollbar) {
-    if (!m_pHorzScrollBar) {
-      if (!pfWidth) {
-        pfWidth = static_cast<FX_FLOAT*>(
-            GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-      }
-
-      FX_FLOAT fWidth = pfWidth ? *pfWidth : 0;
-      InitScrollBar(false);
-      CFX_RectF rtHoriScr;
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_OuterScrollbar) {
-        rtHoriScr.Set(m_rtClient.left, m_rtClient.bottom() + kEditMargin,
-                      m_rtClient.width, fWidth);
-      } else {
-        rtHoriScr.Set(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->SetStates(FWL_WGTSTATE_Invisible, false);
-  } else if (m_pHorzScrollBar) {
-    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-  if (bShowVertScrollbar || bShowHorzScrollbar)
-    UpdateScroll();
-}
-
-void IFWL_Edit::DeviceToEngine(CFX_PointF& pt) {
-  pt.x += m_fScrollOffsetX - m_rtEngine.left;
-  pt.y += m_fScrollOffsetY - m_rtEngine.top - m_fVAlignOffset;
-}
-
-void IFWL_Edit::InitScrollBar(bool bVert) {
-  if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar))
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
-  prop->m_dwStates = FWL_WGTSTATE_Disabled | FWL_WGTSTATE_Invisible;
-  prop->m_pParent = this;
-  prop->m_pThemeProvider = m_pProperties->m_pThemeProvider;
-
-  CFWL_ScrollBar* sb = new CFWL_ScrollBar(m_pOwnerApp, std::move(prop), this);
-  if (bVert)
-    m_pVertScrollBar.reset(sb);
-  else
-    m_pHorzScrollBar.reset(sb);
-}
-
-bool FWL_ShowCaret(IFWL_Widget* pWidget,
-                   bool bVisible,
-                   const CFX_RectF* pRtAnchor) {
-  CXFA_FFWidget* pXFAWidget =
-      static_cast<CXFA_FFWidget*>(pWidget->GetLayoutItem());
-  if (!pXFAWidget)
-    return false;
-
-  IXFA_DocEnvironment* pDocEnvironment =
-      pXFAWidget->GetDoc()->GetDocEnvironment();
-  if (!pDocEnvironment)
-    return false;
-
-  if (bVisible) {
-    CFX_Matrix mt;
-    pXFAWidget->GetRotateMatrix(mt);
-    CFX_RectF rt(*pRtAnchor);
-    mt.TransformRect(rt);
-    pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, &rt);
-    return true;
-  }
-
-  pDocEnvironment->DisplayCaret(pXFAWidget, bVisible, pRtAnchor);
-  return true;
-}
-
-void IFWL_Edit::ShowCaret(bool bVisible, CFX_RectF* pRect) {
-  if (m_pCaret) {
-    m_pCaret->ShowCaret(bVisible);
-    if (bVisible && !pRect->IsEmpty())
-      m_pCaret->SetWidgetRect(*pRect);
-    Repaint(&m_rtEngine);
-    return;
-  }
-
-  IFWL_Widget* pOuter = this;
-  if (bVisible) {
-    pRect->Offset(m_pProperties->m_rtWidget.left,
-                  m_pProperties->m_rtWidget.top);
-  }
-  while (pOuter->GetOuter()) {
-    pOuter = pOuter->GetOuter();
-    if (bVisible) {
-      CFX_RectF rtOuter;
-      pOuter->GetWidgetRect(rtOuter);
-      pRect->Offset(rtOuter.left, rtOuter.top);
-    }
-  }
-  FWL_ShowCaret(pOuter, bVisible, pRect);
-}
-
-bool IFWL_Edit::ValidateNumberChar(FX_WCHAR cNum) {
-  if (!m_bSetRange)
-    return true;
-
-  CFX_WideString wsOld, wsText;
-  m_EdtEngine.GetText(wsText, 0);
-  if (wsText.IsEmpty()) {
-    if (cNum == L'0')
-      return false;
-    return true;
-  }
-
-  int32_t caretPos = m_EdtEngine.GetCaretPos();
-  if (CountSelRanges() == 0) {
-    if (cNum == L'0' && caretPos == 0)
-      return false;
-
-    int32_t nLen = wsText.GetLength();
-    CFX_WideString l = wsText.Mid(0, caretPos);
-    CFX_WideString r = wsText.Mid(caretPos, nLen - caretPos);
-    CFX_WideString wsNew = l + cNum + r;
-    if (wsNew.GetInteger() <= m_iMax)
-      return true;
-    return false;
-  }
-
-  if (wsText.GetInteger() <= m_iMax)
-    return true;
-  return false;
-}
-
-void IFWL_Edit::InitCaret() {
-  if (!m_pCaret) {
-    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret)) {
-      m_pCaret.reset(new CFWL_Caret(
-          m_pOwnerApp, pdfium::MakeUnique<CFWL_WidgetProperties>(), this));
-      m_pCaret->SetParent(this);
-      m_pCaret->SetStates(m_pProperties->m_dwStates);
-    }
-  } else if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_InnerCaret) ==
-             0) {
-    m_pCaret.reset();
-  }
-}
-
-void IFWL_Edit::ClearRecord() {
-  m_iCurRecord = -1;
-  m_DoRecords.clear();
-}
-
-void IFWL_Edit::ProcessInsertError(int32_t iError) {
-  if (iError != -2)
-    return;
-
-  CFWL_EvtTextFull textFullEvent;
-  textFullEvent.m_pSrcTarget = this;
-  DispatchEvent(&textFullEvent);
-}
-
-void IFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-
-  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
-  switch (dwMsgCode) {
-    case CFWL_MessageType::SetFocus:
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(pMessage, dwMsgCode == CFWL_MessageType::SetFocus);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonDblClk:
-          OnButtonDblClk(pMsg);
-          break;
-        case FWL_MouseCommand::Move:
-          OnMouseMove(pMsg);
-          break;
-        case FWL_MouseCommand::RightButtonDown:
-          DoButtonDown(pMsg);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
-      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
-        OnKeyDown(pKey);
-      else if (pKey->m_dwCmd == FWL_KeyCommand::Char)
-        OnChar(pKey);
-      break;
-    }
-    default:
-      break;
-  }
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_Edit::OnProcessEvent(CFWL_Event* pEvent) {
-  if (!pEvent)
-    return;
-  if (pEvent->GetClassID() != CFWL_EventType::Scroll)
-    return;
-
-  IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
-  if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
-      (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
-    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
-    OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
-             pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
-  }
-}
-
-void IFWL_Edit::OnDrawWidget(CFX_Graphics* pGraphics,
-                             const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_Edit::DoButtonDown(CFWL_MsgMouse* pMsg) {
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    SetFocus(true);
-
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return;
-
-  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
-  DeviceToEngine(pt);
-  bool bBefore = true;
-  int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
-  if (nIndex < 0)
-    nIndex = 0;
-
-  m_EdtEngine.SetCaretPos(nIndex, bBefore);
-}
-
-void IFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  uint32_t dwStyleEx = GetStylesEx();
-  bool bRepaint = !!(dwStyleEx & FWL_STYLEEXT_EDT_InnerCaret);
-  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;
-    ShowCaret(false);
-    if ((dwStyleEx & FWL_STYLEEXT_EDT_NoHideSel) == 0) {
-      int32_t nSel = CountSelRanges();
-      if (nSel > 0) {
-        ClearSelections();
-        bRepaint = true;
-      }
-      m_EdtEngine.SetCaretPos(0, true);
-      UpdateOffset();
-    }
-    ClearRecord();
-  }
-
-  LayoutScrollBar();
-  if (!bRepaint)
-    return;
-
-  CFX_RectF rtInvalidate;
-  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
-                   m_pProperties->m_rtWidget.height);
-  Repaint(&rtInvalidate);
-}
-
-void IFWL_Edit::OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    return;
-
-  m_bLButtonDown = true;
-  SetGrab(true);
-  DoButtonDown(pMsg);
-  int32_t nIndex = m_EdtEngine.GetCaretPos();
-  bool bRepaint = false;
-  if (m_EdtEngine.CountSelRanges() > 0) {
-    m_EdtEngine.ClearSelection();
-    bRepaint = true;
-  }
-
-  if ((pMsg->m_dwFlags & FWL_KEYFLAG_Shift) && m_nSelStart != nIndex) {
-    int32_t iStart = std::min(m_nSelStart, nIndex);
-    int32_t iEnd = std::max(m_nSelStart, nIndex);
-    m_EdtEngine.AddSelRange(iStart, iEnd - iStart);
-    bRepaint = true;
-  } else {
-    m_nSelStart = nIndex;
-  }
-  if (bRepaint)
-    Repaint(&m_rtEngine);
-}
-
-void IFWL_Edit::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  m_bLButtonDown = false;
-  SetGrab(false);
-}
-
-void IFWL_Edit::OnButtonDblClk(CFWL_MsgMouse* pMsg) {
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return;
-
-  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
-  DeviceToEngine(pt);
-  int32_t nCount = 0;
-  int32_t nIndex = pPage->SelectWord(pt, nCount);
-  if (nIndex < 0)
-    return;
-
-  m_EdtEngine.AddSelRange(nIndex, nCount);
-  m_EdtEngine.SetCaretPos(nIndex + nCount - 1, false);
-  Repaint(&m_rtEngine);
-}
-
-void IFWL_Edit::OnMouseMove(CFWL_MsgMouse* pMsg) {
-  if (m_nSelStart == -1 || !m_bLButtonDown)
-    return;
-
-  IFDE_TxtEdtPage* pPage = m_EdtEngine.GetPage(0);
-  if (!pPage)
-    return;
-
-  CFX_PointF pt(pMsg->m_fx, pMsg->m_fy);
-  DeviceToEngine(pt);
-  bool bBefore = true;
-  int32_t nIndex = pPage->GetCharIndex(pt, bBefore);
-  m_EdtEngine.SetCaretPos(nIndex, bBefore);
-  nIndex = m_EdtEngine.GetCaretPos();
-  m_EdtEngine.ClearSelection();
-
-  if (nIndex == m_nSelStart)
-    return;
-
-  int32_t nLen = m_EdtEngine.GetTextLength();
-  if (m_nSelStart >= nLen)
-    m_nSelStart = nLen;
-
-  m_EdtEngine.AddSelRange(std::min(m_nSelStart, nIndex),
-                          FXSYS_abs(nIndex - m_nSelStart));
-}
-
-void IFWL_Edit::OnKeyDown(CFWL_MsgKey* pMsg) {
-  FDE_TXTEDTMOVECARET MoveCaret = MC_MoveNone;
-  bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
-  bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);
-  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
-  switch (dwKeyCode) {
-    case FWL_VKEY_Left: {
-      MoveCaret = MC_Left;
-      break;
-    }
-    case FWL_VKEY_Right: {
-      MoveCaret = MC_Right;
-      break;
-    }
-    case FWL_VKEY_Up: {
-      MoveCaret = MC_Up;
-      break;
-    }
-    case FWL_VKEY_Down: {
-      MoveCaret = MC_Down;
-      break;
-    }
-    case FWL_VKEY_Home: {
-      MoveCaret = bCtrl ? MC_Home : MC_LineStart;
-      break;
-    }
-    case FWL_VKEY_End: {
-      MoveCaret = bCtrl ? MC_End : MC_LineEnd;
-      break;
-    }
-    case FWL_VKEY_Insert:
-      break;
-    case FWL_VKEY_Delete: {
-      if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
-          (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
-        break;
-      }
-      int32_t nCaret = m_EdtEngine.GetCaretPos();
-#if (_FX_OS_ == _FX_MACOSX_)
-      m_EdtEngine.Delete(nCaret, true);
-#else
-      m_EdtEngine.Delete(nCaret);
-#endif
-      break;
-    }
-    case FWL_VKEY_F2:
-      break;
-    case FWL_VKEY_Tab: {
-      DispatchKeyEvent(pMsg);
-      break;
-    }
-    default:
-      break;
-  }
-  if (MoveCaret != MC_MoveNone)
-    m_EdtEngine.MoveCaretPos(MoveCaret, bShift, bCtrl);
-}
-
-void IFWL_Edit::OnChar(CFWL_MsgKey* pMsg) {
-  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_ReadOnly) ||
-      (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)) {
-    return;
-  }
-
-  int32_t iError = 0;
-  FX_WCHAR c = static_cast<FX_WCHAR>(pMsg->m_dwKeyCode);
-  int32_t nCaret = m_EdtEngine.GetCaretPos();
-  switch (c) {
-    case FWL_VKEY_Back:
-      m_EdtEngine.Delete(nCaret, true);
-      break;
-    case FWL_VKEY_NewLine:
-    case FWL_VKEY_Escape:
-      break;
-    case FWL_VKEY_Tab: {
-      iError = m_EdtEngine.Insert(nCaret, L"\t", 1);
-      break;
-    }
-    case FWL_VKEY_Return: {
-      if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_WantReturn) {
-        iError = m_EdtEngine.Insert(nCaret, L"\n", 1);
-      }
-      break;
-    }
-    default: {
-      if (!m_pWidgetMgr->IsFormDisabled()) {
-        if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_EDT_Number) {
-          if (((pMsg->m_dwKeyCode < FWL_VKEY_0) &&
-               (pMsg->m_dwKeyCode != 0x2E && pMsg->m_dwKeyCode != 0x2D)) ||
-              pMsg->m_dwKeyCode > FWL_VKEY_9) {
-            break;
-          }
-          if (!ValidateNumberChar(c))
-            break;
-        }
-      }
-#if (_FX_OS_ == _FX_MACOSX_)
-      if (pMsg->m_dwFlags & FWL_KEYFLAG_Command)
-#else
-      if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl)
-#endif
-      {
-        break;
-      }
-      iError = m_EdtEngine.Insert(nCaret, &c, 1);
-      break;
-    }
-  }
-  if (iError < 0)
-    ProcessInsertError(iError);
-}
-
-bool IFWL_Edit::OnScroll(CFWL_ScrollBar* pScrollBar,
-                         FWL_SCBCODE dwCode,
-                         FX_FLOAT fPos) {
-  CFX_SizeF fs;
-  pScrollBar->GetRange(&fs.x, &fs.y);
-  FX_FLOAT iCurPos = pScrollBar->GetPos();
-  FX_FLOAT fStep = pScrollBar->GetStepSize();
-  switch (dwCode) {
-    case FWL_SCBCODE::Min: {
-      fPos = fs.x;
-      break;
-    }
-    case FWL_SCBCODE::Max: {
-      fPos = fs.y;
-      break;
-    }
-    case FWL_SCBCODE::StepBackward: {
-      fPos -= fStep;
-      if (fPos < fs.x + fStep / 2) {
-        fPos = fs.x;
-      }
-      break;
-    }
-    case FWL_SCBCODE::StepForward: {
-      fPos += fStep;
-      if (fPos > fs.y - fStep / 2) {
-        fPos = fs.y;
-      }
-      break;
-    }
-    case FWL_SCBCODE::PageBackward: {
-      fPos -= pScrollBar->GetPageSize();
-      if (fPos < fs.x) {
-        fPos = fs.x;
-      }
-      break;
-    }
-    case FWL_SCBCODE::PageForward: {
-      fPos += pScrollBar->GetPageSize();
-      if (fPos > fs.y) {
-        fPos = fs.y;
-      }
-      break;
-    }
-    case FWL_SCBCODE::Pos:
-    case FWL_SCBCODE::TrackPos:
-    case FWL_SCBCODE::None:
-      break;
-    case FWL_SCBCODE::EndScroll:
-      return false;
-  }
-  if (iCurPos == fPos)
-    return true;
-
-  pScrollBar->SetPos(fPos);
-  pScrollBar->SetTrackPos(fPos);
-  UpdateOffset(pScrollBar, fPos - iCurPos);
-  UpdateCaret();
-
-  CFX_RectF rect;
-  GetWidgetRect(rect);
-  CFX_RectF rtInvalidate;
-  rtInvalidate.Set(0, 0, rect.width + 2, rect.height + 2);
-  Repaint(&rtInvalidate);
-  return true;
-}
diff --git a/xfa/fwl/core/ifwl_edit.h b/xfa/fwl/core/ifwl_edit.h
deleted file mode 100644
index 8b217fa..0000000
--- a/xfa/fwl/core/ifwl_edit.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_EDIT_H_
-#define XFA_FWL_CORE_IFWL_EDIT_H_
-
-#include <deque>
-#include <memory>
-#include <vector>
-
-#include "xfa/fde/cfde_txtedtengine.h"
-#include "xfa/fde/ifde_txtedtdorecord.h"
-#include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/cfwl_scrollbar.h"
-#include "xfa/fwl/core/cfwl_widget.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-#include "xfa/fxgraphics/cfx_path.h"
-
-#define FWL_STYLEEXT_EDT_ReadOnly (1L << 0)
-#define FWL_STYLEEXT_EDT_MultiLine (1L << 1)
-#define FWL_STYLEEXT_EDT_WantReturn (1L << 2)
-#define FWL_STYLEEXT_EDT_NoHideSel (1L << 3)
-#define FWL_STYLEEXT_EDT_AutoHScroll (1L << 4)
-#define FWL_STYLEEXT_EDT_AutoVScroll (1L << 5)
-#define FWL_STYLEEXT_EDT_NoRedoUndo (1L << 6)
-#define FWL_STYLEEXT_EDT_Validate (1L << 7)
-#define FWL_STYLEEXT_EDT_Password (1L << 8)
-#define FWL_STYLEEXT_EDT_Number (1L << 9)
-#define FWL_STYLEEXT_EDT_VerticalLayout (1L << 12)
-#define FWL_STYLEEXT_EDT_VerticalChars (1L << 13)
-#define FWL_STYLEEXT_EDT_ReverseLine (1L << 14)
-#define FWL_STYLEEXT_EDT_ArabicShapes (1L << 15)
-#define FWL_STYLEEXT_EDT_ExpandTab (1L << 16)
-#define FWL_STYLEEXT_EDT_CombText (1L << 17)
-#define FWL_STYLEEXT_EDT_HNear (0L << 18)
-#define FWL_STYLEEXT_EDT_HCenter (1L << 18)
-#define FWL_STYLEEXT_EDT_HFar (2L << 18)
-#define FWL_STYLEEXT_EDT_VNear (0L << 20)
-#define FWL_STYLEEXT_EDT_VCenter (1L << 20)
-#define FWL_STYLEEXT_EDT_VFar (2L << 20)
-#define FWL_STYLEEXT_EDT_Justified (1L << 22)
-#define FWL_STYLEEXT_EDT_Distributed (2L << 22)
-#define FWL_STYLEEXT_EDT_HAlignMask (3L << 18)
-#define FWL_STYLEEXT_EDT_VAlignMask (3L << 20)
-#define FWL_STYLEEXT_EDT_HAlignModeMask (3L << 22)
-#define FWL_STYLEEXT_EDT_InnerCaret (1L << 24)
-#define FWL_STYLEEXT_EDT_ShowScrollbarFocus (1L << 25)
-#define FWL_STYLEEXT_EDT_OuterScrollbar (1L << 26)
-#define FWL_STYLEEXT_EDT_LastLineHeight (1L << 27)
-
-class IFDE_TxtEdtDoRecord;
-class IFWL_Edit;
-class CFWL_MsgMouse;
-class CFWL_WidgetProperties;
-class CFWL_Caret;
-
-class IFWL_Edit : public IFWL_Widget {
- public:
-  IFWL_Edit(const CFWL_App* app,
-            std::unique_ptr<CFWL_WidgetProperties> properties,
-            IFWL_Widget* pOuter);
-  ~IFWL_Edit() override;
-
-  // IFWL_Widget:
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void Update() override;
-  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
-  void SetStates(uint32_t dwStates, bool bSet = true) override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnProcessEvent(CFWL_Event* pEvent) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
-  virtual void SetText(const CFX_WideString& wsText);
-
-  int32_t GetTextLength() const;
-  void GetText(CFX_WideString& wsText,
-               int32_t nStart = 0,
-               int32_t nCount = -1) const;
-  void ClearText();
-
-  void AddSelRange(int32_t nStart, int32_t nCount = -1);
-  int32_t CountSelRanges() const;
-  int32_t GetSelRange(int32_t nIndex, int32_t& nStart) const;
-  void ClearSelections();
-  int32_t GetLimit() const;
-  void SetLimit(int32_t nLimit);
-  void SetAliasChar(FX_WCHAR wAlias);
-  bool Copy(CFX_WideString& wsCopy);
-  bool Cut(CFX_WideString& wsCut);
-  bool Paste(const CFX_WideString& wsPaste);
-  bool Redo(const IFDE_TxtEdtDoRecord* pRecord);
-  bool Undo(const IFDE_TxtEdtDoRecord* pRecord);
-  bool Undo();
-  bool Redo();
-  bool CanUndo();
-  bool CanRedo();
-
-  void SetOuter(IFWL_Widget* pOuter);
-
-  void On_CaretChanged(CFDE_TxtEdtEngine* pEdit,
-                       int32_t nPage,
-                       bool bVisible = true);
-  void On_TextChanged(CFDE_TxtEdtEngine* pEdit,
-                      FDE_TXTEDT_TEXTCHANGE_INFO& ChangeInfo);
-  void On_SelChanged(CFDE_TxtEdtEngine* pEdit);
-  bool On_PageLoad(CFDE_TxtEdtEngine* pEdit,
-                   int32_t nPageIndex,
-                   int32_t nPurpose);
-  bool On_PageUnload(CFDE_TxtEdtEngine* pEdit,
-                     int32_t nPageIndex,
-                     int32_t nPurpose);
-  void On_AddDoRecord(CFDE_TxtEdtEngine* pEdit, IFDE_TxtEdtDoRecord* pRecord);
-  bool On_Validate(CFDE_TxtEdtEngine* pEdit, CFX_WideString& wsText);
-  void SetScrollOffset(FX_FLOAT fScrollOffset);
-
- protected:
-  void ShowCaret(bool bVisible, CFX_RectF* pRect = nullptr);
-  const CFX_RectF& GetRTClient() const { return m_rtClient; }
-  CFDE_TxtEdtEngine* GetTxtEdtEngine() { return &m_EdtEngine; }
-
- private:
-  void DrawTextBk(CFX_Graphics* pGraphics,
-                  IFWL_ThemeProvider* pTheme,
-                  const CFX_Matrix* pMatrix = nullptr);
-  void DrawContent(CFX_Graphics* pGraphics,
-                   IFWL_ThemeProvider* pTheme,
-                   const CFX_Matrix* pMatrix = nullptr);
-  void UpdateEditEngine();
-  void UpdateEditParams();
-  void UpdateEditLayout();
-  bool UpdateOffset();
-  bool UpdateOffset(CFWL_ScrollBar* pScrollBar, FX_FLOAT fPosChanged);
-  void UpdateVAlignment();
-  void UpdateCaret();
-  CFWL_ScrollBar* UpdateScroll();
-  void Layout();
-  void LayoutScrollBar();
-  void DeviceToEngine(CFX_PointF& pt);
-  void InitScrollBar(bool bVert = true);
-  void InitEngine();
-  bool ValidateNumberChar(FX_WCHAR cNum);
-  void InitCaret();
-  void ClearRecord();
-  bool IsShowScrollBar(bool bVert);
-  bool IsContentHeightOverflow();
-  int32_t AddDoRecord(IFDE_TxtEdtDoRecord* pRecord);
-  void ProcessInsertError(int32_t iError);
-
-  void DrawSpellCheck(CFX_Graphics* pGraphics,
-                      const CFX_Matrix* pMatrix = nullptr);
-  void AddSpellCheckObj(CFX_Path& PathData,
-                        int32_t nStart,
-                        int32_t nCount,
-                        FX_FLOAT fOffSetX,
-                        FX_FLOAT fOffSetY);
-  void DoButtonDown(CFWL_MsgMouse* pMsg);
-  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
-  void OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnButtonDblClk(CFWL_MsgMouse* pMsg);
-  void OnMouseMove(CFWL_MsgMouse* pMsg);
-  void OnKeyDown(CFWL_MsgKey* pMsg);
-  void OnChar(CFWL_MsgKey* pMsg);
-  bool OnScroll(CFWL_ScrollBar* pScrollBar, FWL_SCBCODE dwCode, FX_FLOAT fPos);
-
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtEngine;
-  CFX_RectF m_rtStatic;
-  FX_FLOAT m_fVAlignOffset;
-  FX_FLOAT m_fScrollOffsetX;
-  FX_FLOAT m_fScrollOffsetY;
-  CFDE_TxtEdtEngine m_EdtEngine;
-  bool m_bLButtonDown;
-  int32_t m_nSelStart;
-  int32_t m_nLimit;
-  FX_FLOAT m_fFontSize;
-  bool m_bSetRange;
-  int32_t m_iMax;
-  std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar;
-  std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar;
-  std::unique_ptr<CFWL_Caret> m_pCaret;
-  CFX_WideString m_wsCache;
-  CFX_WideString m_wsFont;
-  std::deque<std::unique_ptr<IFDE_TxtEdtDoRecord>> m_DoRecords;
-  int32_t m_iCurRecord;
-  int32_t m_iMaxRecord;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_EDIT_H_
diff --git a/xfa/fwl/core/ifwl_listbox.cpp b/xfa/fwl/core/ifwl_listbox.cpp
deleted file mode 100644
index 6186e64..0000000
--- a/xfa/fwl/core/ifwl_listbox.cpp
+++ /dev/null
@@ -1,1126 +0,0 @@
-// 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/core/ifwl_listbox.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "third_party/base/stl_util.h"
-#include "xfa/fde/tto/fde_textout.h"
-#include "xfa/fwl/core/cfwl_app.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_msgmousewheel.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-namespace {
-
-const int kItemTextMargin = 2;
-
-}  // namespace
-
-IFWL_ListBox::IFWL_ListBox(const CFWL_App* app,
-                           std::unique_ptr<CFWL_WidgetProperties> properties,
-                           IFWL_Widget* pOuter)
-    : IFWL_Widget(app, std::move(properties), pOuter),
-      m_dwTTOStyles(0),
-      m_iTTOAligns(0),
-      m_hAnchor(nullptr),
-      m_fScorllBarWidth(0),
-      m_bLButtonDown(false),
-      m_pScrollBarTP(nullptr) {
-  m_rtClient.Reset();
-  m_rtConent.Reset();
-  m_rtStatic.Reset();
-}
-
-IFWL_ListBox::~IFWL_ListBox() {}
-
-FWL_Type IFWL_ListBox::GetClassID() const {
-  return FWL_Type::ListBox;
-}
-
-void IFWL_ListBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Set(0, 0, 0, 0);
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  CFX_SizeF fs = CalcSize(true);
-  rect.Set(0, 0, fs.x, fs.y);
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_ListBox::Update() {
-  if (IsLocked())
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) {
-    case FWL_STYLEEXT_LTB_LeftAlign: {
-      m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft;
-      break;
-    }
-    case FWL_STYLEEXT_LTB_RightAlign: {
-      m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight;
-      break;
-    }
-    case FWL_STYLEEXT_LTB_CenterAlign:
-    default: {
-      m_iTTOAligns = FDE_TTOALIGNMENT_Center;
-      break;
-    }
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
-    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
-
-  m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine;
-  m_fScorllBarWidth = GetScrollWidth();
-  CalcSize();
-}
-
-FWL_WidgetHit IFWL_ListBox::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  if (IsShowScrollBar(false)) {
-    CFX_RectF rect;
-    m_pHorzScrollBar->GetWidgetRect(rect);
-    if (rect.Contains(fx, fy))
-      return FWL_WidgetHit::HScrollBar;
-  }
-  if (IsShowScrollBar(true)) {
-    CFX_RectF rect;
-    m_pVertScrollBar->GetWidgetRect(rect);
-    if (rect.Contains(fx, fy))
-      return FWL_WidgetHit::VScrollBar;
-  }
-  if (m_rtClient.Contains(fx, fy))
-    return FWL_WidgetHit::Client;
-  return FWL_WidgetHit::Unknown;
-}
-
-void IFWL_ListBox::DrawWidget(CFX_Graphics* pGraphics,
-                              const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
-  pGraphics->SaveGraphState();
-  if (HasBorder())
-    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-
-  CFX_RectF rtClip(m_rtConent);
-  if (IsShowScrollBar(false))
-    rtClip.height -= m_fScorllBarWidth;
-  if (IsShowScrollBar(true))
-    rtClip.width -= m_fScorllBarWidth;
-  if (pMatrix)
-    pMatrix->TransformRect(rtClip);
-
-  pGraphics->SetClipRect(rtClip);
-  if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0)
-    DrawBkground(pGraphics, pTheme, pMatrix);
-
-  DrawItems(pGraphics, pTheme, pMatrix);
-  pGraphics->RestoreGraphState();
-}
-
-void IFWL_ListBox::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
-  if (pThemeProvider)
-    m_pProperties->m_pThemeProvider = pThemeProvider;
-}
-
-int32_t IFWL_ListBox::CountSelItems() {
-  int32_t iRet = 0;
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      continue;
-
-    uint32_t dwStyle = GetItemStyles(this, pItem);
-    if (dwStyle & FWL_ITEMSTATE_LTB_Selected)
-      iRet++;
-  }
-  return iRet;
-}
-
-CFWL_ListItem* IFWL_ListBox::GetSelItem(int32_t nIndexSel) {
-  int32_t idx = GetSelIndex(nIndexSel);
-  if (idx < 0)
-    return nullptr;
-  return GetItem(this, idx);
-}
-
-int32_t IFWL_ListBox::GetSelIndex(int32_t nIndex) {
-  int32_t index = 0;
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      return -1;
-
-    uint32_t dwStyle = GetItemStyles(this, pItem);
-    if (dwStyle & FWL_ITEMSTATE_LTB_Selected) {
-      if (index == nIndex)
-        return i;
-      index++;
-    }
-  }
-  return -1;
-}
-
-void IFWL_ListBox::SetSelItem(CFWL_ListItem* pItem, bool bSelect) {
-  if (!pItem) {
-    if (bSelect) {
-      SelectAll();
-    } else {
-      ClearSelection();
-      SetFocusItem(nullptr);
-    }
-    return;
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection)
-    SetSelectionDirect(pItem, bSelect);
-  else
-    SetSelection(pItem, pItem, bSelect);
-}
-
-void IFWL_ListBox::GetDataProviderItemText(CFWL_ListItem* pItem,
-                                           CFX_WideString& wsText) {
-  if (!pItem)
-    return;
-  GetItemText(this, pItem, wsText);
-}
-
-CFWL_ListItem* IFWL_ListBox::GetListItem(CFWL_ListItem* pItem,
-                                         uint32_t dwKeyCode) {
-  CFWL_ListItem* hRet = nullptr;
-  switch (dwKeyCode) {
-    case FWL_VKEY_Up:
-    case FWL_VKEY_Down:
-    case FWL_VKEY_Home:
-    case FWL_VKEY_End: {
-      const bool bUp = dwKeyCode == FWL_VKEY_Up;
-      const bool bDown = dwKeyCode == FWL_VKEY_Down;
-      const bool bHome = dwKeyCode == FWL_VKEY_Home;
-      int32_t iDstItem = -1;
-      if (bUp || bDown) {
-        int32_t index = GetItemIndex(this, pItem);
-        iDstItem = dwKeyCode == FWL_VKEY_Up ? index - 1 : index + 1;
-      } else if (bHome) {
-        iDstItem = 0;
-      } else {
-        int32_t iCount = CountItems(this);
-        iDstItem = iCount - 1;
-      }
-      hRet = GetItem(this, iDstItem);
-      break;
-    }
-    default:
-      break;
-  }
-  return hRet;
-}
-
-void IFWL_ListBox::SetSelection(CFWL_ListItem* hStart,
-                                CFWL_ListItem* hEnd,
-                                bool bSelected) {
-  int32_t iStart = GetItemIndex(this, hStart);
-  int32_t iEnd = GetItemIndex(this, hEnd);
-  if (iStart > iEnd) {
-    int32_t iTemp = iStart;
-    iStart = iEnd;
-    iEnd = iTemp;
-  }
-  if (bSelected) {
-    int32_t iCount = CountItems(this);
-    for (int32_t i = 0; i < iCount; i++) {
-      CFWL_ListItem* pItem = GetItem(this, i);
-      SetSelectionDirect(pItem, false);
-    }
-  }
-  for (; iStart <= iEnd; iStart++) {
-    CFWL_ListItem* pItem = GetItem(this, iStart);
-    SetSelectionDirect(pItem, bSelected);
-  }
-}
-
-void IFWL_ListBox::SetSelectionDirect(CFWL_ListItem* pItem, bool bSelect) {
-  uint32_t dwOldStyle = GetItemStyles(this, pItem);
-  bSelect ? dwOldStyle |= FWL_ITEMSTATE_LTB_Selected
-          : dwOldStyle &= ~FWL_ITEMSTATE_LTB_Selected;
-  SetItemStyles(this, pItem, dwOldStyle);
-}
-
-bool IFWL_ListBox::IsItemSelected(CFWL_ListItem* pItem) {
-  uint32_t dwState = GetItemStyles(this, pItem);
-  return (dwState & FWL_ITEMSTATE_LTB_Selected) != 0;
-}
-
-void IFWL_ListBox::ClearSelection() {
-  bool bMulti = m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection;
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    uint32_t dwState = GetItemStyles(this, pItem);
-    if (!(dwState & FWL_ITEMSTATE_LTB_Selected))
-      continue;
-    SetSelectionDirect(pItem, false);
-    if (!bMulti)
-      return;
-  }
-}
-
-void IFWL_ListBox::SelectAll() {
-  if (!m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection)
-    return;
-
-  int32_t iCount = CountItems(this);
-  if (iCount <= 0)
-    return;
-
-  CFWL_ListItem* pItemStart = GetItem(this, 0);
-  CFWL_ListItem* pItemEnd = GetItem(this, iCount - 1);
-  SetSelection(pItemStart, pItemEnd, false);
-}
-
-CFWL_ListItem* IFWL_ListBox::GetFocusedItem() {
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      return nullptr;
-    if (GetItemStyles(this, pItem) & FWL_ITEMSTATE_LTB_Focused)
-      return pItem;
-  }
-  return nullptr;
-}
-
-void IFWL_ListBox::SetFocusItem(CFWL_ListItem* pItem) {
-  CFWL_ListItem* hFocus = GetFocusedItem();
-  if (pItem == hFocus)
-    return;
-
-  if (hFocus) {
-    uint32_t dwStyle = GetItemStyles(this, hFocus);
-    dwStyle &= ~FWL_ITEMSTATE_LTB_Focused;
-    SetItemStyles(this, hFocus, dwStyle);
-  }
-  if (pItem) {
-    uint32_t dwStyle = GetItemStyles(this, pItem);
-    dwStyle |= FWL_ITEMSTATE_LTB_Focused;
-    SetItemStyles(this, pItem, dwStyle);
-  }
-}
-
-CFWL_ListItem* IFWL_ListBox::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) {
-  fx -= m_rtConent.left, fy -= m_rtConent.top;
-  FX_FLOAT fPosX = 0.0f;
-  if (m_pHorzScrollBar)
-    fPosX = m_pHorzScrollBar->GetPos();
-
-  FX_FLOAT fPosY = 0.0;
-  if (m_pVertScrollBar)
-    fPosY = m_pVertScrollBar->GetPos();
-
-  int32_t nCount = CountItems(this);
-  for (int32_t i = 0; i < nCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      continue;
-
-    CFX_RectF rtItem;
-    GetItemRect(this, pItem, rtItem);
-    rtItem.Offset(-fPosX, -fPosY);
-    if (rtItem.Contains(fx, fy))
-      return pItem;
-  }
-  return nullptr;
-}
-
-bool IFWL_ListBox::GetItemCheckRectInternal(CFWL_ListItem* pItem,
-                                            CFX_RectF& rtCheck) {
-  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
-    return false;
-  GetItemCheckRect(this, pItem, rtCheck);
-  return true;
-}
-
-bool IFWL_ListBox::GetItemChecked(CFWL_ListItem* pItem) {
-  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
-    return false;
-  return !!(GetItemCheckState(this, pItem) & FWL_ITEMSTATE_LTB_Checked);
-}
-
-bool IFWL_ListBox::SetItemChecked(CFWL_ListItem* pItem, bool bChecked) {
-  if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check))
-    return false;
-
-  SetItemCheckState(this, pItem, bChecked ? FWL_ITEMSTATE_LTB_Checked : 0);
-  return true;
-}
-
-bool IFWL_ListBox::ScrollToVisible(CFWL_ListItem* pItem) {
-  if (!m_pVertScrollBar)
-    return false;
-
-  CFX_RectF rtItem;
-  GetItemRect(this, pItem, rtItem);
-
-  bool bScroll = false;
-  FX_FLOAT fPosY = m_pVertScrollBar->GetPos();
-  rtItem.Offset(0, -fPosY + m_rtConent.top);
-  if (rtItem.top < m_rtConent.top) {
-    fPosY += rtItem.top - m_rtConent.top;
-    bScroll = true;
-  } else if (rtItem.bottom() > m_rtConent.bottom()) {
-    fPosY += rtItem.bottom() - m_rtConent.bottom();
-    bScroll = true;
-  }
-  if (!bScroll)
-    return false;
-
-  m_pVertScrollBar->SetPos(fPosY);
-  m_pVertScrollBar->SetTrackPos(fPosY);
-  Repaint(&m_rtClient);
-  return true;
-}
-
-void IFWL_ListBox::DrawBkground(CFX_Graphics* pGraphics,
-                                IFWL_ThemeProvider* pTheme,
-                                const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!pTheme)
-    return;
-
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = CFWL_Part::Background;
-  param.m_dwStates = 0;
-  param.m_pGraphics = pGraphics;
-  param.m_matrix.Concat(*pMatrix);
-  param.m_rtPart = m_rtClient;
-  if (IsShowScrollBar(false) && IsShowScrollBar(true))
-    param.m_pData = &m_rtStatic;
-  if (!IsEnabled())
-    param.m_dwStates = CFWL_PartState_Disabled;
-
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_ListBox::DrawItems(CFX_Graphics* pGraphics,
-                             IFWL_ThemeProvider* pTheme,
-                             const CFX_Matrix* pMatrix) {
-  FX_FLOAT fPosX = 0.0f;
-  if (m_pHorzScrollBar)
-    fPosX = m_pHorzScrollBar->GetPos();
-
-  FX_FLOAT fPosY = 0.0f;
-  if (m_pVertScrollBar)
-    fPosY = m_pVertScrollBar->GetPos();
-
-  CFX_RectF rtView(m_rtConent);
-  if (m_pHorzScrollBar)
-    rtView.height -= m_fScorllBarWidth;
-  if (m_pVertScrollBar)
-    rtView.width -= m_fScorllBarWidth;
-
-  bool bMultiCol =
-      !!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn);
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      continue;
-
-    CFX_RectF rtItem;
-    GetItemRect(this, pItem, rtItem);
-    rtItem.Offset(m_rtConent.left - fPosX, m_rtConent.top - fPosY);
-    if (rtItem.bottom() < m_rtConent.top)
-      continue;
-    if (rtItem.top >= m_rtConent.bottom())
-      break;
-    if (bMultiCol && rtItem.left > m_rtConent.right())
-      break;
-
-    if (!(GetStylesEx() & FWL_STYLEEXT_LTB_OwnerDraw))
-      DrawItem(pGraphics, pTheme, pItem, i, rtItem, pMatrix);
-  }
-}
-
-void IFWL_ListBox::DrawItem(CFX_Graphics* pGraphics,
-                            IFWL_ThemeProvider* pTheme,
-                            CFWL_ListItem* pItem,
-                            int32_t Index,
-                            const CFX_RectF& rtItem,
-                            const CFX_Matrix* pMatrix) {
-  uint32_t dwItemStyles = GetItemStyles(this, pItem);
-  uint32_t dwPartStates = CFWL_PartState_Normal;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    dwPartStates = CFWL_PartState_Disabled;
-  else if (dwItemStyles & FWL_ITEMSTATE_LTB_Selected)
-    dwPartStates = CFWL_PartState_Selected;
-
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused &&
-      dwItemStyles & FWL_ITEMSTATE_LTB_Focused) {
-    dwPartStates |= CFWL_PartState_Focused;
-  }
-
-  CFWL_ThemeBackground bg_param;
-  bg_param.m_pWidget = this;
-  bg_param.m_iPart = CFWL_Part::ListItem;
-  bg_param.m_dwStates = dwPartStates;
-  bg_param.m_pGraphics = pGraphics;
-  bg_param.m_matrix.Concat(*pMatrix);
-  bg_param.m_rtPart = rtItem;
-  bg_param.m_bMaximize = true;
-  CFX_RectF rtFocus(rtItem);
-  bg_param.m_pData = &rtFocus;
-  if (m_pVertScrollBar && !m_pHorzScrollBar &&
-      (dwPartStates & CFWL_PartState_Focused)) {
-    bg_param.m_rtPart.left += 1;
-    bg_param.m_rtPart.width -= (m_fScorllBarWidth + 1);
-    rtFocus.Deflate(0.5, 0.5, 1 + m_fScorllBarWidth, 1);
-  }
-  pTheme->DrawBackground(&bg_param);
-
-  bool bHasIcon = !!(GetStylesEx() & FWL_STYLEEXT_LTB_Icon);
-  if (bHasIcon) {
-    CFX_RectF rtDIB;
-    CFX_DIBitmap* pDib = GetItemIcon(this, pItem);
-    rtDIB.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
-    if (pDib) {
-      CFWL_ThemeBackground param;
-      param.m_pWidget = this;
-      param.m_iPart = CFWL_Part::Icon;
-      param.m_pGraphics = pGraphics;
-      param.m_matrix.Concat(*pMatrix);
-      param.m_rtPart = rtDIB;
-      param.m_bMaximize = true;
-      param.m_pImage = pDib;
-      pTheme->DrawBackground(&param);
-    }
-  }
-
-  bool bHasCheck = !!(GetStylesEx() & FWL_STYLEEXT_LTB_Check);
-  if (bHasCheck) {
-    CFX_RectF rtCheck;
-    rtCheck.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height);
-    rtCheck.Deflate(2, 2, 2, 2);
-    SetItemCheckRect(this, pItem, rtCheck);
-    CFWL_ThemeBackground param;
-    param.m_pWidget = this;
-    param.m_iPart = CFWL_Part::Check;
-    param.m_pGraphics = pGraphics;
-    if (GetItemChecked(pItem))
-      param.m_dwStates = CFWL_PartState_Checked;
-    else
-      param.m_dwStates = CFWL_PartState_Normal;
-    param.m_matrix.Concat(*pMatrix);
-    param.m_rtPart = rtCheck;
-    param.m_bMaximize = true;
-    pTheme->DrawBackground(&param);
-  }
-
-  CFX_WideString wsText;
-  GetItemText(this, pItem, wsText);
-  if (wsText.GetLength() <= 0)
-    return;
-
-  CFX_RectF rtText(rtItem);
-  rtText.Deflate(kItemTextMargin, kItemTextMargin);
-  if (bHasIcon || bHasCheck)
-    rtText.Deflate(rtItem.height, 0, 0, 0);
-
-  CFWL_ThemeText textParam;
-  textParam.m_pWidget = this;
-  textParam.m_iPart = CFWL_Part::ListItem;
-  textParam.m_dwStates = dwPartStates;
-  textParam.m_pGraphics = pGraphics;
-  textParam.m_matrix.Concat(*pMatrix);
-  textParam.m_rtPart = rtText;
-  textParam.m_wsText = wsText;
-  textParam.m_dwTTOStyles = m_dwTTOStyles;
-  textParam.m_iTTOAlign = m_iTTOAligns;
-  textParam.m_bMaximize = true;
-  pTheme->DrawText(&textParam);
-}
-
-CFX_SizeF IFWL_ListBox::CalcSize(bool bAutoSize) {
-  CFX_SizeF fs;
-  if (!m_pProperties->m_pThemeProvider)
-    return fs;
-
-  GetClientRect(m_rtClient);
-  m_rtConent = m_rtClient;
-  CFX_RectF rtUIMargin;
-  rtUIMargin.Set(0, 0, 0, 0);
-  if (!m_pOuter) {
-    CFX_RectF* pUIMargin = static_cast<CFX_RectF*>(
-        GetThemeCapacity(CFWL_WidgetCapacity::UIMargin));
-    if (pUIMargin) {
-      m_rtConent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
-                         pUIMargin->height);
-    }
-  }
-
-  FX_FLOAT fWidth = GetMaxTextWidth();
-  fWidth += 2 * kItemTextMargin;
-  if (!bAutoSize) {
-    FX_FLOAT fActualWidth =
-        m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
-    fWidth = std::max(fWidth, fActualWidth);
-  }
-
-  m_fItemHeight = CalcItemHeight();
-  if ((GetStylesEx() & FWL_STYLEEXT_LTB_Icon))
-    fWidth += m_fItemHeight;
-
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* htem = GetItem(this, i);
-    GetItemSize(fs, htem, fWidth, m_fItemHeight, bAutoSize);
-  }
-  if (bAutoSize)
-    return fs;
-
-  FX_FLOAT iWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width;
-  FX_FLOAT iHeight = m_rtClient.height;
-  bool bShowVertScr =
-      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
-      (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll);
-  bool bShowHorzScr =
-      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) &&
-      (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll);
-  if (!bShowVertScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll &&
-      (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) == 0) {
-    bShowVertScr = (fs.y > iHeight);
-  }
-  if (!bShowHorzScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll)
-    bShowHorzScr = (fs.x > iWidth);
-
-  CFX_SizeF szRange;
-  if (bShowVertScr) {
-    if (!m_pVertScrollBar)
-      InitScrollBar();
-
-    CFX_RectF rtScrollBar;
-    rtScrollBar.Set(m_rtClient.right() - m_fScorllBarWidth, m_rtClient.top,
-                    m_fScorllBarWidth, m_rtClient.height - 1);
-    if (bShowHorzScr)
-      rtScrollBar.height -= m_fScorllBarWidth;
-
-    m_pVertScrollBar->SetWidgetRect(rtScrollBar);
-    szRange.x = 0, szRange.y = fs.y - m_rtConent.height;
-    szRange.y = std::max(szRange.y, m_fItemHeight);
-
-    m_pVertScrollBar->SetRange(szRange.x, szRange.y);
-    m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10);
-    m_pVertScrollBar->SetStepSize(m_fItemHeight);
-
-    FX_FLOAT fPos =
-        std::min(std::max(m_pVertScrollBar->GetPos(), 0.f), szRange.y);
-    m_pVertScrollBar->SetPos(fPos);
-    m_pVertScrollBar->SetTrackPos(fPos);
-    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
-            0 ||
-        (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
-      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, false);
-    }
-    m_pVertScrollBar->Update();
-  } else if (m_pVertScrollBar) {
-    m_pVertScrollBar->SetPos(0);
-    m_pVertScrollBar->SetTrackPos(0);
-    m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-  if (bShowHorzScr) {
-    if (!m_pHorzScrollBar)
-      InitScrollBar(false);
-
-    CFX_RectF rtScrollBar;
-    rtScrollBar.Set(m_rtClient.left, m_rtClient.bottom() - m_fScorllBarWidth,
-                    m_rtClient.width, m_fScorllBarWidth);
-    if (bShowVertScr)
-      rtScrollBar.width -= m_fScorllBarWidth;
-
-    m_pHorzScrollBar->SetWidgetRect(rtScrollBar);
-    szRange.x = 0, szRange.y = fs.x - rtScrollBar.width;
-    m_pHorzScrollBar->SetRange(szRange.x, szRange.y);
-    m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10);
-    m_pHorzScrollBar->SetStepSize(fWidth / 10);
-
-    FX_FLOAT fPos =
-        std::min(std::max(m_pHorzScrollBar->GetPos(), 0.f), szRange.y);
-    m_pHorzScrollBar->SetPos(fPos);
-    m_pHorzScrollBar->SetTrackPos(fPos);
-    if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) ==
-            0 ||
-        (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) {
-      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, false);
-    }
-    m_pHorzScrollBar->Update();
-  } else if (m_pHorzScrollBar) {
-    m_pHorzScrollBar->SetPos(0);
-    m_pHorzScrollBar->SetTrackPos(0);
-    m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, true);
-  }
-  if (bShowVertScr && bShowHorzScr) {
-    m_rtStatic.Set(m_rtClient.right() - m_fScorllBarWidth,
-                   m_rtClient.bottom() - m_fScorllBarWidth, m_fScorllBarWidth,
-                   m_fScorllBarWidth);
-  }
-  return fs;
-}
-
-void IFWL_ListBox::GetItemSize(CFX_SizeF& size,
-                               CFWL_ListItem* pItem,
-                               FX_FLOAT fWidth,
-                               FX_FLOAT fItemHeight,
-                               bool bAutoSize) {
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn)
-    return;
-
-  if (!bAutoSize) {
-    CFX_RectF rtItem;
-    rtItem.Set(0, size.y, fWidth, fItemHeight);
-    SetItemRect(this, pItem, rtItem);
-  }
-  size.x = fWidth;
-  size.y += fItemHeight;
-}
-
-FX_FLOAT IFWL_ListBox::GetMaxTextWidth() {
-  FX_FLOAT fRet = 0.0f;
-  int32_t iCount = CountItems(this);
-  for (int32_t i = 0; i < iCount; i++) {
-    CFWL_ListItem* pItem = GetItem(this, i);
-    if (!pItem)
-      continue;
-
-    CFX_WideString wsText;
-    GetItemText(this, pItem, wsText);
-    CFX_SizeF sz = CalcTextSize(wsText, m_pProperties->m_pThemeProvider);
-    fRet = std::max(fRet, sz.x);
-  }
-  return fRet;
-}
-
-FX_FLOAT IFWL_ListBox::GetScrollWidth() {
-  FX_FLOAT* pfWidth = static_cast<FX_FLOAT*>(
-      GetThemeCapacity(CFWL_WidgetCapacity::ScrollBarWidth));
-  if (!pfWidth)
-    return 0;
-  return *pfWidth;
-}
-
-FX_FLOAT IFWL_ListBox::CalcItemHeight() {
-  FX_FLOAT* pfFont =
-      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::FontSize));
-  if (!pfFont)
-    return 20;
-  return *pfFont + 2 * kItemTextMargin;
-}
-
-void IFWL_ListBox::InitScrollBar(bool bVert) {
-  if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar))
-    return;
-
-  auto prop = pdfium::MakeUnique<CFWL_WidgetProperties>();
-  prop->m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz;
-  prop->m_dwStates = FWL_WGTSTATE_Invisible;
-  prop->m_pParent = this;
-  prop->m_pThemeProvider = m_pScrollBarTP;
-  CFWL_ScrollBar* sb = new CFWL_ScrollBar(m_pOwnerApp, std::move(prop), this);
-  if (bVert)
-    m_pVertScrollBar.reset(sb);
-  else
-    m_pHorzScrollBar.reset(sb);
-}
-
-bool IFWL_ListBox::IsShowScrollBar(bool bVert) {
-  CFWL_ScrollBar* pScrollbar =
-      bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get();
-  if (!pScrollbar || (pScrollbar->GetStates() & FWL_WGTSTATE_Invisible))
-    return false;
-  return !(m_pProperties->m_dwStyleExes &
-           FWL_STYLEEXT_LTB_ShowScrollBarFocus) ||
-         (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused);
-}
-
-void IFWL_ListBox::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-  if (!IsEnabled())
-    return;
-
-  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
-  switch (dwMsgCode) {
-    case CFWL_MessageType::SetFocus:
-      OnFocusChanged(pMessage, true);
-      break;
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(pMessage, false);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::MouseWheel:
-      OnMouseWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage));
-      break;
-    case CFWL_MessageType::Key: {
-      CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage);
-      if (pMsg->m_dwCmd == FWL_KeyCommand::KeyDown)
-        OnKeyDown(pMsg);
-      break;
-    }
-    default:
-      break;
-  }
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_ListBox::OnProcessEvent(CFWL_Event* pEvent) {
-  if (!pEvent)
-    return;
-  if (pEvent->GetClassID() != CFWL_EventType::Scroll)
-    return;
-
-  IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget;
-  if ((pSrcTarget == m_pVertScrollBar.get() && m_pVertScrollBar) ||
-      (pSrcTarget == m_pHorzScrollBar.get() && m_pHorzScrollBar)) {
-    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
-    OnScroll(static_cast<CFWL_ScrollBar*>(pSrcTarget),
-             pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos);
-  }
-}
-
-void IFWL_ListBox::OnDrawWidget(CFX_Graphics* pGraphics,
-                                const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_ListBox::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  if (GetStylesEx() & FWL_STYLEEXT_LTB_ShowScrollBarFocus) {
-    if (m_pVertScrollBar)
-      m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
-    if (m_pHorzScrollBar)
-      m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet);
-  }
-  if (bSet)
-    m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused);
-  else
-    m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused);
-
-  Repaint(&m_rtClient);
-}
-
-void IFWL_ListBox::OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  m_bLButtonDown = true;
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    SetFocus(true);
-
-  CFWL_ListItem* pItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
-  if (!pItem)
-    return;
-
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) {
-    if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) {
-      bool bSelected = IsItemSelected(pItem);
-      SetSelectionDirect(pItem, !bSelected);
-      m_hAnchor = pItem;
-    } else if (pMsg->m_dwFlags & FWL_KEYFLAG_Shift) {
-      if (m_hAnchor)
-        SetSelection(m_hAnchor, pItem, true);
-      else
-        SetSelectionDirect(pItem, true);
-    } else {
-      SetSelection(pItem, pItem, true);
-      m_hAnchor = pItem;
-    }
-  } else {
-    SetSelection(pItem, pItem, true);
-  }
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check) {
-    CFWL_ListItem* hSelectedItem = GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
-    CFX_RectF rtCheck;
-    GetItemCheckRectInternal(hSelectedItem, rtCheck);
-    bool bChecked = GetItemChecked(pItem);
-    if (rtCheck.Contains(pMsg->m_fx, pMsg->m_fy)) {
-      SetItemChecked(pItem, !bChecked);
-      Update();
-    }
-  }
-  SetFocusItem(pItem);
-  ScrollToVisible(pItem);
-  SetGrab(true);
-  Repaint(&m_rtClient);
-}
-
-void IFWL_ListBox::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  if (!m_bLButtonDown)
-    return;
-
-  m_bLButtonDown = false;
-  SetGrab(false);
-}
-
-void IFWL_ListBox::OnMouseWheel(CFWL_MsgMouseWheel* pMsg) {
-  if (IsShowScrollBar(true))
-    m_pVertScrollBar->GetDelegate()->OnProcessMessage(pMsg);
-}
-
-void IFWL_ListBox::OnKeyDown(CFWL_MsgKey* pMsg) {
-  uint32_t dwKeyCode = pMsg->m_dwKeyCode;
-  switch (dwKeyCode) {
-    case FWL_VKEY_Tab:
-    case FWL_VKEY_Up:
-    case FWL_VKEY_Down:
-    case FWL_VKEY_Home:
-    case FWL_VKEY_End: {
-      CFWL_ListItem* pItem = GetFocusedItem();
-      pItem = GetListItem(pItem, dwKeyCode);
-      bool bShift = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift);
-      bool bCtrl = !!(pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl);
-      OnVK(pItem, bShift, bCtrl);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-void IFWL_ListBox::OnVK(CFWL_ListItem* pItem, bool bShift, bool bCtrl) {
-  if (!pItem)
-    return;
-
-  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) {
-    if (bCtrl) {
-      // Do nothing.
-    } else if (bShift) {
-      if (m_hAnchor)
-        SetSelection(m_hAnchor, pItem, true);
-      else
-        SetSelectionDirect(pItem, true);
-    } else {
-      SetSelection(pItem, pItem, true);
-      m_hAnchor = pItem;
-    }
-  } else {
-    SetSelection(pItem, pItem, true);
-  }
-
-  SetFocusItem(pItem);
-  ScrollToVisible(pItem);
-
-  CFX_RectF rtInvalidate;
-  rtInvalidate.Set(0, 0, m_pProperties->m_rtWidget.width,
-                   m_pProperties->m_rtWidget.height);
-  Repaint(&rtInvalidate);
-}
-
-bool IFWL_ListBox::OnScroll(CFWL_ScrollBar* pScrollBar,
-                            FWL_SCBCODE dwCode,
-                            FX_FLOAT fPos) {
-  CFX_SizeF fs;
-  pScrollBar->GetRange(&fs.x, &fs.y);
-  FX_FLOAT iCurPos = pScrollBar->GetPos();
-  FX_FLOAT fStep = pScrollBar->GetStepSize();
-  switch (dwCode) {
-    case FWL_SCBCODE::Min: {
-      fPos = fs.x;
-      break;
-    }
-    case FWL_SCBCODE::Max: {
-      fPos = fs.y;
-      break;
-    }
-    case FWL_SCBCODE::StepBackward: {
-      fPos -= fStep;
-      if (fPos < fs.x + fStep / 2)
-        fPos = fs.x;
-      break;
-    }
-    case FWL_SCBCODE::StepForward: {
-      fPos += fStep;
-      if (fPos > fs.y - fStep / 2)
-        fPos = fs.y;
-      break;
-    }
-    case FWL_SCBCODE::PageBackward: {
-      fPos -= pScrollBar->GetPageSize();
-      if (fPos < fs.x)
-        fPos = fs.x;
-      break;
-    }
-    case FWL_SCBCODE::PageForward: {
-      fPos += pScrollBar->GetPageSize();
-      if (fPos > fs.y)
-        fPos = fs.y;
-      break;
-    }
-    case FWL_SCBCODE::Pos:
-    case FWL_SCBCODE::TrackPos:
-    case FWL_SCBCODE::None:
-      break;
-    case FWL_SCBCODE::EndScroll:
-      return false;
-  }
-  if (iCurPos != fPos) {
-    pScrollBar->SetPos(fPos);
-    pScrollBar->SetTrackPos(fPos);
-    Repaint(&m_rtClient);
-  }
-  return true;
-}
-
-void IFWL_ListBox::GetItemText(IFWL_Widget* pWidget,
-                               CFWL_ListItem* pItem,
-                               CFX_WideString& wsText) {
-  if (pItem)
-    wsText = static_cast<CFWL_ListItem*>(pItem)->m_wsText;
-}
-
-int32_t IFWL_ListBox::CountItems(const IFWL_Widget* pWidget) const {
-  return pdfium::CollectionSize<int32_t>(m_ItemArray);
-}
-
-CFWL_ListItem* IFWL_ListBox::GetItem(const IFWL_Widget* pWidget,
-                                     int32_t nIndex) const {
-  if (nIndex < 0 || nIndex >= CountItems(pWidget))
-    return nullptr;
-  return m_ItemArray[nIndex].get();
-}
-
-int32_t IFWL_ListBox::GetItemIndex(IFWL_Widget* pWidget, CFWL_ListItem* pItem) {
-  auto it = std::find_if(
-      m_ItemArray.begin(), m_ItemArray.end(),
-      [pItem](const std::unique_ptr<CFWL_ListItem>& candidate) {
-        return candidate.get() == static_cast<CFWL_ListItem*>(pItem);
-      });
-  return it != m_ItemArray.end() ? it - m_ItemArray.begin() : -1;
-}
-
-uint32_t IFWL_ListBox::GetItemStyles(IFWL_Widget* pWidget,
-                                     CFWL_ListItem* pItem) {
-  return pItem ? static_cast<CFWL_ListItem*>(pItem)->m_dwStates : 0;
-}
-
-void IFWL_ListBox::GetItemRect(IFWL_Widget* pWidget,
-                               CFWL_ListItem* pItem,
-                               CFX_RectF& rtItem) {
-  if (pItem)
-    rtItem = static_cast<CFWL_ListItem*>(pItem)->m_rtItem;
-}
-
-void* IFWL_ListBox::GetItemData(IFWL_Widget* pWidget, CFWL_ListItem* pItem) {
-  return pItem ? static_cast<CFWL_ListItem*>(pItem)->m_pData : nullptr;
-}
-
-void IFWL_ListBox::SetItemStyles(IFWL_Widget* pWidget,
-                                 CFWL_ListItem* pItem,
-                                 uint32_t dwStyle) {
-  if (pItem)
-    static_cast<CFWL_ListItem*>(pItem)->m_dwStates = dwStyle;
-}
-
-void IFWL_ListBox::SetItemRect(IFWL_Widget* pWidget,
-                               CFWL_ListItem* pItem,
-                               const CFX_RectF& rtItem) {
-  if (pItem)
-    static_cast<CFWL_ListItem*>(pItem)->m_rtItem = rtItem;
-}
-
-CFX_DIBitmap* IFWL_ListBox::GetItemIcon(IFWL_Widget* pWidget,
-                                        CFWL_ListItem* pItem) {
-  return static_cast<CFWL_ListItem*>(pItem)->m_pDIB;
-}
-
-void IFWL_ListBox::GetItemCheckRect(IFWL_Widget* pWidget,
-                                    CFWL_ListItem* pItem,
-                                    CFX_RectF& rtCheck) {
-  rtCheck = static_cast<CFWL_ListItem*>(pItem)->m_rtCheckBox;
-}
-
-void IFWL_ListBox::SetItemCheckRect(IFWL_Widget* pWidget,
-                                    CFWL_ListItem* pItem,
-                                    const CFX_RectF& rtCheck) {
-  static_cast<CFWL_ListItem*>(pItem)->m_rtCheckBox = rtCheck;
-}
-
-uint32_t IFWL_ListBox::GetItemCheckState(IFWL_Widget* pWidget,
-                                         CFWL_ListItem* pItem) {
-  return static_cast<CFWL_ListItem*>(pItem)->m_dwCheckState;
-}
-
-void IFWL_ListBox::SetItemCheckState(IFWL_Widget* pWidget,
-                                     CFWL_ListItem* pItem,
-                                     uint32_t dwCheckState) {
-  static_cast<CFWL_ListItem*>(pItem)->m_dwCheckState = dwCheckState;
-}
-
-CFWL_ListItem* IFWL_ListBox::AddString(const CFX_WideStringC& wsAdd,
-                                       bool bSelect) {
-  auto pItem = pdfium::MakeUnique<CFWL_ListItem>();
-  pItem->m_dwStates = 0;
-  pItem->m_wsText = wsAdd;
-  pItem->m_dwStates = bSelect ? FWL_ITEMSTATE_LTB_Selected : 0;
-  m_ItemArray.push_back(std::move(pItem));
-  return m_ItemArray.back().get();
-}
-
-bool IFWL_ListBox::RemoveAt(int32_t iIndex) {
-  if (iIndex < 0 || static_cast<size_t>(iIndex) >= m_ItemArray.size())
-    return false;
-
-  m_ItemArray.erase(m_ItemArray.begin() + iIndex);
-  return true;
-}
-
-bool IFWL_ListBox::DeleteString(CFWL_ListItem* pItem) {
-  int32_t nIndex = GetItemIndex(this, pItem);
-  if (nIndex < 0 || static_cast<size_t>(nIndex) >= m_ItemArray.size())
-    return false;
-
-  int32_t iSel = nIndex + 1;
-  if (iSel >= CountItems(this))
-    iSel = nIndex - 1;
-  if (iSel >= 0) {
-    CFWL_ListItem* pSel = static_cast<CFWL_ListItem*>(GetItem(this, iSel));
-    pSel->m_dwStates |= FWL_ITEMSTATE_LTB_Selected;
-  }
-  m_ItemArray.erase(m_ItemArray.begin() + nIndex);
-  return true;
-}
-
-void IFWL_ListBox::DeleteAll() {
-  m_ItemArray.clear();
-}
diff --git a/xfa/fwl/core/ifwl_listbox.h b/xfa/fwl/core/ifwl_listbox.h
deleted file mode 100644
index a8638eb..0000000
--- a/xfa/fwl/core/ifwl_listbox.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_LISTBOX_H_
-#define XFA_FWL_CORE_IFWL_LISTBOX_H_
-
-#include <memory>
-#include <vector>
-
-#include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/cfwl_listitem.h"
-#include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-
-#define FWL_STYLEEXT_LTB_MultiSelection (1L << 0)
-#define FWL_STYLEEXT_LTB_ShowScrollBarAlaways (1L << 2)
-#define FWL_STYLEEXT_LTB_MultiColumn (1L << 3)
-#define FWL_STYLEEXT_LTB_LeftAlign (0L << 4)
-#define FWL_STYLEEXT_LTB_CenterAlign (1L << 4)
-#define FWL_STYLEEXT_LTB_RightAlign (2L << 4)
-#define FWL_STYLEEXT_LTB_MultiLine (1L << 6)
-#define FWL_STYLEEXT_LTB_OwnerDraw (1L << 7)
-#define FWL_STYLEEXT_LTB_Icon (1L << 8)
-#define FWL_STYLEEXT_LTB_Check (1L << 9)
-#define FWL_STYLEEXT_LTB_AlignMask (3L << 4)
-#define FWL_STYLEEXT_LTB_ShowScrollBarFocus (1L << 10)
-#define FWL_ITEMSTATE_LTB_Selected (1L << 0)
-#define FWL_ITEMSTATE_LTB_Focused (1L << 1)
-#define FWL_ITEMSTATE_LTB_Checked (1L << 2)
-
-class CFWL_MsgKillFocus;
-class CFWL_MsgMouse;
-class CFWL_MsgMouseWheel;
-class CFX_DIBitmap;
-
-class IFWL_ListBox : public IFWL_Widget {
- public:
-  IFWL_ListBox(const CFWL_App* app,
-               std::unique_ptr<CFWL_WidgetProperties> properties,
-               IFWL_Widget* pOuter);
-  ~IFWL_ListBox() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void Update() override;
-  FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy) override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) override;
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnProcessEvent(CFWL_Event* pEvent) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
-  int32_t CountItems(const IFWL_Widget* pWidget) const;
-  CFWL_ListItem* GetItem(const IFWL_Widget* pWidget, int32_t nIndex) const;
-  int32_t GetItemIndex(IFWL_Widget* pWidget, CFWL_ListItem* pItem);
-  uint32_t GetItemStyles(IFWL_Widget* pWidget, CFWL_ListItem* pItem);
-  void GetItemText(IFWL_Widget* pWidget,
-                   CFWL_ListItem* pItem,
-                   CFX_WideString& wsText);
-  void GetItemRect(IFWL_Widget* pWidget,
-                   CFWL_ListItem* pItem,
-                   CFX_RectF& rtItem);
-  void* GetItemData(IFWL_Widget* pWidget, CFWL_ListItem* pItem);
-  void SetItemStyles(IFWL_Widget* pWidget,
-                     CFWL_ListItem* pItem,
-                     uint32_t dwStyle);
-  void SetItemRect(IFWL_Widget* pWidget,
-                   CFWL_ListItem* pItem,
-                   const CFX_RectF& rtItem);
-  CFX_DIBitmap* GetItemIcon(IFWL_Widget* pWidget, CFWL_ListItem* pItem);
-  void GetItemCheckRect(IFWL_Widget* pWidget,
-                        CFWL_ListItem* pItem,
-                        CFX_RectF& rtCheck);
-  void SetItemCheckRect(IFWL_Widget* pWidget,
-                        CFWL_ListItem* pItem,
-                        const CFX_RectF& rtCheck);
-  uint32_t GetItemCheckState(IFWL_Widget* pWidget, CFWL_ListItem* pItem);
-  void SetItemCheckState(IFWL_Widget* pWidget,
-                         CFWL_ListItem* pItem,
-                         uint32_t dwCheckState);
-  CFWL_ListItem* AddString(const CFX_WideStringC& wsAdd, bool bSelect = false);
-  bool RemoveAt(int32_t iIndex);
-  bool DeleteString(CFWL_ListItem* pItem);
-  void DeleteAll();
-
-  int32_t CountSelItems();
-  CFWL_ListItem* GetSelItem(int32_t nIndexSel);
-  int32_t GetSelIndex(int32_t nIndex);
-  void SetSelItem(CFWL_ListItem* hItem, bool bSelect = true);
-  void GetDataProviderItemText(CFWL_ListItem* hItem, CFX_WideString& wsText);
-
-  FX_FLOAT GetItemHeight() const { return m_fItemHeight; }
-  FX_FLOAT CalcItemHeight();
-
- protected:
-  CFWL_ListItem* GetListItem(CFWL_ListItem* hItem, uint32_t dwKeyCode);
-  void SetSelection(CFWL_ListItem* hStart, CFWL_ListItem* hEnd, bool bSelected);
-  CFWL_ListItem* GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy);
-  bool ScrollToVisible(CFWL_ListItem* hItem);
-  void InitScrollBar(bool bVert = true);
-  bool IsShowScrollBar(bool bVert);
-  CFWL_ScrollBar* GetVertScrollBar() const { return m_pVertScrollBar.get(); }
-  const CFX_RectF& GetRTClient() const { return m_rtClient; }
-
- private:
-  void SetSelectionDirect(CFWL_ListItem* hItem, bool bSelect);
-  bool IsItemSelected(CFWL_ListItem* hItem);
-  void ClearSelection();
-  void SelectAll();
-  CFWL_ListItem* GetFocusedItem();
-  void SetFocusItem(CFWL_ListItem* hItem);
-  bool GetItemCheckRectInternal(CFWL_ListItem* hItem, CFX_RectF& rtCheck);
-  bool SetItemChecked(CFWL_ListItem* hItem, bool bChecked);
-  bool GetItemChecked(CFWL_ListItem* hItem);
-  void DrawBkground(CFX_Graphics* pGraphics,
-                    IFWL_ThemeProvider* pTheme,
-                    const CFX_Matrix* pMatrix = nullptr);
-  void DrawItems(CFX_Graphics* pGraphics,
-                 IFWL_ThemeProvider* pTheme,
-                 const CFX_Matrix* pMatrix = nullptr);
-  void DrawItem(CFX_Graphics* pGraphics,
-                IFWL_ThemeProvider* pTheme,
-                CFWL_ListItem* hItem,
-                int32_t Index,
-                const CFX_RectF& rtItem,
-                const CFX_Matrix* pMatrix = nullptr);
-  void DrawStatic(CFX_Graphics* pGraphics, IFWL_ThemeProvider* pTheme);
-  CFX_SizeF CalcSize(bool bAutoSize = false);
-  void GetItemSize(CFX_SizeF& size,
-                   CFWL_ListItem* hItem,
-                   FX_FLOAT fWidth,
-                   FX_FLOAT fHeight,
-                   bool bAutoSize = false);
-  FX_FLOAT GetMaxTextWidth();
-  FX_FLOAT GetScrollWidth();
-
-  void OnFocusChanged(CFWL_Message* pMsg, bool bSet = true);
-  void OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnMouseWheel(CFWL_MsgMouseWheel* pMsg);
-  void OnKeyDown(CFWL_MsgKey* pMsg);
-  void OnVK(CFWL_ListItem* hItem, bool bShift, bool bCtrl);
-  bool OnScroll(CFWL_ScrollBar* pScrollBar, FWL_SCBCODE dwCode, FX_FLOAT fPos);
-
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtStatic;
-  CFX_RectF m_rtConent;
-  std::unique_ptr<CFWL_ScrollBar> m_pHorzScrollBar;
-  std::unique_ptr<CFWL_ScrollBar> m_pVertScrollBar;
-  uint32_t m_dwTTOStyles;
-  int32_t m_iTTOAligns;
-  CFWL_ListItem* m_hAnchor;
-  FX_FLOAT m_fItemHeight;
-  FX_FLOAT m_fScorllBarWidth;
-  bool m_bLButtonDown;
-  IFWL_ThemeProvider* m_pScrollBarTP;
-  std::vector<std::unique_ptr<CFWL_ListItem>> m_ItemArray;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_LISTBOX_H_
diff --git a/xfa/fwl/core/ifwl_picturebox.cpp b/xfa/fwl/core/ifwl_picturebox.cpp
deleted file mode 100644
index 9a3fbf3..0000000
--- a/xfa/fwl/core/ifwl_picturebox.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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/core/ifwl_picturebox.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_picturebox.h"
-
-IFWL_PictureBox::IFWL_PictureBox(
-    const CFWL_App* app,
-    std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr) {
-  m_rtClient.Reset();
-  m_rtImage.Reset();
-  m_matrix.SetIdentity();
-}
-
-IFWL_PictureBox::~IFWL_PictureBox() {}
-
-FWL_Type IFWL_PictureBox::GetClassID() const {
-  return FWL_Type::PictureBox;
-}
-
-void IFWL_PictureBox::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Set(0, 0, 0, 0);
-
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_PictureBox::Update() {
-  if (IsLocked())
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  GetClientRect(m_rtClient);
-}
-
-void IFWL_PictureBox::DrawWidget(CFX_Graphics* pGraphics,
-                                 const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
-  if (HasBorder())
-    DrawBorder(pGraphics, CFWL_Part::Border, pTheme, pMatrix);
-  if (HasEdge())
-    DrawEdge(pGraphics, CFWL_Part::Edge, pTheme, pMatrix);
-}
-
-void IFWL_PictureBox::OnDrawWidget(CFX_Graphics* pGraphics,
-                                   const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
diff --git a/xfa/fwl/core/ifwl_picturebox.h b/xfa/fwl/core/ifwl_picturebox.h
deleted file mode 100644
index 510ab9a..0000000
--- a/xfa/fwl/core/ifwl_picturebox.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_PICTUREBOX_H_
-#define XFA_FWL_CORE_IFWL_PICTUREBOX_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-
-#define FWL_STYLEEXT_PTB_Left 0L << 0
-#define FWL_STYLEEXT_PTB_Center 1L << 0
-#define FWL_STYLEEXT_PTB_Right 2L << 0
-#define FWL_STYLEEXT_PTB_Top 0L << 2
-#define FWL_STYLEEXT_PTB_Vcenter 1L << 2
-#define FWL_STYLEEXT_PTB_Bottom 2L << 2
-#define FWL_STYLEEXT_PTB_Normal 0L << 4
-#define FWL_STYLEEXT_PTB_AutoSize 1L << 4
-#define FWL_STYLEEXT_PTB_StretchImage 2L << 4
-#define FWL_STYLEEXT_PTB_StretchHImage 3L << 4
-#define FWL_STYLEEXT_PTB_StretchVImage 4L << 4
-#define FWL_STYLEEXT_PTB_HAlignMask 3L << 0
-#define FWL_STYLEEXT_PTB_VAlignMask 3L << 2
-#define FWL_STYLEEXT_PTB_StretchAlignMask 7L << 4
-
-class CFX_DIBitmap;
-class IFWL_Widget;
-
-class IFWL_PictureBox : public IFWL_Widget {
- public:
-  explicit IFWL_PictureBox(const CFWL_App* app,
-                           std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_PictureBox() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void Update() override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
- private:
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtImage;
-  CFX_Matrix m_matrix;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_PICTUREBOX_H_
diff --git a/xfa/fwl/core/ifwl_pushbutton.cpp b/xfa/fwl/core/ifwl_pushbutton.cpp
deleted file mode 100644
index 7eb8412..0000000
--- a/xfa/fwl/core/ifwl_pushbutton.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-// 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/core/ifwl_pushbutton.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/base/ptr_util.h"
-#include "xfa/fde/tto/fde_textout.h"
-#include "xfa/fwl/core/cfwl_evtclick.h"
-#include "xfa/fwl/core/cfwl_evtmouse.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-
-IFWL_PushButton::IFWL_PushButton(
-    const CFWL_App* app,
-    std::unique_ptr<CFWL_WidgetProperties> properties)
-    : IFWL_Widget(app, std::move(properties), nullptr),
-      m_bBtnDown(false),
-      m_dwTTOStyles(FDE_TTOSTYLE_SingleLine),
-      m_iTTOAlign(FDE_TTOALIGNMENT_Center) {
-  m_rtClient.Set(0, 0, 0, 0);
-  m_rtCaption.Set(0, 0, 0, 0);
-}
-
-IFWL_PushButton::~IFWL_PushButton() {}
-
-FWL_Type IFWL_PushButton::GetClassID() const {
-  return FWL_Type::PushButton;
-}
-
-void IFWL_PushButton::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  rect.Set(0, 0, 0, 0);
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  FX_FLOAT* fcaption =
-      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::Margin));
-  rect.Inflate(*fcaption, *fcaption);
-  IFWL_Widget::GetWidgetRect(rect, true);
-}
-
-void IFWL_PushButton::SetStates(uint32_t dwStates, bool bSet) {
-  if ((dwStates & FWL_WGTSTATE_Disabled) && bSet) {
-    m_pProperties->m_dwStates = FWL_WGTSTATE_Disabled;
-    return;
-  }
-  IFWL_Widget::SetStates(dwStates, bSet);
-}
-
-void IFWL_PushButton::Update() {
-  if (IsLocked())
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    m_pProperties->m_pThemeProvider = GetAvailableTheme();
-
-  UpdateTextOutStyles();
-  GetClientRect(m_rtClient);
-  m_rtCaption = m_rtClient;
-  FX_FLOAT* fcaption =
-      static_cast<FX_FLOAT*>(GetThemeCapacity(CFWL_WidgetCapacity::Margin));
-  m_rtCaption.Inflate(-*fcaption, -*fcaption);
-}
-
-void IFWL_PushButton::DrawWidget(CFX_Graphics* pGraphics,
-                                 const CFX_Matrix* pMatrix) {
-  if (!pGraphics)
-    return;
-  if (!m_pProperties->m_pThemeProvider)
-    return;
-
-  if (HasBorder()) {
-    DrawBorder(pGraphics, CFWL_Part::Border, m_pProperties->m_pThemeProvider,
-               pMatrix);
-  }
-  if (HasEdge()) {
-    DrawEdge(pGraphics, CFWL_Part::Edge, m_pProperties->m_pThemeProvider,
-             pMatrix);
-  }
-  DrawBkground(pGraphics, m_pProperties->m_pThemeProvider, pMatrix);
-}
-
-void IFWL_PushButton::DrawBkground(CFX_Graphics* pGraphics,
-                                   IFWL_ThemeProvider* pTheme,
-                                   const CFX_Matrix* pMatrix) {
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = CFWL_Part::Background;
-  param.m_dwStates = GetPartStates();
-  param.m_pGraphics = pGraphics;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix);
-  param.m_rtPart = m_rtClient;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-    param.m_pData = &m_rtCaption;
-  pTheme->DrawBackground(&param);
-}
-
-uint32_t IFWL_PushButton::GetPartStates() {
-  uint32_t dwStates = CFWL_PartState_Normal;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
-    dwStates |= CFWL_PartState_Focused;
-  if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
-    dwStates = CFWL_PartState_Disabled;
-  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed)
-    dwStates |= CFWL_PartState_Pressed;
-  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered)
-    dwStates |= CFWL_PartState_Hovered;
-  else if (m_pProperties->m_dwStates & FWL_STATE_PSB_Default)
-    dwStates |= CFWL_PartState_Default;
-  return dwStates;
-}
-
-void IFWL_PushButton::UpdateTextOutStyles() {
-  switch (m_pProperties->m_dwStyleExes &
-          (FWL_STYLEEXT_PSB_HLayoutMask | FWL_STYLEEXT_PSB_VLayoutMask)) {
-    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopCenter;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Top: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_TopRight;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_VCenter: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_VCenter: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_CenterRight;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Left | FWL_STYLEEXT_PSB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomLeft;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomCenter;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Right | FWL_STYLEEXT_PSB_Bottom: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_BottomRight;
-      break;
-    }
-    case FWL_STYLEEXT_PSB_Center | FWL_STYLEEXT_PSB_VCenter:
-    default: {
-      m_iTTOAlign = FDE_TTOALIGNMENT_Center;
-      break;
-    }
-  }
-  m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
-  if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading)
-    m_dwTTOStyles |= FDE_TTOSTYLE_RTL;
-}
-
-void IFWL_PushButton::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage)
-    return;
-  if (!IsEnabled())
-    return;
-
-  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
-  switch (dwMsgCode) {
-    case CFWL_MessageType::SetFocus:
-      OnFocusChanged(pMessage, true);
-      break;
-    case CFWL_MessageType::KillFocus:
-      OnFocusChanged(pMessage, false);
-      break;
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
-      switch (pMsg->m_dwCmd) {
-        case FWL_MouseCommand::LeftButtonDown:
-          OnLButtonDown(pMsg);
-          break;
-        case FWL_MouseCommand::LeftButtonUp:
-          OnLButtonUp(pMsg);
-          break;
-        case FWL_MouseCommand::Move:
-          OnMouseMove(pMsg);
-          break;
-        case FWL_MouseCommand::Leave:
-          OnMouseLeave(pMsg);
-          break;
-        default:
-          break;
-      }
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
-      if (pKey->m_dwCmd == FWL_KeyCommand::KeyDown)
-        OnKeyDown(pKey);
-      break;
-    }
-    default:
-      break;
-  }
-  IFWL_Widget::OnProcessMessage(pMessage);
-}
-
-void IFWL_PushButton::OnDrawWidget(CFX_Graphics* pGraphics,
-                                   const CFX_Matrix* pMatrix) {
-  DrawWidget(pGraphics, pMatrix);
-}
-
-void IFWL_PushButton::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
-  if (bSet)
-    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
-  else
-    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
-
-  Repaint(&m_rtClient);
-}
-
-void IFWL_PushButton::OnLButtonDown(CFWL_MsgMouse* pMsg) {
-  if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
-    SetFocus(true);
-
-  m_bBtnDown = true;
-  m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
-  m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
-  Repaint(&m_rtClient);
-}
-
-void IFWL_PushButton::OnLButtonUp(CFWL_MsgMouse* pMsg) {
-  m_bBtnDown = false;
-  if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
-    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
-    m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
-  } else {
-    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
-    m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
-  }
-  if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
-    CFWL_EvtClick wmClick;
-    wmClick.m_pSrcTarget = this;
-    DispatchEvent(&wmClick);
-  }
-  Repaint(&m_rtClient);
-}
-
-void IFWL_PushButton::OnMouseMove(CFWL_MsgMouse* pMsg) {
-  bool bRepaint = false;
-  if (m_bBtnDown) {
-    if (m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
-      if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) == 0) {
-        m_pProperties->m_dwStates |= FWL_STATE_PSB_Pressed;
-        bRepaint = true;
-      }
-      if (m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) {
-        m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
-        bRepaint = true;
-      }
-    } else {
-      if (m_pProperties->m_dwStates & FWL_STATE_PSB_Pressed) {
-        m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
-        bRepaint = true;
-      }
-      if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
-        m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
-        bRepaint = true;
-      }
-    }
-  } else {
-    if (!m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy))
-      return;
-    if ((m_pProperties->m_dwStates & FWL_STATE_PSB_Hovered) == 0) {
-      m_pProperties->m_dwStates |= FWL_STATE_PSB_Hovered;
-      bRepaint = true;
-    }
-  }
-  if (bRepaint)
-    Repaint(&m_rtClient);
-}
-
-void IFWL_PushButton::OnMouseLeave(CFWL_MsgMouse* pMsg) {
-  m_bBtnDown = false;
-  m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Hovered;
-  m_pProperties->m_dwStates &= ~FWL_STATE_PSB_Pressed;
-  Repaint(&m_rtClient);
-}
-
-void IFWL_PushButton::OnKeyDown(CFWL_MsgKey* pMsg) {
-  if (pMsg->m_dwKeyCode == FWL_VKEY_Return) {
-    CFWL_EvtMouse wmMouse;
-    wmMouse.m_pSrcTarget = this;
-    wmMouse.m_dwCmd = FWL_MouseCommand::LeftButtonUp;
-    DispatchEvent(&wmMouse);
-    CFWL_EvtClick wmClick;
-    wmClick.m_pSrcTarget = this;
-    DispatchEvent(&wmClick);
-    return;
-  }
-  if (pMsg->m_dwKeyCode != FWL_VKEY_Tab)
-    return;
-
-  DispatchKeyEvent(pMsg);
-}
diff --git a/xfa/fwl/core/ifwl_pushbutton.h b/xfa/fwl/core/ifwl_pushbutton.h
deleted file mode 100644
index 9a14213..0000000
--- a/xfa/fwl/core/ifwl_pushbutton.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_PUSHBUTTON_H_
-#define XFA_FWL_CORE_IFWL_PUSHBUTTON_H_
-
-#include <memory>
-
-#include "xfa/fwl/core/cfwl_widgetproperties.h"
-#include "xfa/fwl/core/ifwl_widget.h"
-
-#define FWL_STYLEEXT_PSB_Left (0L << 0)
-#define FWL_STYLEEXT_PSB_Center (1L << 0)
-#define FWL_STYLEEXT_PSB_Right (2L << 0)
-#define FWL_STYLEEXT_PSB_Top (0L << 2)
-#define FWL_STYLEEXT_PSB_VCenter (1L << 2)
-#define FWL_STYLEEXT_PSB_Bottom (2L << 2)
-#define FWL_STYLEEXT_PSB_TextOnly (0L << 4)
-#define FWL_STYLEEXT_PSB_IconOnly (1L << 4)
-#define FWL_STYLEEXT_PSB_TextIcon (2L << 4)
-#define FWL_STYLEEXT_PSB_HLayoutMask (3L << 0)
-#define FWL_STYLEEXT_PSB_VLayoutMask (3L << 2)
-#define FWL_STYLEEXT_PSB_ModeMask (3L << 4)
-#define FWL_STATE_PSB_Hovered (1 << FWL_WGTSTATE_MAX)
-#define FWL_STATE_PSB_Pressed (1 << (FWL_WGTSTATE_MAX + 1))
-#define FWL_STATE_PSB_Default (1 << (FWL_WGTSTATE_MAX + 2))
-
-class CFWL_MsgMouse;
-class CFX_DIBitmap;
-class IFWL_Widget;
-
-class IFWL_PushButton : public IFWL_Widget {
- public:
-  IFWL_PushButton(const CFWL_App* app,
-                  std::unique_ptr<CFWL_WidgetProperties> properties);
-  ~IFWL_PushButton() override;
-
-  // IFWL_Widget
-  FWL_Type GetClassID() const override;
-  void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false) override;
-  void SetStates(uint32_t dwStates, bool bSet = true) override;
-  void Update() override;
-  void DrawWidget(CFX_Graphics* pGraphics,
-                  const CFX_Matrix* pMatrix = nullptr) override;
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix) override;
-
- private:
-  void DrawBkground(CFX_Graphics* pGraphics,
-                    IFWL_ThemeProvider* pTheme,
-                    const CFX_Matrix* pMatrix);
-  uint32_t GetPartStates();
-  void UpdateTextOutStyles();
-  void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
-  void OnLButtonDown(CFWL_MsgMouse* pMsg);
-  void OnLButtonUp(CFWL_MsgMouse* pMsg);
-  void OnMouseMove(CFWL_MsgMouse* pMsg);
-  void OnMouseLeave(CFWL_MsgMouse* pMsg);
-  void OnKeyDown(CFWL_MsgKey* pMsg);
-
-  CFX_RectF m_rtClient;
-  CFX_RectF m_rtCaption;
-  bool m_bBtnDown;
-  uint32_t m_dwTTOStyles;
-  int32_t m_iTTOAlign;
-};
-
-#endif  // XFA_FWL_CORE_IFWL_PUSHBUTTON_H_
diff --git a/xfa/fwl/core/ifwl_themeprovider.h b/xfa/fwl/core/ifwl_themeprovider.h
index cc55fa3..e376cb1 100644
--- a/xfa/fwl/core/ifwl_themeprovider.h
+++ b/xfa/fwl/core/ifwl_themeprovider.h
@@ -13,7 +13,7 @@
 class CFWL_ThemeBackground;
 class CFWL_ThemePart;
 class CFWL_ThemeText;
-class IFWL_Widget;
+class CFWL_Widget;
 
 class IFWL_ThemeProvider {
  public:
diff --git a/xfa/fwl/core/ifwl_widget.cpp b/xfa/fwl/core/ifwl_widget.cpp
deleted file mode 100644
index 9a37cc8..0000000
--- a/xfa/fwl/core/ifwl_widget.cpp
+++ /dev/null
@@ -1,803 +0,0 @@
-// 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/core/ifwl_widget.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "xfa/fde/tto/fde_textout.h"
-#include "xfa/fwl/core/cfwl_app.h"
-#include "xfa/fwl/core/cfwl_evtkey.h"
-#include "xfa/fwl/core/cfwl_evtkillfocus.h"
-#include "xfa/fwl/core/cfwl_evtmouse.h"
-#include "xfa/fwl/core/cfwl_evtmousewheel.h"
-#include "xfa/fwl/core/cfwl_evtsetfocus.h"
-#include "xfa/fwl/core/cfwl_evtsizechanged.h"
-#include "xfa/fwl/core/cfwl_form.h"
-#include "xfa/fwl/core/cfwl_msgkey.h"
-#include "xfa/fwl/core/cfwl_msgkillfocus.h"
-#include "xfa/fwl/core/cfwl_msgmouse.h"
-#include "xfa/fwl/core/cfwl_msgmousewheel.h"
-#include "xfa/fwl/core/cfwl_msgsetfocus.h"
-#include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
-#include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fxfa/xfa_ffapp.h"
-
-#define FWL_STYLEEXT_MNU_Vert (1L << 0)
-#define FWL_WGT_CalcHeight 2048
-#define FWL_WGT_CalcWidth 2048
-#define FWL_WGT_CalcMultiLineDefWidth 120.0f
-
-IFWL_Widget::IFWL_Widget(const CFWL_App* app,
-                         std::unique_ptr<CFWL_WidgetProperties> properties,
-                         IFWL_Widget* pOuter)
-    : m_pOwnerApp(app),
-      m_pWidgetMgr(app->GetWidgetMgr()),
-      m_pProperties(std::move(properties)),
-      m_pOuter(pOuter),
-      m_iLock(0),
-      m_pLayoutItem(nullptr),
-      m_pAssociate(nullptr),
-      m_nEventKey(0),
-      m_pDelegate(nullptr) {
-  ASSERT(m_pWidgetMgr);
-
-  IFWL_Widget* pParent = m_pProperties->m_pParent;
-  m_pWidgetMgr->InsertWidget(pParent, this);
-  if (IsChild())
-    return;
-
-  IFWL_Widget* pOwner = m_pProperties->m_pOwner;
-  if (pOwner)
-    m_pWidgetMgr->SetOwner(pOwner, this);
-}
-
-IFWL_Widget::~IFWL_Widget() {
-  NotifyDriver();
-  m_pWidgetMgr->RemoveWidget(this);
-}
-
-bool IFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const {
-  return false;
-}
-
-void IFWL_Widget::GetWidgetRect(CFX_RectF& rect, bool bAutoSize) {
-  if (!bAutoSize) {
-    rect = m_pProperties->m_rtWidget;
-    return;
-  }
-
-  if (HasEdge()) {
-    FX_FLOAT fEdge = GetEdgeWidth();
-    rect.Inflate(fEdge, fEdge);
-  }
-  if (HasBorder()) {
-    FX_FLOAT fBorder = GetBorderSize();
-    rect.Inflate(fBorder, fBorder);
-  }
-}
-
-void IFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
-  CFX_RectF rtOld = m_pProperties->m_rtWidget;
-  m_pProperties->m_rtWidget = rect;
-  if (IsChild()) {
-    if (FXSYS_fabs(rtOld.width - rect.width) > 0.5f ||
-        FXSYS_fabs(rtOld.height - rect.height) > 0.5f) {
-      CFWL_EvtSizeChanged ev;
-      ev.m_pSrcTarget = this;
-      ev.m_rtOld = rtOld;
-      ev.m_rtNew = rect;
-
-      if (IFWL_WidgetDelegate* pDelegate = GetDelegate())
-        pDelegate->OnProcessEvent(&ev);
-    }
-    return;
-  }
-  m_pWidgetMgr->SetWidgetRect_Native(this, rect);
-}
-
-void IFWL_Widget::GetClientRect(CFX_RectF& rect) {
-  GetEdgeRect(rect);
-  if (HasEdge()) {
-    FX_FLOAT fEdge = GetEdgeWidth();
-    rect.Deflate(fEdge, fEdge);
-  }
-}
-
-void IFWL_Widget::SetParent(IFWL_Widget* pParent) {
-  m_pProperties->m_pParent = pParent;
-  m_pWidgetMgr->SetParent(pParent, this);
-}
-
-uint32_t IFWL_Widget::GetStyles() const {
-  return m_pProperties->m_dwStyles;
-}
-
-void IFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
-                               uint32_t dwStylesRemoved) {
-  m_pProperties->m_dwStyles =
-      (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
-}
-
-uint32_t IFWL_Widget::GetStylesEx() const {
-  return m_pProperties->m_dwStyleExes;
-}
-uint32_t IFWL_Widget::GetStates() const {
-  return m_pProperties->m_dwStates;
-}
-
-void IFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded,
-                                 uint32_t dwStylesExRemoved) {
-  m_pProperties->m_dwStyleExes =
-      (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
-}
-
-static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr,
-                                  IFWL_Widget* widget,
-                                  CFWL_NoteDriver* noteDriver) {
-  IFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget);
-  while (child) {
-    noteDriver->NotifyTargetHide(child);
-    NotifyHideChildWidget(widgetMgr, child, noteDriver);
-    child = widgetMgr->GetNextSiblingWidget(child);
-  }
-}
-
-void IFWL_Widget::SetStates(uint32_t dwStates, bool bSet) {
-  bSet ? (m_pProperties->m_dwStates |= dwStates)
-       : (m_pProperties->m_dwStates &= ~dwStates);
-  if (!(dwStates & FWL_WGTSTATE_Invisible) || !bSet)
-    return;
-
-  CFWL_NoteDriver* noteDriver =
-      static_cast<CFWL_NoteDriver*>(GetOwnerApp()->GetNoteDriver());
-  CFWL_WidgetMgr* widgetMgr = GetOwnerApp()->GetWidgetMgr();
-  noteDriver->NotifyTargetHide(this);
-  IFWL_Widget* child = widgetMgr->GetFirstChildWidget(this);
-  while (child) {
-    noteDriver->NotifyTargetHide(child);
-    NotifyHideChildWidget(widgetMgr, child, noteDriver);
-    child = widgetMgr->GetNextSiblingWidget(child);
-  }
-  return;
-}
-
-FWL_WidgetHit IFWL_Widget::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
-  CFX_RectF rtClient;
-  GetClientRect(rtClient);
-  if (rtClient.Contains(fx, fy))
-    return FWL_WidgetHit::Client;
-  if (HasEdge()) {
-    CFX_RectF rtEdge;
-    GetEdgeRect(rtEdge);
-    if (rtEdge.Contains(fx, fy))
-      return FWL_WidgetHit::Edge;
-  }
-  if (HasBorder()) {
-    CFX_RectF rtRelative;
-    GetRelativeRect(rtRelative);
-    if (rtRelative.Contains(fx, fy))
-      return FWL_WidgetHit::Border;
-  }
-  return FWL_WidgetHit::Unknown;
-}
-
-void IFWL_Widget::TransformTo(IFWL_Widget* pWidget,
-                              FX_FLOAT& fx,
-                              FX_FLOAT& fy) {
-  if (m_pWidgetMgr->IsFormDisabled()) {
-    CFX_SizeF szOffset;
-    if (IsParent(pWidget)) {
-      szOffset = GetOffsetFromParent(pWidget);
-    } else {
-      szOffset = pWidget->GetOffsetFromParent(this);
-      szOffset.x = -szOffset.x;
-      szOffset.y = -szOffset.y;
-    }
-    fx += szOffset.x;
-    fy += szOffset.y;
-    return;
-  }
-  CFX_RectF r;
-  CFX_Matrix m;
-  IFWL_Widget* parent = GetParent();
-  if (parent) {
-    GetWidgetRect(r);
-    fx += r.left;
-    fy += r.top;
-    GetMatrix(m, true);
-    m.TransformPoint(fx, fy);
-  }
-  IFWL_Widget* form1 = m_pWidgetMgr->GetSystemFormWidget(this);
-  if (!form1)
-    return;
-  if (!pWidget) {
-    form1->GetWidgetRect(r);
-    fx += r.left;
-    fy += r.top;
-    return;
-  }
-  IFWL_Widget* form2 = m_pWidgetMgr->GetSystemFormWidget(pWidget);
-  if (!form2)
-    return;
-  if (form1 != form2) {
-    form1->GetWidgetRect(r);
-    fx += r.left;
-    fy += r.top;
-    form2->GetWidgetRect(r);
-    fx -= r.left;
-    fy -= r.top;
-  }
-  parent = pWidget->GetParent();
-  if (parent) {
-    pWidget->GetMatrix(m, true);
-    CFX_Matrix m1;
-    m1.SetIdentity();
-    m1.SetReverse(m);
-    m1.TransformPoint(fx, fy);
-    pWidget->GetWidgetRect(r);
-    fx -= r.left;
-    fy -= r.top;
-  }
-}
-
-void IFWL_Widget::GetMatrix(CFX_Matrix& matrix, bool bGlobal) {
-  if (!m_pProperties)
-    return;
-  if (!bGlobal) {
-    matrix.SetIdentity();
-    return;
-  }
-
-  IFWL_Widget* parent = GetParent();
-  CFX_ArrayTemplate<IFWL_Widget*> parents;
-  while (parent) {
-    parents.Add(parent);
-    parent = parent->GetParent();
-  }
-  matrix.SetIdentity();
-  CFX_Matrix ctmOnParent;
-  CFX_RectF rect;
-  int32_t count = parents.GetSize();
-  for (int32_t i = count - 2; i >= 0; i--) {
-    parent = parents.GetAt(i);
-    parent->GetMatrix(ctmOnParent, false);
-    parent->GetWidgetRect(rect);
-    matrix.Concat(ctmOnParent, true);
-    matrix.Translate(rect.left, rect.top, true);
-  }
-  CFX_Matrix m;
-  m.SetIdentity();
-  matrix.Concat(m, true);
-  parents.RemoveAll();
-}
-
-IFWL_ThemeProvider* IFWL_Widget::GetThemeProvider() const {
-  return m_pProperties->m_pThemeProvider;
-}
-
-void IFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
-  m_pProperties->m_pThemeProvider = pThemeProvider;
-}
-
-bool IFWL_Widget::IsEnabled() const {
-  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
-}
-
-bool IFWL_Widget::IsActive() const {
-  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Deactivated) == 0;
-}
-
-bool IFWL_Widget::HasBorder() const {
-  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
-}
-
-bool IFWL_Widget::HasEdge() const {
-  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask);
-}
-
-bool IFWL_Widget::IsVisible() const {
-  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
-}
-
-bool IFWL_Widget::IsOverLapper() const {
-  return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
-         FWL_WGTSTYLE_OverLapper;
-}
-
-bool IFWL_Widget::IsPopup() const {
-  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
-}
-
-bool IFWL_Widget::IsChild() const {
-  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
-}
-
-bool IFWL_Widget::IsOffscreen() const {
-  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Offscreen);
-}
-
-void IFWL_Widget::GetEdgeRect(CFX_RectF& rtEdge) {
-  rtEdge = m_pProperties->m_rtWidget;
-  rtEdge.left = rtEdge.top = 0;
-  if (HasBorder()) {
-    FX_FLOAT fCX = GetBorderSize();
-    FX_FLOAT fCY = GetBorderSize(false);
-    rtEdge.Deflate(fCX, fCY);
-  }
-}
-
-FX_FLOAT IFWL_Widget::GetBorderSize(bool bCX) {
-  FX_FLOAT* pfBorder = static_cast<FX_FLOAT*>(GetThemeCapacity(
-      bCX ? CFWL_WidgetCapacity::CXBorder : CFWL_WidgetCapacity::CYBorder));
-  if (!pfBorder)
-    return 0;
-  return *pfBorder;
-}
-
-FX_FLOAT IFWL_Widget::GetEdgeWidth() {
-  CFWL_WidgetCapacity dwCapacity = CFWL_WidgetCapacity::None;
-  switch (m_pProperties->m_dwStyles & FWL_WGTSTYLE_EdgeMask) {
-    case FWL_WGTSTYLE_EdgeFlat: {
-      dwCapacity = CFWL_WidgetCapacity::EdgeFlat;
-      break;
-    }
-    case FWL_WGTSTYLE_EdgeRaised: {
-      dwCapacity = CFWL_WidgetCapacity::EdgeRaised;
-      break;
-    }
-    case FWL_WGTSTYLE_EdgeSunken: {
-      dwCapacity = CFWL_WidgetCapacity::EdgeSunken;
-      break;
-    }
-  }
-  if (dwCapacity != CFWL_WidgetCapacity::None) {
-    FX_FLOAT* fRet = static_cast<FX_FLOAT*>(GetThemeCapacity(dwCapacity));
-    return fRet ? *fRet : 0;
-  }
-  return 0;
-}
-
-void IFWL_Widget::GetRelativeRect(CFX_RectF& rect) {
-  rect = m_pProperties->m_rtWidget;
-  rect.left = rect.top = 0;
-}
-
-void* IFWL_Widget::GetThemeCapacity(CFWL_WidgetCapacity dwCapacity) {
-  IFWL_ThemeProvider* pTheme = GetAvailableTheme();
-  if (!pTheme)
-    return nullptr;
-
-  CFWL_ThemePart part;
-  part.m_pWidget = this;
-  return pTheme->GetCapacity(&part, dwCapacity);
-}
-
-IFWL_ThemeProvider* IFWL_Widget::GetAvailableTheme() {
-  if (m_pProperties->m_pThemeProvider)
-    return m_pProperties->m_pThemeProvider;
-
-  IFWL_Widget* pUp = this;
-  do {
-    pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
-              ? m_pWidgetMgr->GetOwnerWidget(pUp)
-              : m_pWidgetMgr->GetParentWidget(pUp);
-    if (pUp) {
-      IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
-      if (pRet)
-        return pRet;
-    }
-  } while (pUp);
-  return nullptr;
-}
-
-IFWL_Widget* IFWL_Widget::GetRootOuter() {
-  IFWL_Widget* pRet = m_pOuter;
-  if (!pRet)
-    return nullptr;
-
-  while (IFWL_Widget* pOuter = pRet->GetOuter())
-    pRet = pOuter;
-  return pRet;
-}
-
-CFX_SizeF IFWL_Widget::CalcTextSize(const CFX_WideString& wsText,
-                                    IFWL_ThemeProvider* pTheme,
-                                    bool bMultiLine,
-                                    int32_t iLineWidth) {
-  if (!pTheme)
-    return CFX_SizeF();
-
-  CFWL_ThemeText calPart;
-  calPart.m_pWidget = this;
-  calPart.m_wsText = wsText;
-  calPart.m_dwTTOStyles =
-      bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine;
-  calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
-  CFX_RectF rect;
-  FX_FLOAT fWidth = bMultiLine
-                        ? (iLineWidth > 0 ? (FX_FLOAT)iLineWidth
-                                          : FWL_WGT_CalcMultiLineDefWidth)
-                        : FWL_WGT_CalcWidth;
-  rect.Set(0, 0, fWidth, FWL_WGT_CalcHeight);
-  pTheme->CalcTextRect(&calPart, rect);
-  return CFX_SizeF(rect.width, rect.height);
-}
-
-void IFWL_Widget::CalcTextRect(const CFX_WideString& wsText,
-                               IFWL_ThemeProvider* pTheme,
-                               uint32_t dwTTOStyles,
-                               int32_t iTTOAlign,
-                               CFX_RectF& rect) {
-  CFWL_ThemeText calPart;
-  calPart.m_pWidget = this;
-  calPart.m_wsText = wsText;
-  calPart.m_dwTTOStyles = dwTTOStyles;
-  calPart.m_iTTOAlign = iTTOAlign;
-  pTheme->CalcTextRect(&calPart, rect);
-}
-
-void IFWL_Widget::SetFocus(bool bFocus) {
-  if (m_pWidgetMgr->IsFormDisabled())
-    return;
-
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pDriver =
-      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
-  if (!pDriver)
-    return;
-
-  IFWL_Widget* curFocus = pDriver->GetFocus();
-  if (bFocus && curFocus != this)
-    pDriver->SetFocus(this);
-  else if (!bFocus && curFocus == this)
-    pDriver->SetFocus(nullptr);
-}
-
-void IFWL_Widget::SetGrab(bool bSet) {
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pDriver =
-      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
-  pDriver->SetGrab(this, bSet);
-}
-
-void IFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight,
-                              FX_FLOAT fMaxHeight,
-                              const CFX_RectF& rtAnchor,
-                              CFX_RectF& rtPopup) {
-  if (GetClassID() == FWL_Type::ComboBox) {
-    if (m_pWidgetMgr->IsFormDisabled()) {
-      m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
-                                       rtPopup);
-      return;
-    }
-    GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
-    return;
-  }
-  if (GetClassID() == FWL_Type::DateTimePicker &&
-      m_pWidgetMgr->IsFormDisabled()) {
-    m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
-                                     rtPopup);
-    return;
-  }
-  GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
-}
-
-bool IFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight,
-                                  FX_FLOAT fMaxHeight,
-                                  const CFX_RectF& rtAnchor,
-                                  CFX_RectF& rtPopup) {
-  FX_FLOAT fx = 0;
-  FX_FLOAT fy = 0;
-
-  if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
-    bool bLeft = m_pProperties->m_rtWidget.left < 0;
-    FX_FLOAT fRight = rtAnchor.right() + rtPopup.width;
-    TransformTo(nullptr, fx, fy);
-    if (fRight + fx > 0.0f || bLeft) {
-      rtPopup.Set(rtAnchor.left - rtPopup.width, rtAnchor.top, rtPopup.width,
-                  rtPopup.height);
-    } else {
-      rtPopup.Set(rtAnchor.right(), rtAnchor.top, rtPopup.width,
-                  rtPopup.height);
-    }
-  } else {
-    FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height;
-    TransformTo(nullptr, fx, fy);
-    if (fBottom + fy > 0.0f) {
-      rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
-                  rtPopup.height);
-    } else {
-      rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
-                  rtPopup.height);
-    }
-  }
-  rtPopup.Offset(fx, fy);
-  return true;
-}
-
-bool IFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight,
-                                      FX_FLOAT fMaxHeight,
-                                      const CFX_RectF& rtAnchor,
-                                      CFX_RectF& rtPopup) {
-  FX_FLOAT fx = 0;
-  FX_FLOAT fy = 0;
-
-  FX_FLOAT fPopHeight = rtPopup.height;
-  if (rtPopup.height > fMaxHeight)
-    fPopHeight = fMaxHeight;
-  else if (rtPopup.height < fMinHeight)
-    fPopHeight = fMinHeight;
-
-  FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width);
-  FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight;
-  TransformTo(nullptr, fx, fy);
-  if (fBottom + fy > 0.0f)
-    rtPopup.Set(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
-  else
-    rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
-
-  rtPopup.Offset(fx, fy);
-  return true;
-}
-
-bool IFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight,
-                                     FX_FLOAT fMaxHeight,
-                                     const CFX_RectF& rtAnchor,
-                                     CFX_RectF& rtPopup) {
-  FX_FLOAT fx = 0;
-  FX_FLOAT fy = 0;
-
-  TransformTo(nullptr, fx, fy);
-  if (rtAnchor.bottom() + fy > 0.0f) {
-    rtPopup.Set(rtAnchor.left, rtAnchor.top - rtPopup.height, rtPopup.width,
-                rtPopup.height);
-  } else {
-    rtPopup.Set(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
-                rtPopup.height);
-  }
-  rtPopup.Offset(fx, fy);
-  return true;
-}
-
-void IFWL_Widget::RegisterEventTarget(IFWL_Widget* pEventSource) {
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
-  if (!pNoteDriver)
-    return;
-
-  pNoteDriver->RegisterEventTarget(this, pEventSource);
-}
-
-void IFWL_Widget::UnregisterEventTarget() {
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
-  if (!pNoteDriver)
-    return;
-
-  pNoteDriver->UnregisterEventTarget(this);
-}
-
-void IFWL_Widget::DispatchKeyEvent(CFWL_MsgKey* pNote) {
-  if (!pNote)
-    return;
-
-  auto pEvent = pdfium::MakeUnique<CFWL_EvtKey>();
-  pEvent->m_pSrcTarget = this;
-  pEvent->m_dwCmd = pNote->m_dwCmd;
-  pEvent->m_dwKeyCode = pNote->m_dwKeyCode;
-  pEvent->m_dwFlags = pNote->m_dwFlags;
-  DispatchEvent(pEvent.get());
-}
-
-void IFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
-  if (m_pOuter) {
-    m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
-    return;
-  }
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
-  if (!pNoteDriver)
-    return;
-  pNoteDriver->SendEvent(pEvent);
-}
-
-void IFWL_Widget::Repaint(const CFX_RectF* pRect) {
-  if (pRect) {
-    m_pWidgetMgr->RepaintWidget(this, pRect);
-    return;
-  }
-  CFX_RectF rect;
-  rect = m_pProperties->m_rtWidget;
-  rect.left = rect.top = 0;
-  m_pWidgetMgr->RepaintWidget(this, &rect);
-}
-
-void IFWL_Widget::DrawBackground(CFX_Graphics* pGraphics,
-                                 CFWL_Part iPartBk,
-                                 IFWL_ThemeProvider* pTheme,
-                                 const CFX_Matrix* pMatrix) {
-  CFX_RectF rtRelative;
-  GetRelativeRect(rtRelative);
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = iPartBk;
-  param.m_pGraphics = pGraphics;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix, true);
-  param.m_rtPart = rtRelative;
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_Widget::DrawBorder(CFX_Graphics* pGraphics,
-                             CFWL_Part iPartBorder,
-                             IFWL_ThemeProvider* pTheme,
-                             const CFX_Matrix* pMatrix) {
-  CFX_RectF rtRelative;
-  GetRelativeRect(rtRelative);
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = iPartBorder;
-  param.m_pGraphics = pGraphics;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix, true);
-  param.m_rtPart = rtRelative;
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_Widget::DrawEdge(CFX_Graphics* pGraphics,
-                           CFWL_Part iPartEdge,
-                           IFWL_ThemeProvider* pTheme,
-                           const CFX_Matrix* pMatrix) {
-  CFX_RectF rtEdge;
-  GetEdgeRect(rtEdge);
-  CFWL_ThemeBackground param;
-  param.m_pWidget = this;
-  param.m_iPart = iPartEdge;
-  param.m_pGraphics = pGraphics;
-  if (pMatrix)
-    param.m_matrix.Concat(*pMatrix, true);
-  param.m_rtPart = rtEdge;
-  pTheme->DrawBackground(&param);
-}
-
-void IFWL_Widget::NotifyDriver() {
-  const CFWL_App* pApp = GetOwnerApp();
-  if (!pApp)
-    return;
-
-  CFWL_NoteDriver* pDriver =
-      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
-  if (!pDriver)
-    return;
-
-  pDriver->NotifyTargetDestroy(this);
-}
-
-CFX_SizeF IFWL_Widget::GetOffsetFromParent(IFWL_Widget* pParent) {
-  if (pParent == this)
-    return CFX_SizeF();
-
-  CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
-  if (!pWidgetMgr)
-    return CFX_SizeF();
-
-  CFX_SizeF szRet(m_pProperties->m_rtWidget.left,
-                  m_pProperties->m_rtWidget.top);
-
-  IFWL_Widget* pDstWidget = GetParent();
-  while (pDstWidget && pDstWidget != pParent) {
-    CFX_RectF rtDst;
-    pDstWidget->GetWidgetRect(rtDst);
-    szRet += CFX_SizeF(rtDst.left, rtDst.top);
-    pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget);
-  }
-  return szRet;
-}
-
-bool IFWL_Widget::IsParent(IFWL_Widget* pParent) {
-  IFWL_Widget* pUpWidget = GetParent();
-  while (pUpWidget) {
-    if (pUpWidget == pParent)
-      return true;
-    pUpWidget = pUpWidget->GetParent();
-  }
-  return false;
-}
-
-void IFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) {
-  if (!pMessage->m_pDstTarget)
-    return;
-
-  IFWL_Widget* pWidget = pMessage->m_pDstTarget;
-  CFWL_MessageType dwMsgCode = pMessage->GetClassID();
-  switch (dwMsgCode) {
-    case CFWL_MessageType::Mouse: {
-      CFWL_MsgMouse* pMsgMouse = static_cast<CFWL_MsgMouse*>(pMessage);
-      CFWL_EvtMouse evt;
-      evt.m_pSrcTarget = pWidget;
-      evt.m_pDstTarget = pWidget;
-      evt.m_dwCmd = pMsgMouse->m_dwCmd;
-      evt.m_dwFlags = pMsgMouse->m_dwFlags;
-      evt.m_fx = pMsgMouse->m_fx;
-      evt.m_fy = pMsgMouse->m_fy;
-      pWidget->DispatchEvent(&evt);
-      break;
-    }
-    case CFWL_MessageType::MouseWheel: {
-      CFWL_MsgMouseWheel* pMsgMouseWheel =
-          static_cast<CFWL_MsgMouseWheel*>(pMessage);
-      CFWL_EvtMouseWheel evt;
-      evt.m_pSrcTarget = pWidget;
-      evt.m_pDstTarget = pWidget;
-      evt.m_dwFlags = pMsgMouseWheel->m_dwFlags;
-      evt.m_fDeltaX = pMsgMouseWheel->m_fDeltaX;
-      evt.m_fDeltaY = pMsgMouseWheel->m_fDeltaY;
-      evt.m_fx = pMsgMouseWheel->m_fx;
-      evt.m_fy = pMsgMouseWheel->m_fy;
-      pWidget->DispatchEvent(&evt);
-      break;
-    }
-    case CFWL_MessageType::Key: {
-      CFWL_MsgKey* pMsgKey = static_cast<CFWL_MsgKey*>(pMessage);
-      CFWL_EvtKey evt;
-      evt.m_pSrcTarget = pWidget;
-      evt.m_pDstTarget = pWidget;
-      evt.m_dwKeyCode = pMsgKey->m_dwKeyCode;
-      evt.m_dwFlags = pMsgKey->m_dwFlags;
-      evt.m_dwCmd = pMsgKey->m_dwCmd;
-      pWidget->DispatchEvent(&evt);
-      break;
-    }
-    case CFWL_MessageType::SetFocus: {
-      CFWL_MsgSetFocus* pMsgSetFocus = static_cast<CFWL_MsgSetFocus*>(pMessage);
-      CFWL_EvtSetFocus evt;
-      evt.m_pSrcTarget = pMsgSetFocus->m_pDstTarget;
-      evt.m_pDstTarget = pMsgSetFocus->m_pDstTarget;
-      evt.m_pSetFocus = pWidget;
-      pWidget->DispatchEvent(&evt);
-      break;
-    }
-    case CFWL_MessageType::KillFocus: {
-      CFWL_MsgKillFocus* pMsgKillFocus =
-          static_cast<CFWL_MsgKillFocus*>(pMessage);
-      CFWL_EvtKillFocus evt;
-      evt.m_pSrcTarget = pMsgKillFocus->m_pDstTarget;
-      evt.m_pDstTarget = pMsgKillFocus->m_pDstTarget;
-      evt.m_pKillFocus = pWidget;
-      pWidget->DispatchEvent(&evt);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-void IFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}
-
-void IFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics,
-                               const CFX_Matrix* pMatrix) {}
diff --git a/xfa/fwl/core/ifwl_widget.h b/xfa/fwl/core/ifwl_widget.h
deleted file mode 100644
index 056a0c8..0000000
--- a/xfa/fwl/core/ifwl_widget.h
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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
-
-#ifndef XFA_FWL_CORE_IFWL_WIDGET_H_
-#define XFA_FWL_CORE_IFWL_WIDGET_H_
-
-#include <memory>
-
-#include "core/fxcrt/fx_coordinates.h"
-#include "core/fxcrt/fx_system.h"
-#include "xfa/fwl/core/cfwl_event.h"
-#include "xfa/fwl/core/cfwl_themepart.h"
-#include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/fwl_widgethit.h"
-#include "xfa/fwl/core/ifwl_widgetdelegate.h"
-#include "xfa/fwl/theme/cfwl_widgettp.h"
-
-// FWL contains two parallel inheritance hierarchies, which reference each
-// other via pointers as follows:
-//
-//                  m_pAssociate
-//                  <----------
-//      CFWL_Widget ----------> IFWL_Widget
-//           |       m_pIface        |
-//           A                       A
-//           |                       |
-//      CFWL_...                IFWL_...
-//
-// TODO(tsepez): Collapse these into a single hierarchy.
-//
-
-enum class FWL_Type {
-  Unknown = 0,
-
-  Barcode,
-  Caret,
-  CheckBox,
-  ComboBox,
-  DateTimePicker,
-  Edit,
-  Form,
-  FormProxy,
-  ListBox,
-  MonthCalendar,
-  PictureBox,
-  PushButton,
-  ScrollBar,
-  SpinButton,
-  ToolTip
-};
-
-class CFWL_AppImp;
-class CFWL_MsgKey;
-class CFWL_Widget;
-class CFWL_WidgetProperties;
-class CFWL_WidgetMgr;
-class CFWL_App;
-class IFWL_ThemeProvider;
-class IFWL_Widget;
-enum class FWL_Type;
-
-class IFWL_Widget : public IFWL_WidgetDelegate {
- public:
-  ~IFWL_Widget() override;
-
-  virtual FWL_Type GetClassID() const = 0;
-  virtual bool IsInstance(const CFX_WideStringC& wsClass) const;
-  virtual void GetWidgetRect(CFX_RectF& rect, bool bAutoSize = false);
-  virtual void GetClientRect(CFX_RectF& rect);
-  virtual void ModifyStylesEx(uint32_t dwStylesExAdded,
-                              uint32_t dwStylesExRemoved);
-  virtual void SetStates(uint32_t dwStates, bool bSet = true);
-  virtual void Update() = 0;
-  virtual FWL_WidgetHit HitTest(FX_FLOAT fx, FX_FLOAT fy);
-  virtual void DrawWidget(CFX_Graphics* pGraphics,
-                          const CFX_Matrix* pMatrix = nullptr) = 0;
-  virtual void SetThemeProvider(IFWL_ThemeProvider* pThemeProvider);
-
-  // IFWL_WidgetDelegate.
-  void OnProcessMessage(CFWL_Message* pMessage) override;
-  void OnProcessEvent(CFWL_Event* pEvent) override;
-  void OnDrawWidget(CFX_Graphics* pGraphics,
-                    const CFX_Matrix* pMatrix = nullptr) override;
-
-  void SetWidgetRect(const CFX_RectF& rect);
-
-  void SetParent(IFWL_Widget* pParent);
-
-  IFWL_Widget* GetOwner() { return m_pWidgetMgr->GetOwnerWidget(this); }
-  IFWL_Widget* GetOuter() const { return m_pOuter; }
-
-  uint32_t GetStyles() const;
-  void ModifyStyles(uint32_t dwStylesAdded, uint32_t dwStylesRemoved);
-  uint32_t GetStylesEx() const;
-  uint32_t GetStates() const;
-
-  void LockUpdate() { m_iLock++; }
-  void UnlockUpdate() {
-    if (IsLocked())
-      m_iLock--;
-  }
-
-  void TransformTo(IFWL_Widget* pWidget, FX_FLOAT& fx, FX_FLOAT& fy);
-  void GetMatrix(CFX_Matrix& matrix, bool bGlobal = false);
-  IFWL_ThemeProvider* GetThemeProvider() const;
-
-  void SetDelegate(IFWL_WidgetDelegate* delegate) { m_pDelegate = delegate; }
-  IFWL_WidgetDelegate* GetDelegate() {
-    return m_pDelegate ? m_pDelegate : this;
-  }
-  const IFWL_WidgetDelegate* GetDelegate() const {
-    return m_pDelegate ? m_pDelegate : this;
-  }
-
-  const CFWL_App* GetOwnerApp() const { return m_pOwnerApp; }
-  uint32_t GetEventKey() const { return m_nEventKey; }
-  void SetEventKey(uint32_t key) { m_nEventKey = key; }
-
-  void* GetLayoutItem() const { return m_pLayoutItem; }
-  void SetLayoutItem(void* pItem) { m_pLayoutItem = pItem; }
-
-  void SetAssociateWidget(CFWL_Widget* pAssociate) {
-    m_pAssociate = pAssociate;
-  }
-
-  void SetFocus(bool bFocus);
-  void Repaint(const CFX_RectF* pRect = nullptr);
-
- protected:
-  IFWL_Widget(const CFWL_App* app,
-              std::unique_ptr<CFWL_WidgetProperties> properties,
-              IFWL_Widget* pOuter);
-
-  bool IsEnabled() const;
-  bool IsActive() const;
-  bool IsLocked() const { return m_iLock > 0; }
-  bool HasBorder() const;
-  bool HasEdge() const;
-  void GetEdgeRect(CFX_RectF& rtEdge);
-  FX_FLOAT GetBorderSize(bool bCX = true);
-  FX_FLOAT GetEdgeWidth();
-  void GetRelativeRect(CFX_RectF& rect);
-  void* GetThemeCapacity(CFWL_WidgetCapacity dwCapacity);
-  IFWL_ThemeProvider* GetAvailableTheme();
-  CFX_SizeF CalcTextSize(const CFX_WideString& wsText,
-                         IFWL_ThemeProvider* pTheme,
-                         bool bMultiLine = false,
-                         int32_t iLineWidth = -1);
-  void CalcTextRect(const CFX_WideString& wsText,
-                    IFWL_ThemeProvider* pTheme,
-                    uint32_t dwTTOStyles,
-                    int32_t iTTOAlign,
-                    CFX_RectF& rect);
-  void SetGrab(bool bSet);
-  void GetPopupPos(FX_FLOAT fMinHeight,
-                   FX_FLOAT fMaxHeight,
-                   const CFX_RectF& rtAnchor,
-                   CFX_RectF& rtPopup);
-  void RegisterEventTarget(IFWL_Widget* pEventSource);
-  void UnregisterEventTarget();
-  void DispatchKeyEvent(CFWL_MsgKey* pNote);
-  void DispatchEvent(CFWL_Event* pEvent);
-  void DrawBorder(CFX_Graphics* pGraphics,
-                  CFWL_Part iPartBorder,
-                  IFWL_ThemeProvider* pTheme,
-                  const CFX_Matrix* pMatrix = nullptr);
-  void DrawEdge(CFX_Graphics* pGraphics,
-                CFWL_Part iPartEdge,
-                IFWL_ThemeProvider* pTheme,
-                const CFX_Matrix* pMatrix = nullptr);
-
-  const CFWL_App* const m_pOwnerApp;
-  CFWL_WidgetMgr* const m_pWidgetMgr;
-  std::unique_ptr<CFWL_WidgetProperties> m_pProperties;
-  IFWL_Widget* m_pOuter;
-  int32_t m_iLock;
-
- private:
-  IFWL_Widget* GetParent() { return m_pWidgetMgr->GetParentWidget(this); }
-  CFX_SizeF GetOffsetFromParent(IFWL_Widget* pParent);
-
-  bool IsVisible() const;
-  bool IsOverLapper() const;
-  bool IsPopup() const;
-  bool IsChild() const;
-  bool IsOffscreen() const;
-  IFWL_Widget* GetRootOuter();
-  bool GetPopupPosMenu(FX_FLOAT fMinHeight,
-                       FX_FLOAT fMaxHeight,
-                       const CFX_RectF& rtAnchor,
-                       CFX_RectF& rtPopup);
-  bool GetPopupPosComboBox(FX_FLOAT fMinHeight,
-                           FX_FLOAT fMaxHeight,
-                           const CFX_RectF& rtAnchor,
-                           CFX_RectF& rtPopup);
-  bool GetPopupPosGeneral(FX_FLOAT fMinHeight,
-                          FX_FLOAT fMaxHeight,
-                          const CFX_RectF& rtAnchor,
-                          CFX_RectF& rtPopup);
-  bool GetScreenSize(FX_FLOAT& fx, FX_FLOAT& fy);
-  void DrawBackground(CFX_Graphics* pGraphics,
-                      CFWL_Part iPartBk,
-                      IFWL_ThemeProvider* pTheme,
-                      const CFX_Matrix* pMatrix = nullptr);
-  void NotifyDriver();
-  bool IsParent(IFWL_Widget* pParent);
-
-  void* m_pLayoutItem;
-  CFWL_Widget* m_pAssociate;
-  uint32_t m_nEventKey;
-  IFWL_WidgetDelegate* m_pDelegate;  // Not owned.
-};
-
-#endif  // XFA_FWL_CORE_IFWL_WIDGET_H_
diff --git a/xfa/fwl/core/ifwl_widgetmgrdelegate.h b/xfa/fwl/core/ifwl_widgetmgrdelegate.h
index c832692..67f73d3 100644
--- a/xfa/fwl/core/ifwl_widgetmgrdelegate.h
+++ b/xfa/fwl/core/ifwl_widgetmgrdelegate.h
@@ -10,13 +10,13 @@
 class CFWL_Message;
 class CFX_Graphics;
 class CFX_Matrix;
-class IFWL_Widget;
+class CFWL_Widget;
 
-class IFWL_WidgetMgrDelegate {
+class CFWL_WidgetMgrDelegate {
  public:
   virtual void OnSetCapability(uint32_t dwCapability) = 0;
   virtual void OnProcessMessageToForm(CFWL_Message* pMessage) = 0;
-  virtual void OnDrawWidget(IFWL_Widget* pWidget,
+  virtual void OnDrawWidget(CFWL_Widget* pWidget,
                             CFX_Graphics* pGraphics,
                             const CFX_Matrix* pMatrix) = 0;
 };
diff --git a/xfa/fwl/theme/cfwl_barcodetp.cpp b/xfa/fwl/theme/cfwl_barcodetp.cpp
index a3a450e..96112e2 100644
--- a/xfa/fwl/theme/cfwl_barcodetp.cpp
+++ b/xfa/fwl/theme/cfwl_barcodetp.cpp
@@ -6,15 +6,15 @@
 
 #include "xfa/fwl/theme/cfwl_barcodetp.h"
 
+#include "xfa/fwl/core/cfwl_barcode.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_barcode.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 
 CFWL_BarcodeTP::CFWL_BarcodeTP() {}
 
 CFWL_BarcodeTP::~CFWL_BarcodeTP() {}
 
-bool CFWL_BarcodeTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_BarcodeTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::Barcode;
 }
 
diff --git a/xfa/fwl/theme/cfwl_barcodetp.h b/xfa/fwl/theme/cfwl_barcodetp.h
index 1eb34e7..adc79dc 100644
--- a/xfa/fwl/theme/cfwl_barcodetp.h
+++ b/xfa/fwl/theme/cfwl_barcodetp.h
@@ -16,7 +16,7 @@
   ~CFWL_BarcodeTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 };
 
diff --git a/xfa/fwl/theme/cfwl_carettp.cpp b/xfa/fwl/theme/cfwl_carettp.cpp
index 55de2a7..ff8c036 100644
--- a/xfa/fwl/theme/cfwl_carettp.cpp
+++ b/xfa/fwl/theme/cfwl_carettp.cpp
@@ -8,14 +8,14 @@
 
 #include "xfa/fwl/core/cfwl_caret.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
 CFWL_CaretTP::CFWL_CaretTP() {}
 CFWL_CaretTP::~CFWL_CaretTP() {}
 
-bool CFWL_CaretTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_CaretTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::Caret;
 }
 
diff --git a/xfa/fwl/theme/cfwl_carettp.h b/xfa/fwl/theme/cfwl_carettp.h
index bc745be..d618e72 100644
--- a/xfa/fwl/theme/cfwl_carettp.h
+++ b/xfa/fwl/theme/cfwl_carettp.h
@@ -15,7 +15,7 @@
   ~CFWL_CaretTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 
  protected:
diff --git a/xfa/fwl/theme/cfwl_checkboxtp.cpp b/xfa/fwl/theme/cfwl_checkboxtp.cpp
index 32c390a..5ea849e 100644
--- a/xfa/fwl/theme/cfwl_checkboxtp.cpp
+++ b/xfa/fwl/theme/cfwl_checkboxtp.cpp
@@ -8,10 +8,10 @@
 
 #include "core/fxge/cfx_pathdata.h"
 #include "xfa/fde/tto/fde_textout.h"
+#include "xfa/fwl/core/cfwl_checkbox.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/ifwl_checkbox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -35,7 +35,7 @@
     m_pCheckPath->Clear();
 }
 
-bool CFWL_CheckBoxTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_CheckBoxTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::CheckBox;
 }
 
@@ -297,7 +297,7 @@
   }
 }
 
-void CFWL_CheckBoxTP::DrawCheckSign(IFWL_Widget* pWidget,
+void CFWL_CheckBoxTP::DrawCheckSign(CFWL_Widget* pWidget,
                                     CFX_Graphics* pGraphics,
                                     const CFX_RectF& pRtBox,
                                     int32_t iState,
diff --git a/xfa/fwl/theme/cfwl_checkboxtp.h b/xfa/fwl/theme/cfwl_checkboxtp.h
index 81447b4..1dd204d 100644
--- a/xfa/fwl/theme/cfwl_checkboxtp.h
+++ b/xfa/fwl/theme/cfwl_checkboxtp.h
@@ -20,7 +20,7 @@
   // CFWL_WidgeTP
   void Initialize() override;
   void Finalize() override;
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawText(CFWL_ThemeText* pParams) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 
@@ -36,7 +36,7 @@
     FX_ARGB clrSignNeutralPressed;
   };
 
-  void DrawCheckSign(IFWL_Widget* pWidget,
+  void DrawCheckSign(CFWL_Widget* pWidget,
                      CFX_Graphics* pGraphics,
                      const CFX_RectF& pRtBox,
                      int32_t iState,
diff --git a/xfa/fwl/theme/cfwl_comboboxtp.cpp b/xfa/fwl/theme/cfwl_comboboxtp.cpp
index 3a4b880..8b4041b 100644
--- a/xfa/fwl/theme/cfwl_comboboxtp.cpp
+++ b/xfa/fwl/theme/cfwl_comboboxtp.cpp
@@ -6,10 +6,10 @@
 
 #include "xfa/fwl/theme/cfwl_comboboxtp.h"
 
+#include "xfa/fwl/core/cfwl_combobox.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -23,7 +23,7 @@
 
 CFWL_ComboBoxTP::~CFWL_ComboBoxTP() {}
 
-bool CFWL_ComboBoxTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_ComboBoxTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::ComboBox;
 }
 
diff --git a/xfa/fwl/theme/cfwl_comboboxtp.h b/xfa/fwl/theme/cfwl_comboboxtp.h
index 6c24821..6abca29 100644
--- a/xfa/fwl/theme/cfwl_comboboxtp.h
+++ b/xfa/fwl/theme/cfwl_comboboxtp.h
@@ -15,7 +15,7 @@
   ~CFWL_ComboBoxTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
   void* GetCapacity(CFWL_ThemePart* pThemePart,
                     CFWL_WidgetCapacity dwCapacity) override;
diff --git a/xfa/fwl/theme/cfwl_datetimepickertp.cpp b/xfa/fwl/theme/cfwl_datetimepickertp.cpp
index 7aeee04..3b5befb 100644
--- a/xfa/fwl/theme/cfwl_datetimepickertp.cpp
+++ b/xfa/fwl/theme/cfwl_datetimepickertp.cpp
@@ -6,14 +6,14 @@
 
 #include "xfa/fwl/theme/cfwl_datetimepickertp.h"
 
+#include "xfa/fwl/core/cfwl_datetimepicker.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
 
 CFWL_DateTimePickerTP::CFWL_DateTimePickerTP() {}
 
 CFWL_DateTimePickerTP::~CFWL_DateTimePickerTP() {}
 
-bool CFWL_DateTimePickerTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_DateTimePickerTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::DateTimePicker;
 }
 
diff --git a/xfa/fwl/theme/cfwl_datetimepickertp.h b/xfa/fwl/theme/cfwl_datetimepickertp.h
index d9950de..2e6ebba 100644
--- a/xfa/fwl/theme/cfwl_datetimepickertp.h
+++ b/xfa/fwl/theme/cfwl_datetimepickertp.h
@@ -15,7 +15,7 @@
   ~CFWL_DateTimePickerTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 
  protected:
diff --git a/xfa/fwl/theme/cfwl_edittp.cpp b/xfa/fwl/theme/cfwl_edittp.cpp
index 2c09f39..bd12939 100644
--- a/xfa/fwl/theme/cfwl_edittp.cpp
+++ b/xfa/fwl/theme/cfwl_edittp.cpp
@@ -6,9 +6,9 @@
 
 #include "xfa/fwl/theme/cfwl_edittp.h"
 
+#include "xfa/fwl/core/cfwl_edit.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxfa/app/xfa_fwltheme.h"
 #include "xfa/fxfa/xfa_ffwidget.h"
 #include "xfa/fxgraphics/cfx_color.h"
@@ -17,7 +17,7 @@
 CFWL_EditTP::CFWL_EditTP() {}
 CFWL_EditTP::~CFWL_EditTP() {}
 
-bool CFWL_EditTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_EditTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::Edit;
 }
 
diff --git a/xfa/fwl/theme/cfwl_edittp.h b/xfa/fwl/theme/cfwl_edittp.h
index 24d2e98..0230c36 100644
--- a/xfa/fwl/theme/cfwl_edittp.h
+++ b/xfa/fwl/theme/cfwl_edittp.h
@@ -17,7 +17,7 @@
   // CFWL_WidgeTTP
   void Initialize() override;
   void Finalize() override;
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 };
 
diff --git a/xfa/fwl/theme/cfwl_listboxtp.cpp b/xfa/fwl/theme/cfwl_listboxtp.cpp
index 9851349..8356820 100644
--- a/xfa/fwl/theme/cfwl_listboxtp.cpp
+++ b/xfa/fwl/theme/cfwl_listboxtp.cpp
@@ -6,9 +6,9 @@
 
 #include "xfa/fwl/theme/cfwl_listboxtp.h"
 
+#include "xfa/fwl/core/cfwl_listbox.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -16,7 +16,7 @@
 
 CFWL_ListBoxTP::~CFWL_ListBoxTP() {}
 
-bool CFWL_ListBoxTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_ListBoxTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::ListBox;
 }
 
diff --git a/xfa/fwl/theme/cfwl_listboxtp.h b/xfa/fwl/theme/cfwl_listboxtp.h
index 15967bd..4113f59 100644
--- a/xfa/fwl/theme/cfwl_listboxtp.h
+++ b/xfa/fwl/theme/cfwl_listboxtp.h
@@ -17,7 +17,7 @@
   // CFWL_WidgetTP
   void Initialize() override;
   void Finalize() override;
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 
  protected:
diff --git a/xfa/fwl/theme/cfwl_monthcalendartp.cpp b/xfa/fwl/theme/cfwl_monthcalendartp.cpp
index c0f29b6..d090e70 100644
--- a/xfa/fwl/theme/cfwl_monthcalendartp.cpp
+++ b/xfa/fwl/theme/cfwl_monthcalendartp.cpp
@@ -10,8 +10,8 @@
 #include "xfa/fwl/core/cfwl_monthcalendar.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -55,7 +55,7 @@
 
 CFWL_MonthCalendarTP::~CFWL_MonthCalendarTP() {}
 
-bool CFWL_MonthCalendarTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_MonthCalendarTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::MonthCalendar;
 }
 
diff --git a/xfa/fwl/theme/cfwl_monthcalendartp.h b/xfa/fwl/theme/cfwl_monthcalendartp.h
index dc60ef1..a0b1322 100644
--- a/xfa/fwl/theme/cfwl_monthcalendartp.h
+++ b/xfa/fwl/theme/cfwl_monthcalendartp.h
@@ -19,7 +19,7 @@
   // CFWL_WidgetTP
   void Initialize() override;
   void Finalize() override;
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
   void DrawText(CFWL_ThemeText* pParams) override;
   void* GetCapacity(CFWL_ThemePart* pThemePart,
diff --git a/xfa/fwl/theme/cfwl_pictureboxtp.cpp b/xfa/fwl/theme/cfwl_pictureboxtp.cpp
index 98ba21f..600de0e 100644
--- a/xfa/fwl/theme/cfwl_pictureboxtp.cpp
+++ b/xfa/fwl/theme/cfwl_pictureboxtp.cpp
@@ -6,15 +6,15 @@
 
 #include "xfa/fwl/theme/cfwl_pictureboxtp.h"
 
+#include "xfa/fwl/core/cfwl_picturebox.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_picturebox.h"
-#include "xfa/fwl/core/ifwl_widget.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 
 CFWL_PictureBoxTP::CFWL_PictureBoxTP() {}
 
 CFWL_PictureBoxTP::~CFWL_PictureBoxTP() {}
 
-bool CFWL_PictureBoxTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_PictureBoxTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::PictureBox;
 }
 
diff --git a/xfa/fwl/theme/cfwl_pictureboxtp.h b/xfa/fwl/theme/cfwl_pictureboxtp.h
index 24f658b..3152103 100644
--- a/xfa/fwl/theme/cfwl_pictureboxtp.h
+++ b/xfa/fwl/theme/cfwl_pictureboxtp.h
@@ -15,7 +15,7 @@
   ~CFWL_PictureBoxTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
 };
 
diff --git a/xfa/fwl/theme/cfwl_pushbuttontp.cpp b/xfa/fwl/theme/cfwl_pushbuttontp.cpp
index 3f38c0f..3b37b61 100644
--- a/xfa/fwl/theme/cfwl_pushbuttontp.cpp
+++ b/xfa/fwl/theme/cfwl_pushbuttontp.cpp
@@ -6,10 +6,10 @@
 
 #include "xfa/fwl/theme/cfwl_pushbuttontp.h"
 
+#include "xfa/fwl/core/cfwl_pushbutton.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
-#include "xfa/fwl/core/ifwl_pushbutton.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -21,7 +21,7 @@
 
 CFWL_PushButtonTP::~CFWL_PushButtonTP() {}
 
-bool CFWL_PushButtonTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_PushButtonTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::PushButton;
 }
 
diff --git a/xfa/fwl/theme/cfwl_pushbuttontp.h b/xfa/fwl/theme/cfwl_pushbuttontp.h
index 559f1a7..b0efe03 100644
--- a/xfa/fwl/theme/cfwl_pushbuttontp.h
+++ b/xfa/fwl/theme/cfwl_pushbuttontp.h
@@ -19,7 +19,7 @@
   // CFWL_WidgetTP
   void Initialize() override;
   void Finalize() override;
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
   void* GetCapacity(CFWL_ThemePart* pThemePart,
                     CFWL_WidgetCapacity dwCapacity) override;
diff --git a/xfa/fwl/theme/cfwl_scrollbartp.cpp b/xfa/fwl/theme/cfwl_scrollbartp.cpp
index d9f364e..19022ca 100644
--- a/xfa/fwl/theme/cfwl_scrollbartp.cpp
+++ b/xfa/fwl/theme/cfwl_scrollbartp.cpp
@@ -8,8 +8,8 @@
 
 #include "xfa/fwl/core/cfwl_scrollbar.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
 
@@ -25,7 +25,7 @@
 
 CFWL_ScrollBarTP::~CFWL_ScrollBarTP() {}
 
-bool CFWL_ScrollBarTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_ScrollBarTP::IsValidWidget(CFWL_Widget* pWidget) {
   return pWidget && pWidget->GetClassID() == FWL_Type::ScrollBar;
 }
 
@@ -42,7 +42,7 @@
   if (!pParams)
     return;
 
-  IFWL_Widget* pWidget = pParams->m_pWidget;
+  CFWL_Widget* pWidget = pParams->m_pWidget;
   FWLTHEME_STATE eState = FWLTHEME_STATE_Normal;
   if (pParams->m_dwStates & CFWL_PartState_Hovered)
     eState = FWLTHEME_STATE_Hover;
diff --git a/xfa/fwl/theme/cfwl_scrollbartp.h b/xfa/fwl/theme/cfwl_scrollbartp.h
index ef2bbc9..10138d6 100644
--- a/xfa/fwl/theme/cfwl_scrollbartp.h
+++ b/xfa/fwl/theme/cfwl_scrollbartp.h
@@ -17,7 +17,7 @@
   ~CFWL_ScrollBarTP() override;
 
   // CFWL_WidgetTP
-  bool IsValidWidget(IFWL_Widget* pWidget) override;
+  bool IsValidWidget(CFWL_Widget* pWidget) override;
   void DrawBackground(CFWL_ThemeBackground* pParams) override;
   void* GetCapacity(CFWL_ThemePart* pThemePart,
                     CFWL_WidgetCapacity dwCapacity) override;
diff --git a/xfa/fwl/theme/cfwl_widgettp.cpp b/xfa/fwl/theme/cfwl_widgettp.cpp
index 3f294aa..d578435 100644
--- a/xfa/fwl/theme/cfwl_widgettp.cpp
+++ b/xfa/fwl/theme/cfwl_widgettp.cpp
@@ -15,9 +15,9 @@
 #include "xfa/fwl/core/cfwl_themebackground.h"
 #include "xfa/fwl/core/cfwl_themepart.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
+#include "xfa/fwl/core/cfwl_widget.h"
 #include "xfa/fwl/core/cfwl_widgetmgr.h"
 #include "xfa/fwl/core/ifwl_themeprovider.h"
-#include "xfa/fwl/core/ifwl_widget.h"
 #include "xfa/fwl/theme/cfwl_arrowdata.h"
 #include "xfa/fxgraphics/cfx_color.h"
 #include "xfa/fxgraphics/cfx_path.h"
@@ -37,7 +37,7 @@
 
 }  // namespace
 
-bool CFWL_WidgetTP::IsValidWidget(IFWL_Widget* pWidget) {
+bool CFWL_WidgetTP::IsValidWidget(CFWL_Widget* pWidget) {
   return false;
 }
 
@@ -136,7 +136,7 @@
 
 CFWL_WidgetTP::~CFWL_WidgetTP() {}
 
-void CFWL_WidgetTP::SetFont(IFWL_Widget* pWidget,
+void CFWL_WidgetTP::SetFont(CFWL_Widget* pWidget,
                             const FX_WCHAR* strFont,
                             FX_FLOAT fFontSize,
                             FX_ARGB rgbFont) {
@@ -149,7 +149,7 @@
   m_pTextOut->SetTextColor(rgbFont);
 }
 
-void CFWL_WidgetTP::SetFont(IFWL_Widget* pWidget,
+void CFWL_WidgetTP::SetFont(CFWL_Widget* pWidget,
                             CFGAS_GEFont* pFont,
                             FX_FLOAT fFontSize,
                             FX_ARGB rgbFont) {
@@ -161,7 +161,7 @@
   m_pTextOut->SetTextColor(rgbFont);
 }
 
-CFGAS_GEFont* CFWL_WidgetTP::GetFont(IFWL_Widget* pWidget) {
+CFGAS_GEFont* CFWL_WidgetTP::GetFont(CFWL_Widget* pWidget) {
   return m_pFDEFont;
 }
 
diff --git a/xfa/fwl/theme/cfwl_widgettp.h b/xfa/fwl/theme/cfwl_widgettp.h
index 6093dd2..998d3c7 100644
--- a/xfa/fwl/theme/cfwl_widgettp.h
+++ b/xfa/fwl/theme/cfwl_widgettp.h
@@ -97,7 +97,7 @@
 class CFWL_ThemePart;
 class CFWL_ThemeText;
 class CFGAS_FontMgr;
-class IFWL_Widget;
+class CFWL_Widget;
 
 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
 class CFX_FontSourceEnum_File;
@@ -110,7 +110,7 @@
   virtual void Initialize();
   virtual void Finalize();
 
-  virtual bool IsValidWidget(IFWL_Widget* pWidget);
+  virtual bool IsValidWidget(CFWL_Widget* pWidget);
 
   virtual void DrawBackground(CFWL_ThemeBackground* pParams);
   virtual void DrawText(CFWL_ThemeText* pParams);
@@ -118,15 +118,15 @@
                             CFWL_WidgetCapacity dwCapacity);
   virtual void CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect);
 
-  void SetFont(IFWL_Widget* pWidget,
+  void SetFont(CFWL_Widget* pWidget,
                const FX_WCHAR* strFont,
                FX_FLOAT fFontSize,
                FX_ARGB rgbFont);
-  void SetFont(IFWL_Widget* pWidget,
+  void SetFont(CFWL_Widget* pWidget,
                CFGAS_GEFont* pFont,
                FX_FLOAT fFontSize,
                FX_ARGB rgbFont);
-  CFGAS_GEFont* GetFont(IFWL_Widget* pWidget);
+  CFGAS_GEFont* GetFont(CFWL_Widget* pWidget);
 
  protected:
   CFWL_WidgetTP();
diff --git a/xfa/fxfa/app/xfa_ffapp.cpp b/xfa/fxfa/app/xfa_ffapp.cpp
index b6b90ab..797c3e7 100644
--- a/xfa/fxfa/app/xfa_ffapp.cpp
+++ b/xfa/fxfa/app/xfa_ffapp.cpp
@@ -132,7 +132,7 @@
 }
 
 CXFA_FWLAdapterWidgetMgr* CXFA_FFApp::GetWidgetMgr(
-    IFWL_WidgetMgrDelegate* pDelegate) {
+    CFWL_WidgetMgrDelegate* pDelegate) {
   if (!m_pAdapterWidgetMgr) {
     m_pAdapterWidgetMgr.reset(new CXFA_FWLAdapterWidgetMgr);
     pDelegate->OnSetCapability(FWL_WGTMGR_DisableForm);
diff --git a/xfa/fxfa/app/xfa_ffbarcode.cpp b/xfa/fxfa/app/xfa_ffbarcode.cpp
index 355ab0f..f89f846 100644
--- a/xfa/fxfa/app/xfa_ffbarcode.cpp
+++ b/xfa/fxfa/app/xfa_ffbarcode.cpp
@@ -124,13 +124,12 @@
 
 bool CXFA_FFBarcode::LoadWidget() {
   CFWL_Barcode* pFWLBarcode = new CFWL_Barcode(GetFWLApp());
-  pFWLBarcode->Initialize();
 
   m_pNormalWidget = pFWLBarcode;
   m_pNormalWidget->SetLayoutItem(this);
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
diff --git a/xfa/fxfa/app/xfa_ffcheckbutton.cpp b/xfa/fxfa/app/xfa_ffcheckbutton.cpp
index a99b7b1..06e3b2c 100644
--- a/xfa/fxfa/app/xfa_ffcheckbutton.cpp
+++ b/xfa/fxfa/app/xfa_ffcheckbutton.cpp
@@ -28,13 +28,12 @@
 
 bool CXFA_FFCheckButton::LoadWidget() {
   CFWL_CheckBox* pCheckBox = new CFWL_CheckBox(GetFWLApp());
-  pCheckBox->Initialize();
   m_pNormalWidget = pCheckBox;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -238,8 +237,7 @@
   CFX_Matrix mt;
   mt.Set(1, 0, 0, 1, m_rtCheckBox.left, m_rtCheckBox.top);
   mt.Concat(mtRotate);
-  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
-                                                 pGS, &mt);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt);
 }
 bool CXFA_FFCheckButton::OnLButtonUp(uint32_t dwFlags,
                                      FX_FLOAT fx,
@@ -254,7 +252,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
diff --git a/xfa/fxfa/app/xfa_ffchoicelist.cpp b/xfa/fxfa/app/xfa_ffchoicelist.cpp
index eec4947..b289a39 100644
--- a/xfa/fxfa/app/xfa_ffchoicelist.cpp
+++ b/xfa/fxfa/app/xfa_ffchoicelist.cpp
@@ -6,14 +6,14 @@
 
 #include "xfa/fxfa/app/xfa_ffchoicelist.h"
 
+#include "third_party/base/ptr_util.h"
 #include "xfa/fwl/core/cfwl_app.h"
 #include "xfa/fwl/core/cfwl_combobox.h"
+#include "xfa/fwl/core/cfwl_edit.h"
 #include "xfa/fwl/core/cfwl_evtselectchanged.h"
 #include "xfa/fwl/core/cfwl_listbox.h"
 #include "xfa/fwl/core/cfwl_notedriver.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
+#include "xfa/fwl/core/cfwl_widgetproperties.h"
 #include "xfa/fxfa/app/xfa_fffield.h"
 #include "xfa/fxfa/app/xfa_fwladapter.h"
 #include "xfa/fxfa/cxfa_eventparam.h"
@@ -28,23 +28,23 @@
 
 CXFA_FFListBox::~CXFA_FFListBox() {
   if (m_pNormalWidget) {
-    IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-    CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-    pNoteDriver->UnregisterEventTarget(pWidget);
+    CFWL_NoteDriver* pNoteDriver =
+        m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+    pNoteDriver->UnregisterEventTarget(m_pNormalWidget);
   }
 }
 
 bool CXFA_FFListBox::LoadWidget() {
-  CFWL_ListBox* pListBox = new CFWL_ListBox(GetFWLApp());
-  pListBox->Initialize();
+  CFWL_ListBox* pListBox = new CFWL_ListBox(
+      GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
   pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground,
                          0xFFFFFFFF);
   m_pNormalWidget = (CFWL_Widget*)pListBox;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -151,7 +151,7 @@
   m_pNormalWidget->Update();
   return true;
 }
-void CXFA_FFListBox::OnSelectChanged(IFWL_Widget* pWidget,
+void CXFA_FFListBox::OnSelectChanged(CFWL_Widget* pWidget,
                                      const CFX_Int32Array& arrSels) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Change;
@@ -197,7 +197,7 @@
   switch (pEvent->GetClassID()) {
     case CFWL_EventType::SelectChanged: {
       CFX_Int32Array arrSels;
-      OnSelectChanged(m_pNormalWidget->GetWidget(), arrSels);
+      OnSelectChanged(m_pNormalWidget, arrSels);
       break;
     }
     default:
@@ -237,13 +237,12 @@
 }
 bool CXFA_FFComboBox::LoadWidget() {
   CFWL_ComboBox* pComboBox = new CFWL_ComboBox(GetFWLApp());
-  pComboBox->Initialize();
   m_pNormalWidget = (CFWL_Widget*)pComboBox;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -475,15 +474,14 @@
   m_pNormalWidget->Update();
   AddInvalidateRect();
 }
-void CXFA_FFComboBox::OnTextChanged(IFWL_Widget* pWidget,
+void CXFA_FFComboBox::OnTextChanged(CFWL_Widget* pWidget,
                                     const CFX_WideString& wsChanged) {
   CXFA_EventParam eParam;
   m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
   eParam.m_wsChange = wsChanged;
   FWLEventSelChange(&eParam);
 }
-void CXFA_FFComboBox::OnSelectChanged(IFWL_Widget* pWidget,
-                                      bool bLButtonUp) {
+void CXFA_FFComboBox::OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp) {
   CXFA_EventParam eParam;
   m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
   FWLEventSelChange(&eParam);
@@ -492,13 +490,13 @@
     m_pDocView->SetFocusWidgetAcc(nullptr);
   }
 }
-void CXFA_FFComboBox::OnPreOpen(IFWL_Widget* pWidget) {
+void CXFA_FFComboBox::OnPreOpen(CFWL_Widget* pWidget) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_PreOpen;
   eParam.m_pTarget = m_pDataAcc;
   m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PreOpen, &eParam);
 }
-void CXFA_FFComboBox::OnPostOpen(IFWL_Widget* pWidget) {
+void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_PostOpen;
   eParam.m_pTarget = m_pDataAcc;
@@ -515,20 +513,20 @@
     case CFWL_EventType::SelectChanged: {
       CFWL_EvtSelectChanged* postEvent =
           static_cast<CFWL_EvtSelectChanged*>(pEvent);
-      OnSelectChanged(m_pNormalWidget->GetWidget(), postEvent->bLButtonUp);
+      OnSelectChanged(m_pNormalWidget, postEvent->bLButtonUp);
       break;
     }
     case CFWL_EventType::EditChanged: {
       CFX_WideString wsChanged;
-      OnTextChanged(m_pNormalWidget->GetWidget(), wsChanged);
+      OnTextChanged(m_pNormalWidget, wsChanged);
       break;
     }
     case CFWL_EventType::PreDropDown: {
-      OnPreOpen(m_pNormalWidget->GetWidget());
+      OnPreOpen(m_pNormalWidget);
       break;
     }
     case CFWL_EventType::PostDropDown: {
-      OnPostOpen(m_pNormalWidget->GetWidget());
+      OnPostOpen(m_pNormalWidget);
       break;
     }
     default:
diff --git a/xfa/fxfa/app/xfa_ffchoicelist.h b/xfa/fxfa/app/xfa_ffchoicelist.h
index 1855d19..e9bee6f 100644
--- a/xfa/fxfa/app/xfa_ffchoicelist.h
+++ b/xfa/fxfa/app/xfa_ffchoicelist.h
@@ -23,7 +23,7 @@
   void OnDrawWidget(CFX_Graphics* pGraphics,
                     const CFX_Matrix* pMatrix = nullptr) override;
 
-  void OnSelectChanged(IFWL_Widget* pWidget, const CFX_Int32Array& arrSels);
+  void OnSelectChanged(CFWL_Widget* pWidget, const CFX_Int32Array& arrSels);
   void SetItemState(int32_t nIndex, bool bSelected);
   void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1);
   void DeleteItem(int32_t nIndex);
@@ -75,11 +75,10 @@
 
   virtual void OpenDropDownList();
 
-  void OnTextChanged(IFWL_Widget* pWidget, const CFX_WideString& wsChanged);
-  void OnSelectChanged(IFWL_Widget* pWidget,
-                       bool bLButtonUp);
-  void OnPreOpen(IFWL_Widget* pWidget);
-  void OnPostOpen(IFWL_Widget* pWidget);
+  void OnTextChanged(CFWL_Widget* pWidget, const CFX_WideString& wsChanged);
+  void OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp);
+  void OnPreOpen(CFWL_Widget* pWidget);
+  void OnPostOpen(CFWL_Widget* pWidget);
   void SetItemState(int32_t nIndex, bool bSelected);
   void InsertItem(const CFX_WideStringC& wsLabel, int32_t nIndex = -1);
   void DeleteItem(int32_t nIndex);
diff --git a/xfa/fxfa/app/xfa_fffield.cpp b/xfa/fxfa/app/xfa_fffield.cpp
index ac9317e..43efb5e 100644
--- a/xfa/fxfa/app/xfa_fffield.cpp
+++ b/xfa/fxfa/app/xfa_fffield.cpp
@@ -15,7 +15,6 @@
 #include "xfa/fwl/core/cfwl_msgsetfocus.h"
 #include "xfa/fwl/core/cfwl_picturebox.h"
 #include "xfa/fwl/core/cfwl_widgetmgr.h"
-#include "xfa/fwl/core/ifwl_edit.h"
 #include "xfa/fxfa/app/xfa_fwltheme.h"
 #include "xfa/fxfa/app/xfa_textlayout.h"
 #include "xfa/fxfa/xfa_ffapp.h"
@@ -75,8 +74,7 @@
   CFX_Matrix mt;
   mt.Set(1, 0, 0, 1, rtWidget.left, rtWidget.top);
   mt.Concat(mtRotate);
-  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
-                                                 pGS, &mt);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt);
 }
 void CXFA_FFField::DrawHighlight(CFX_Graphics* pGS,
                                  CFX_Matrix* pMatrix,
@@ -114,9 +112,8 @@
   }
 }
 void CXFA_FFField::SetFWLThemeProvider() {
-  if (m_pNormalWidget) {
-    m_pNormalWidget->GetWidget()->SetThemeProvider(GetApp()->GetFWLTheme());
-  }
+  if (m_pNormalWidget)
+    m_pNormalWidget->SetThemeProvider(GetApp()->GetFWLTheme());
 }
 bool CXFA_FFField::IsLoaded() {
   return m_pNormalWidget && CXFA_FFWidget::IsLoaded();
@@ -354,7 +351,7 @@
   }
   CFWL_MsgMouse ms;
   ms.m_dwCmd = FWL_MouseCommand::Enter;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   return true;
@@ -365,7 +362,7 @@
   }
   CFWL_MsgMouse ms;
   ms.m_dwCmd = FWL_MouseCommand::Leave;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -396,7 +393,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -414,7 +411,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -428,7 +425,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -442,7 +439,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -460,7 +457,7 @@
   FWLToClient(ms.m_fx, ms.m_fy);
   ms.m_fDeltaX = zDelta;
   ms.m_fDeltaY = 0;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -482,7 +479,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -500,7 +497,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -514,7 +511,7 @@
   ms.m_fx = fx;
   ms.m_fy = fy;
   FWLToClient(ms.m_fx, ms.m_fy);
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   TranslateFWLMessage(&ms);
   return true;
 }
@@ -525,7 +522,7 @@
     return false;
   }
   CFWL_MsgSetFocus ms;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   m_dwStatus |= XFA_WidgetStatus_Focused;
@@ -537,7 +534,7 @@
     return CXFA_FFWidget::OnKillFocus(pNewWidget);
   }
   CFWL_MsgKillFocus ms;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   m_dwStatus &= ~XFA_WidgetStatus_Focused;
@@ -553,7 +550,7 @@
   ms.m_dwCmd = FWL_KeyCommand::KeyDown;
   ms.m_dwFlags = dwFlags;
   ms.m_dwKeyCode = dwKeyCode;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   return true;
@@ -566,7 +563,7 @@
   ms.m_dwCmd = FWL_KeyCommand::KeyUp;
   ms.m_dwFlags = dwFlags;
   ms.m_dwKeyCode = dwKeyCode;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   return true;
@@ -588,7 +585,7 @@
   ms.m_dwCmd = FWL_KeyCommand::Char;
   ms.m_dwFlags = dwFlags;
   ms.m_dwKeyCode = dwChar;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   return true;
diff --git a/xfa/fxfa/app/xfa_ffimageedit.cpp b/xfa/fxfa/app/xfa_ffimageedit.cpp
index 89188b2..318a772 100644
--- a/xfa/fxfa/app/xfa_ffimageedit.cpp
+++ b/xfa/fxfa/app/xfa_ffimageedit.cpp
@@ -24,13 +24,12 @@
 }
 bool CXFA_FFImageEdit::LoadWidget() {
   CFWL_PictureBox* pPictureBox = new CFWL_PictureBox(GetFWLApp());
-  pPictureBox->Initialize();
   m_pNormalWidget = pPictureBox;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = pPictureBox->GetDelegate();
   pPictureBox->SetDelegate(this);
@@ -99,7 +98,7 @@
   ms.m_dwFlags = dwFlags;
   ms.m_fx = fx;
   ms.m_fy = fy;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   FWLToClient(ms.m_fx, ms.m_fy);
   TranslateFWLMessage(&ms);
   return true;
diff --git a/xfa/fxfa/app/xfa_ffpushbutton.cpp b/xfa/fxfa/app/xfa_ffpushbutton.cpp
index ba0bdcf..df093a0 100644
--- a/xfa/fxfa/app/xfa_ffpushbutton.cpp
+++ b/xfa/fxfa/app/xfa_ffpushbutton.cpp
@@ -47,22 +47,20 @@
   CFX_Matrix mt;
   mt.Set(1, 0, 0, 1, rtWidget.left, rtWidget.top);
   mt.Concat(mtRotate);
-  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget->GetWidget(),
-                                                 pGS, &mt);
+  GetApp()->GetWidgetMgrDelegate()->OnDrawWidget(m_pNormalWidget, pGS, &mt);
 }
 bool CXFA_FFPushButton::LoadWidget() {
   ASSERT(!m_pNormalWidget);
   CFWL_PushButton* pPushButton = new CFWL_PushButton(GetFWLApp());
-  pPushButton->Initialize();
-
   m_pOldDelegate = pPushButton->GetDelegate();
   pPushButton->SetDelegate(this);
 
   m_pNormalWidget = pPushButton;
   m_pNormalWidget->SetLayoutItem(this);
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
   m_pNormalWidget->LockUpdate();
   UpdateWidgetProperty();
   LoadHighlightCaption();
diff --git a/xfa/fxfa/app/xfa_fftextedit.cpp b/xfa/fxfa/app/xfa_fftextedit.cpp
index d13e946..77ca7a6 100644
--- a/xfa/fxfa/app/xfa_fftextedit.cpp
+++ b/xfa/fxfa/app/xfa_fftextedit.cpp
@@ -35,21 +35,21 @@
 
 CXFA_FFTextEdit::~CXFA_FFTextEdit() {
   if (m_pNormalWidget) {
-    IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-    CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-    pNoteDriver->UnregisterEventTarget(pWidget);
+    CFWL_NoteDriver* pNoteDriver =
+        m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+    pNoteDriver->UnregisterEventTarget(m_pNormalWidget);
   }
 }
 
 bool CXFA_FFTextEdit::LoadWidget() {
-  CFWL_Edit* pFWLEdit = new CFWL_Edit(GetFWLApp());
-  pFWLEdit->Initialize();
+  CFWL_Edit* pFWLEdit = new CFWL_Edit(
+      GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
   m_pNormalWidget = pFWLEdit;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pWidget, pWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -122,7 +122,7 @@
   ms.m_dwFlags = dwFlags;
   ms.m_fx = fx;
   ms.m_fy = fy;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   FWLToClient(ms.m_fx, ms.m_fy);
   TranslateFWLMessage(&ms);
   return true;
@@ -167,14 +167,14 @@
   }
   CXFA_FFWidget::OnSetFocus(pOldWidget);
   CFWL_MsgSetFocus ms;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   return true;
 }
 bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) {
   CFWL_MsgKillFocus ms;
-  ms.m_pDstTarget = m_pNormalWidget->GetWidget();
+  ms.m_pDstTarget = m_pNormalWidget;
   ms.m_pSrcTarget = nullptr;
   TranslateFWLMessage(&ms);
   m_dwStatus &= ~XFA_WidgetStatus_Focused;
@@ -294,7 +294,7 @@
   }
   return true;
 }
-void CXFA_FFTextEdit::OnTextChanged(IFWL_Widget* pWidget,
+void CXFA_FFTextEdit::OnTextChanged(CFWL_Widget* pWidget,
                                     const CFX_WideString& wsChanged,
                                     const CFX_WideString& wsPrevText) {
   m_dwStatus |= XFA_WidgetStatus_TextEditValueChanged;
@@ -320,7 +320,7 @@
   }
   m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
 }
-void CXFA_FFTextEdit::OnTextFull(IFWL_Widget* pWidget) {
+void CXFA_FFTextEdit::OnTextFull(CFWL_Widget* pWidget) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Full;
   eParam.m_pTarget = m_pDataAcc;
@@ -343,11 +343,11 @@
     case CFWL_EventType::TextChanged: {
       CFWL_EvtTextChanged* event = static_cast<CFWL_EvtTextChanged*>(pEvent);
       CFX_WideString wsChange;
-      OnTextChanged(m_pNormalWidget->GetWidget(), wsChange, event->wsPrevText);
+      OnTextChanged(m_pNormalWidget, wsChange, event->wsPrevText);
       break;
     }
     case CFWL_EventType::TextFull: {
-      OnTextFull(m_pNormalWidget->GetWidget());
+      OnTextFull(m_pNormalWidget);
       break;
     }
     case CFWL_EventType::CheckWord: {
@@ -372,14 +372,14 @@
     : CXFA_FFTextEdit(pPageView, pDataAcc) {}
 CXFA_FFNumericEdit::~CXFA_FFNumericEdit() {}
 bool CXFA_FFNumericEdit::LoadWidget() {
-  CFWL_Edit* pWidget = new CFWL_Edit(GetFWLApp());
-  pWidget->Initialize();
+  CFWL_Edit* pWidget = new CFWL_Edit(
+      GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
   m_pNormalWidget = pWidget;
 
-  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
   m_pNormalWidget->SetLayoutItem(this);
-  CFWL_NoteDriver* pNoteDriver = pIWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -421,14 +421,13 @@
 void CXFA_FFNumericEdit::OnProcessEvent(CFWL_Event* pEvent) {
   if (pEvent->GetClassID() == CFWL_EventType::Validate) {
     CFWL_EvtValidate* event = static_cast<CFWL_EvtValidate*>(pEvent);
-    event->bValidate =
-        OnValidate(m_pNormalWidget->GetWidget(), event->wsInsert);
+    event->bValidate = OnValidate(m_pNormalWidget, event->wsInsert);
     return;
   }
   CXFA_FFTextEdit::OnProcessEvent(pEvent);
 }
 
-bool CXFA_FFNumericEdit::OnValidate(IFWL_Widget* pWidget,
+bool CXFA_FFNumericEdit::OnValidate(CFWL_Widget* pWidget,
                                     CFX_WideString& wsText) {
   CFX_WideString wsPattern;
   m_pDataAcc->GetPictureContent(wsPattern, XFA_VALUEPICTURE_Edit);
@@ -452,14 +451,14 @@
 CXFA_FFPasswordEdit::~CXFA_FFPasswordEdit() {}
 
 bool CXFA_FFPasswordEdit::LoadWidget() {
-  CFWL_Edit* pWidget = new CFWL_Edit(GetFWLApp());
-  pWidget->Initialize();
+  CFWL_Edit* pWidget = new CFWL_Edit(
+      GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
   m_pNormalWidget = pWidget;
   m_pNormalWidget->SetLayoutItem(this);
 
-  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pIWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -523,12 +522,11 @@
 }
 bool CXFA_FFDateTimeEdit::LoadWidget() {
   CFWL_DateTimePicker* pWidget = new CFWL_DateTimePicker(GetFWLApp());
-  pWidget->Initialize();
   m_pNormalWidget = pWidget;
   m_pNormalWidget->SetLayoutItem(this);
-  IFWL_Widget* pIWidget = m_pNormalWidget->GetWidget();
-  CFWL_NoteDriver* pNoteDriver = pIWidget->GetOwnerApp()->GetNoteDriver();
-  pNoteDriver->RegisterEventTarget(pIWidget, pIWidget);
+  CFWL_NoteDriver* pNoteDriver =
+      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
+  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);
 
   m_pOldDelegate = m_pNormalWidget->GetDelegate();
   m_pNormalWidget->SetDelegate(this);
@@ -661,7 +659,7 @@
   return wsOldValue != wsText;
 }
 
-void CXFA_FFDateTimeEdit::OnSelectChanged(IFWL_Widget* pWidget,
+void CXFA_FFDateTimeEdit::OnSelectChanged(CFWL_Widget* pWidget,
                                           int32_t iYear,
                                           int32_t iMonth,
                                           int32_t iDay) {
@@ -688,8 +686,7 @@
 void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) {
   if (pEvent->GetClassID() == CFWL_EventType::SelectChanged) {
     CFWL_EvtSelectChanged* event = static_cast<CFWL_EvtSelectChanged*>(pEvent);
-    OnSelectChanged(m_pNormalWidget->GetWidget(), event->iYear, event->iMonth,
-                    event->iDay);
+    OnSelectChanged(m_pNormalWidget, event->iYear, event->iMonth, event->iDay);
     return;
   }
   CXFA_FFTextEdit::OnProcessEvent(pEvent);
diff --git a/xfa/fxfa/app/xfa_fftextedit.h b/xfa/fxfa/app/xfa_fftextedit.h
index 115b370..88622e3 100644
--- a/xfa/fxfa/app/xfa_fftextedit.h
+++ b/xfa/fxfa/app/xfa_fftextedit.h
@@ -29,10 +29,10 @@
   void OnDrawWidget(CFX_Graphics* pGraphics,
                     const CFX_Matrix* pMatrix = nullptr) override;
 
-  void OnTextChanged(IFWL_Widget* pWidget,
+  void OnTextChanged(CFWL_Widget* pWidget,
                      const CFX_WideString& wsChanged,
                      const CFX_WideString& wsPrevText);
-  void OnTextFull(IFWL_Widget* pWidget);
+  void OnTextFull(CFWL_Widget* pWidget);
   bool CheckWord(const CFX_ByteStringC& sWord);
 
  protected:
@@ -57,7 +57,7 @@
   void OnProcessEvent(CFWL_Event* pEvent) override;
 
  public:
-  bool OnValidate(IFWL_Widget* pWidget, CFX_WideString& wsText);
+  bool OnValidate(CFWL_Widget* pWidget, CFX_WideString& wsText);
 };
 
 class CXFA_FFPasswordEdit : public CXFA_FFTextEdit {
@@ -91,7 +91,7 @@
   void UpdateWidgetProperty() override;
   void OnProcessEvent(CFWL_Event* pEvent) override;
 
-  void OnSelectChanged(IFWL_Widget* pWidget,
+  void OnSelectChanged(CFWL_Widget* pWidget,
                        int32_t iYear,
                        int32_t iMonth,
                        int32_t iDay);
diff --git a/xfa/fxfa/app/xfa_fwladapter.cpp b/xfa/fxfa/app/xfa_fwladapter.cpp
index ba38f85..63a4a92 100644
--- a/xfa/fxfa/app/xfa_fwladapter.cpp
+++ b/xfa/fxfa/app/xfa_fwladapter.cpp
@@ -13,7 +13,7 @@
 
 CXFA_FWLAdapterWidgetMgr::~CXFA_FWLAdapterWidgetMgr() {}
 
-void CXFA_FWLAdapterWidgetMgr::RepaintWidget(IFWL_Widget* pWidget,
+void CXFA_FWLAdapterWidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
                                              const CFX_RectF* pRect) {
   if (!pWidget)
     return;
@@ -26,7 +26,7 @@
   pFFWidget->AddInvalidateRect(nullptr);
 }
 
-bool CXFA_FWLAdapterWidgetMgr::GetPopupPos(IFWL_Widget* pWidget,
+bool CXFA_FWLAdapterWidgetMgr::GetPopupPos(CFWL_Widget* pWidget,
                                            FX_FLOAT fMinHeight,
                                            FX_FLOAT fMaxHeight,
                                            const CFX_RectF& rtAnchor,
diff --git a/xfa/fxfa/app/xfa_fwladapter.h b/xfa/fxfa/app/xfa_fwladapter.h
index 489d870..3aaa04e 100644
--- a/xfa/fxfa/app/xfa_fwladapter.h
+++ b/xfa/fxfa/app/xfa_fwladapter.h
@@ -11,15 +11,15 @@
 #include "core/fxcrt/fx_system.h"
 #include "xfa/fwl/core/fwl_error.h"
 
-class IFWL_Widget;
+class CFWL_Widget;
 
 class CXFA_FWLAdapterWidgetMgr {
  public:
   CXFA_FWLAdapterWidgetMgr();
   ~CXFA_FWLAdapterWidgetMgr();
 
-  void RepaintWidget(IFWL_Widget* pWidget, const CFX_RectF* pRect);
-  bool GetPopupPos(IFWL_Widget* pWidget,
+  void RepaintWidget(CFWL_Widget* pWidget, const CFX_RectF* pRect);
+  bool GetPopupPos(CFWL_Widget* pWidget,
                    FX_FLOAT fMinHeight,
                    FX_FLOAT fMaxHeight,
                    const CFX_RectF& rtAnchor,
diff --git a/xfa/fxfa/app/xfa_fwltheme.cpp b/xfa/fxfa/app/xfa_fwltheme.cpp
index 782038a..0222ddd 100644
--- a/xfa/fxfa/app/xfa_fwltheme.cpp
+++ b/xfa/fxfa/app/xfa_fwltheme.cpp
@@ -9,19 +9,19 @@
 #include "xfa/fde/tto/fde_textout.h"
 #include "xfa/fgas/crt/fgas_codepage.h"
 #include "xfa/fgas/font/cfgas_gefont.h"
+#include "xfa/fwl/core/cfwl_barcode.h"
 #include "xfa/fwl/core/cfwl_caret.h"
+#include "xfa/fwl/core/cfwl_checkbox.h"
+#include "xfa/fwl/core/cfwl_combobox.h"
+#include "xfa/fwl/core/cfwl_datetimepicker.h"
+#include "xfa/fwl/core/cfwl_edit.h"
+#include "xfa/fwl/core/cfwl_listbox.h"
 #include "xfa/fwl/core/cfwl_monthcalendar.h"
+#include "xfa/fwl/core/cfwl_picturebox.h"
+#include "xfa/fwl/core/cfwl_pushbutton.h"
 #include "xfa/fwl/core/cfwl_scrollbar.h"
 #include "xfa/fwl/core/cfwl_themebackground.h"
 #include "xfa/fwl/core/cfwl_themetext.h"
-#include "xfa/fwl/core/ifwl_barcode.h"
-#include "xfa/fwl/core/ifwl_checkbox.h"
-#include "xfa/fwl/core/ifwl_combobox.h"
-#include "xfa/fwl/core/ifwl_datetimepicker.h"
-#include "xfa/fwl/core/ifwl_edit.h"
-#include "xfa/fwl/core/ifwl_listbox.h"
-#include "xfa/fwl/core/ifwl_picturebox.h"
-#include "xfa/fwl/core/ifwl_pushbutton.h"
 #include "xfa/fxfa/xfa_ffapp.h"
 #include "xfa/fxfa/xfa_ffwidget.h"
 #include "xfa/fxgraphics/cfx_color.h"
@@ -34,8 +34,8 @@
 
 }  // namespace
 
-CXFA_FFWidget* XFA_ThemeGetOuterWidget(IFWL_Widget* pWidget) {
-  IFWL_Widget* pOuter = pWidget;
+CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget) {
+  CFWL_Widget* pOuter = pWidget;
   while (pOuter && pOuter->GetOuter())
     pOuter = pOuter->GetOuter();
 
@@ -342,7 +342,7 @@
                             pParams->m_wsText.GetLength(), rect);
 }
 
-CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(IFWL_Widget* pWidget) {
+CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(CFWL_Widget* pWidget) {
   switch (pWidget->GetClassID()) {
     case FWL_Type::CheckBox:
       return m_pCheckBoxTP.get();
diff --git a/xfa/fxfa/app/xfa_fwltheme.h b/xfa/fxfa/app/xfa_fwltheme.h
index 4ba3ffb..2579950 100644
--- a/xfa/fxfa/app/xfa_fwltheme.h
+++ b/xfa/fxfa/app/xfa_fwltheme.h
@@ -37,7 +37,7 @@
   void CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) override;
 
  private:
-  CFWL_WidgetTP* GetTheme(IFWL_Widget* pWidget);
+  CFWL_WidgetTP* GetTheme(CFWL_Widget* pWidget);
   std::unique_ptr<CFWL_CheckBoxTP> m_pCheckBoxTP;
   std::unique_ptr<CFWL_ListBoxTP> m_pListBoxTP;
   std::unique_ptr<CFWL_PictureBoxTP> m_pPictureBoxTP;
@@ -59,6 +59,6 @@
   CFX_SizeF m_SizeAboveBelow;
 };
 
-CXFA_FFWidget* XFA_ThemeGetOuterWidget(IFWL_Widget* pWidget);
+CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget);
 
 #endif  // XFA_FXFA_APP_XFA_FWLTHEME_H_
diff --git a/xfa/fxfa/xfa_ffapp.h b/xfa/fxfa/xfa_ffapp.h
index 4b40ba7..6dbdb72 100644
--- a/xfa/fxfa/xfa_ffapp.h
+++ b/xfa/fxfa/xfa_ffapp.h
@@ -22,7 +22,7 @@
 class CXFA_FFDocHandler;
 class CXFA_FontMgr;
 class IFWL_AdapterTimerMgr;
-class IFWL_WidgetMgrDelegate;
+class CFWL_WidgetMgrDelegate;
 
 class CXFA_FileRead : public IFX_SeekableReadStream {
  public:
@@ -51,7 +51,7 @@
   void SetDefaultFontMgr(std::unique_ptr<CXFA_DefFontMgr> pFontMgr);
 
   CXFA_FFDocHandler* GetDocHandler();
-  CXFA_FWLAdapterWidgetMgr* GetWidgetMgr(IFWL_WidgetMgrDelegate* pDelegate);
+  CXFA_FWLAdapterWidgetMgr* GetWidgetMgr(CFWL_WidgetMgrDelegate* pDelegate);
   CFGAS_FontMgr* GetFDEFontMgr();
   CXFA_FWLTheme* GetFWLTheme();
 
@@ -59,7 +59,7 @@
   const CFWL_App* GetFWLApp() const { return m_pFWLApp.get(); }
   IFWL_AdapterTimerMgr* GetTimerMgr() const;
   CXFA_FontMgr* GetXFAFontMgr() const;
-  IFWL_WidgetMgrDelegate* GetWidgetMgrDelegate() const {
+  CFWL_WidgetMgrDelegate* GetWidgetMgrDelegate() const {
     return m_pWidgetMgrDelegate;
   }
 
@@ -86,7 +86,7 @@
   std::unique_ptr<CFX_FontSourceEnum_File> m_pFontSource;
 #endif
   std::unique_ptr<CXFA_FWLAdapterWidgetMgr> m_pAdapterWidgetMgr;
-  IFWL_WidgetMgrDelegate* m_pWidgetMgrDelegate;  // not owned.
+  CFWL_WidgetMgrDelegate* m_pWidgetMgrDelegate;  // not owned.
 
   // |m_pFWLApp| has to be released first, then |m_pFWLTheme| since the former
   // may refers to theme manager and the latter refers to font manager.