Add CFFL_TextField class.

This class implements common code used by several CFFL_FormFiller
sub-classes. Make those sub-classes inherit from CFFL_TextField, instead
of inheriting from CFFL_FormFiller directly and then implementing the
same functionality multiple times.

Change-Id: Iad8a735b6d6e18e89d617636b753805d3f77a286
Reviewed-on: https://pdfium-review.googlesource.com/9850
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index db87b16..59b116f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1204,6 +1204,8 @@
     "fpdfsdk/formfiller/cffl_radiobutton.h",
     "fpdfsdk/formfiller/cffl_textfield.cpp",
     "fpdfsdk/formfiller/cffl_textfield.h",
+    "fpdfsdk/formfiller/cffl_textobject.cpp",
+    "fpdfsdk/formfiller/cffl_textobject.h",
   ]
   configs += [ ":pdfium_core_config" ]
   deps = [
diff --git a/fpdfsdk/formfiller/cffl_combobox.cpp b/fpdfsdk/formfiller/cffl_combobox.cpp
index c4554c1..98f98b3 100644
--- a/fpdfsdk/formfiller/cffl_combobox.cpp
+++ b/fpdfsdk/formfiller/cffl_combobox.cpp
@@ -9,7 +9,6 @@
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_widget.h"
 #include "fpdfsdk/formfiller/cba_fontmap.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
 #include "fpdfsdk/fsdk_common.h"
 #include "fpdfsdk/pwl/cpwl_combo_box.h"
@@ -17,7 +16,7 @@
 
 CFFL_ComboBox::CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp,
                              CPDFSDK_Widget* pWidget)
-    : CFFL_FormFiller(pApp, pWidget) {
+    : CFFL_TextObject(pApp, pWidget) {
   m_State.nIndex = 0;
   m_State.nStart = 0;
   m_State.nEnd = 0;
@@ -34,15 +33,11 @@
 }
 
 PWL_CREATEPARAM CFFL_ComboBox::GetCreateParam() {
-  PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
+  PWL_CREATEPARAM cp = CFFL_TextObject::GetCreateParam();
   if (m_pWidget->GetFieldFlags() & FIELDFLAG_EDIT)
     cp.dwFlags |= PCBS_ALLOWCUSTOMTEXT;
 
-  if (!m_pFontMap) {
-    m_pFontMap =
-        pdfium::MakeUnique<CBA_FontMap>(m_pWidget.Get(), GetSystemHandler());
-  }
-  cp.pFontMap = m_pFontMap.get();
+  cp.pFontMap = MaybeCreateFontMap();
   cp.pFocusHandler = this;
   return cp;
 }
@@ -75,7 +70,7 @@
 bool CFFL_ComboBox::OnChar(CPDFSDK_Annot* pAnnot,
                            uint32_t nChar,
                            uint32_t nFlags) {
-  return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+  return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
 }
 
 bool CFFL_ComboBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
@@ -225,20 +220,6 @@
   }
 }
 
-CPWL_Wnd* CFFL_ComboBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                                        bool bRestoreValue) {
-  if (bRestoreValue)
-    SaveState(pPageView);
-
-  DestroyPDFWindow(pPageView);
-  if (bRestoreValue)
-    RestoreState(pPageView);
-
-  CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue));
-  m_pWidget->UpdateField();  // May invoke JS, invalidating pRet.
-  return pRet.Get();
-}
-
 #ifdef PDF_ENABLE_XFA
 bool CFFL_ComboBox::IsFieldFull(CPDFSDK_PageView* pPageView) {
   if (CPWL_ComboBox* pComboBox =
diff --git a/fpdfsdk/formfiller/cffl_combobox.h b/fpdfsdk/formfiller/cffl_combobox.h
index 96e8ffd..0f510be 100644
--- a/fpdfsdk/formfiller/cffl_combobox.h
+++ b/fpdfsdk/formfiller/cffl_combobox.h
@@ -7,10 +7,8 @@
 #ifndef FPDFSDK_FORMFILLER_CFFL_COMBOBOX_H_
 #define FPDFSDK_FORMFILLER_CFFL_COMBOBOX_H_
 
-#include <memory>
-
 #include "core/fxcrt/fx_string.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
 
 class CBA_FontMap;
 
@@ -21,12 +19,12 @@
   CFX_WideString sValue;
 };
 
-class CFFL_ComboBox : public CFFL_FormFiller, public IPWL_FocusHandler {
+class CFFL_ComboBox : public CFFL_TextObject, public IPWL_FocusHandler {
  public:
   CFFL_ComboBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
   ~CFFL_ComboBox() override;
 
-  // CFFL_FormFiller:
+  // CFFL_TextObject:
   PWL_CREATEPARAM GetCreateParam() override;
   CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
@@ -43,21 +41,16 @@
                            const PDFSDK_FieldAction& faNew) override;
   void SaveState(CPDFSDK_PageView* pPageView) override;
   void RestoreState(CPDFSDK_PageView* pPageView) override;
-  CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                           bool bRestoreValue) override;
+#ifdef PDF_ENABLE_XFA
+  bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
+#endif
 
   // IPWL_FocusHandler:
   void OnSetFocus(CPWL_Edit* pEdit) override;
 
-#ifdef PDF_ENABLE_XFA
-  // CFFL_FormFiller:
-  bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
-#endif  // PDF_ENABLE_XFA
-
  private:
   CFX_WideString GetSelectExportText();
 
-  std::unique_ptr<CBA_FontMap> m_pFontMap;
   FFL_ComboBoxState m_State;
 };
 
diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp
index ca983d8..a5851b0 100644
--- a/fpdfsdk/formfiller/cffl_listbox.cpp
+++ b/fpdfsdk/formfiller/cffl_listbox.cpp
@@ -9,7 +9,6 @@
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/cpdfsdk_widget.h"
 #include "fpdfsdk/formfiller/cba_fontmap.h"
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
 #include "fpdfsdk/formfiller/cffl_interactiveformfiller.h"
 #include "fpdfsdk/fsdk_common.h"
 #include "fpdfsdk/pwl/cpwl_list_box.h"
@@ -19,12 +18,12 @@
 
 CFFL_ListBox::CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp,
                            CPDFSDK_Widget* pWidget)
-    : CFFL_FormFiller(pApp, pWidget) {}
+    : CFFL_TextObject(pApp, pWidget) {}
 
 CFFL_ListBox::~CFFL_ListBox() {}
 
 PWL_CREATEPARAM CFFL_ListBox::GetCreateParam() {
-  PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
+  PWL_CREATEPARAM cp = CFFL_TextObject::GetCreateParam();
   uint32_t dwFieldFlag = m_pWidget->GetFieldFlags();
   if (dwFieldFlag & FIELDFLAG_MULTISELECT)
     cp.dwFlags |= PLBS_MULTIPLESEL;
@@ -34,11 +33,7 @@
   if (cp.dwFlags & PWS_AUTOFONTSIZE)
     cp.fFontSize = FFL_DEFAULTLISTBOXFONTSIZE;
 
-  if (!m_pFontMap) {
-    m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
-        m_pWidget.Get(), m_pFormFillEnv->GetSysHandler());
-  }
-  cp.pFontMap = m_pFontMap.get();
+  cp.pFontMap = MaybeCreateFontMap();
   return cp;
 }
 
@@ -82,7 +77,7 @@
 bool CFFL_ListBox::OnChar(CPDFSDK_Annot* pAnnot,
                           uint32_t nChar,
                           uint32_t nFlags) {
-  return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+  return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
 }
 
 bool CFFL_ListBox::IsDataChanged(CPDFSDK_PageView* pPageView) {
@@ -182,17 +177,3 @@
   for (const auto& item : m_State)
     pListBox->Select(item);
 }
-
-CPWL_Wnd* CFFL_ListBox::ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                                       bool bRestoreValue) {
-  if (bRestoreValue)
-    SaveState(pPageView);
-
-  DestroyPDFWindow(pPageView);
-  if (bRestoreValue)
-    RestoreState(pPageView);
-
-  CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue));
-  m_pWidget->UpdateField();  // May invoke JS, invalidating pRet.
-  return pRet.Get();
-}
diff --git a/fpdfsdk/formfiller/cffl_listbox.h b/fpdfsdk/formfiller/cffl_listbox.h
index 7c2713c..fc06e14 100644
--- a/fpdfsdk/formfiller/cffl_listbox.h
+++ b/fpdfsdk/formfiller/cffl_listbox.h
@@ -7,20 +7,19 @@
 #ifndef FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_
 #define FPDFSDK_FORMFILLER_CFFL_LISTBOX_H_
 
-#include <memory>
 #include <set>
 #include <vector>
 
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
 
 class CBA_FontMap;
 
-class CFFL_ListBox : public CFFL_FormFiller {
+class CFFL_ListBox : public CFFL_TextObject {
  public:
   CFFL_ListBox(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
   ~CFFL_ListBox() override;
 
-  // CFFL_FormFiller
+  // CFFL_TextObject:
   PWL_CREATEPARAM GetCreateParam() override;
   CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
@@ -31,11 +30,8 @@
                      PDFSDK_FieldAction& fa) override;
   void SaveState(CPDFSDK_PageView* pPageView) override;
   void RestoreState(CPDFSDK_PageView* pPageView) override;
-  CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                           bool bRestoreValue) override;
 
  private:
-  std::unique_ptr<CBA_FontMap> m_pFontMap;
   std::set<int> m_OriginSelections;
   std::vector<int> m_State;
 };
diff --git a/fpdfsdk/formfiller/cffl_textfield.cpp b/fpdfsdk/formfiller/cffl_textfield.cpp
index 0f330b5..d26b4a5 100644
--- a/fpdfsdk/formfiller/cffl_textfield.cpp
+++ b/fpdfsdk/formfiller/cffl_textfield.cpp
@@ -14,7 +14,7 @@
 
 CFFL_TextField::CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp,
                                CPDFSDK_Widget* pWidget)
-    : CFFL_FormFiller(pApp, pWidget) {}
+    : CFFL_TextObject(pApp, pWidget) {}
 
 CFFL_TextField::~CFFL_TextField() {
   for (const auto& it : m_Maps)
@@ -27,7 +27,7 @@
 }
 
 PWL_CREATEPARAM CFFL_TextField::GetCreateParam() {
-  PWL_CREATEPARAM cp = CFFL_FormFiller::GetCreateParam();
+  PWL_CREATEPARAM cp = CFFL_TextObject::GetCreateParam();
   int nFlags = m_pWidget->GetFieldFlags();
   if (nFlags & FIELDFLAG_PASSWORD)
     cp.dwFlags |= PES_PASSWORD;
@@ -62,11 +62,7 @@
       cp.dwFlags |= PES_RIGHT;
       break;
   }
-  if (!m_pFontMap) {
-    m_pFontMap = pdfium::MakeUnique<CBA_FontMap>(
-        m_pWidget.Get(), m_pFormFillEnv->GetSysHandler());
-  }
-  cp.pFontMap = m_pFontMap.get();
+  cp.pFontMap = MaybeCreateFontMap();
   cp.pFocusHandler = this;
   return cp;
 }
@@ -127,7 +123,7 @@
     }
   }
 
-  return CFFL_FormFiller::OnChar(pAnnot, nChar, nFlags);
+  return CFFL_TextObject::OnChar(pAnnot, nChar, nFlags);
 }
 
 bool CFFL_TextField::IsDataChanged(CPDFSDK_PageView* pPageView) {
@@ -232,20 +228,6 @@
   pWnd->SetSelection(m_State.nStart, m_State.nEnd);
 }
 
-CPWL_Wnd* CFFL_TextField::ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                                         bool bRestoreValue) {
-  if (bRestoreValue)
-    SaveState(pPageView);
-
-  DestroyPDFWindow(pPageView);
-  if (bRestoreValue)
-    RestoreState(pPageView);
-
-  CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue));
-  m_pWidget->UpdateField();  // May invoke JS, invalidating pRet.
-  return pRet.Get();
-}
-
 #ifdef PDF_ENABLE_XFA
 bool CFFL_TextField::IsFieldFull(CPDFSDK_PageView* pPageView) {
   CPWL_Edit* pWnd = GetEdit(pPageView, false);
diff --git a/fpdfsdk/formfiller/cffl_textfield.h b/fpdfsdk/formfiller/cffl_textfield.h
index 91771a1..4297998 100644
--- a/fpdfsdk/formfiller/cffl_textfield.h
+++ b/fpdfsdk/formfiller/cffl_textfield.h
@@ -7,9 +7,7 @@
 #ifndef FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_
 #define FPDFSDK_FORMFILLER_CFFL_TEXTFIELD_H_
 
-#include <memory>
-
-#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/formfiller/cffl_textobject.h"
 
 #define BF_ALIGN_LEFT 0
 #define BF_ALIGN_MIDDLE 1
@@ -26,12 +24,12 @@
   CFX_WideString sValue;
 };
 
-class CFFL_TextField : public CFFL_FormFiller, public IPWL_FocusHandler {
+class CFFL_TextField : public CFFL_TextObject, public IPWL_FocusHandler {
  public:
   CFFL_TextField(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
   ~CFFL_TextField() override;
 
-  // CFFL_FormFiller:
+  // CFFL_TextObject:
   PWL_CREATEPARAM GetCreateParam() override;
   CPWL_Wnd* NewPDFWindow(const PWL_CREATEPARAM& cp) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
@@ -48,21 +46,16 @@
                            const PDFSDK_FieldAction& faNew) override;
   void SaveState(CPDFSDK_PageView* pPageView) override;
   void RestoreState(CPDFSDK_PageView* pPageView) override;
-  CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
-                           bool bRestoreValue) override;
+#ifdef PDF_ENABLE_XFA
+  bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
+#endif
 
   // IPWL_FocusHandler:
   void OnSetFocus(CPWL_Edit* pEdit) override;
 
-#ifdef PDF_ENABLE_XFA
-  // CFFL_FormFiller:
-  bool IsFieldFull(CPDFSDK_PageView* pPageView) override;
-#endif  // PDF_ENABLE_XFA
-
  private:
   CPWL_Edit* GetEdit(CPDFSDK_PageView* pPageView, bool bNew);
 
-  std::unique_ptr<CBA_FontMap> m_pFontMap;
   FFL_TextFieldState m_State;
 };
 
diff --git a/fpdfsdk/formfiller/cffl_textobject.cpp b/fpdfsdk/formfiller/cffl_textobject.cpp
new file mode 100644
index 0000000..d84557e
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_textobject.cpp
@@ -0,0 +1,35 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "fpdfsdk/formfiller/cffl_textobject.h"
+
+CPWL_Wnd* CFFL_TextObject::ResetPDFWindow(CPDFSDK_PageView* pPageView,
+                                          bool bRestoreValue) {
+  if (bRestoreValue)
+    SaveState(pPageView);
+
+  DestroyPDFWindow(pPageView);
+  if (bRestoreValue)
+    RestoreState(pPageView);
+
+  CPWL_Wnd::ObservedPtr pRet(GetPDFWindow(pPageView, !bRestoreValue));
+  m_pWidget->UpdateField();  // May invoke JS, invalidating |pRet|.
+  return pRet.Get();
+}
+
+CFFL_TextObject::CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp,
+                                 CPDFSDK_Widget* pWidget)
+    : CFFL_FormFiller(pApp, pWidget) {}
+
+CFFL_TextObject::~CFFL_TextObject() {}
+
+CBA_FontMap* CFFL_TextObject::MaybeCreateFontMap() {
+  if (!m_pFontMap) {
+    m_pFontMap =
+        pdfium::MakeUnique<CBA_FontMap>(m_pWidget.Get(), GetSystemHandler());
+  }
+  return m_pFontMap.get();
+}
diff --git a/fpdfsdk/formfiller/cffl_textobject.h b/fpdfsdk/formfiller/cffl_textobject.h
new file mode 100644
index 0000000..fcb3c1b
--- /dev/null
+++ b/fpdfsdk/formfiller/cffl_textobject.h
@@ -0,0 +1,32 @@
+// Copyright 2017 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 FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_
+#define FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_
+
+#include <memory>
+
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+
+// Class to implement common functionality for CFFL_FormFiller sub-classes with
+// text fields.
+class CFFL_TextObject : public CFFL_FormFiller {
+ public:
+  // CFFL_FormFiller:
+  CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
+                           bool bRestoreValue) override;
+
+ protected:
+  CFFL_TextObject(CPDFSDK_FormFillEnvironment* pApp, CPDFSDK_Widget* pWidget);
+  ~CFFL_TextObject() override;
+
+  CBA_FontMap* MaybeCreateFontMap();
+
+ private:
+  std::unique_ptr<CBA_FontMap> m_pFontMap;
+};
+
+#endif  // FPDFSDK_FORMFILLER_CFFL_TEXTOBJECT_H_