Implement FORM_GetFocusedText() API.

If there is a focused form field, get its text.

BUG=chromium:753216

Change-Id: I05294f14d05c1c86769055f6c9eaf9177787d9fd
Reviewed-on: https://pdfium-review.googlesource.com/12072
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.cpp b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
index e0405e8..52ab4dd 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.cpp
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.cpp
@@ -76,6 +76,10 @@
   GetAnnotHandler(pAnnot)->OnLoad(pAnnot);
 }
 
+WideString CPDFSDK_AnnotHandlerMgr::Annot_GetText(CPDFSDK_Annot* pAnnot) {
+  return GetAnnotHandler(pAnnot)->GetText(pAnnot);
+}
+
 WideString CPDFSDK_AnnotHandlerMgr::Annot_GetSelectedText(
     CPDFSDK_Annot* pAnnot) {
   return GetAnnotHandler(pAnnot)->GetSelectedText(pAnnot);
diff --git a/fpdfsdk/cpdfsdk_annothandlermgr.h b/fpdfsdk/cpdfsdk_annothandlermgr.h
index df4e1a2..7ea7a0e 100644
--- a/fpdfsdk/cpdfsdk_annothandlermgr.h
+++ b/fpdfsdk/cpdfsdk_annothandlermgr.h
@@ -42,6 +42,7 @@
   void Annot_OnCreate(CPDFSDK_Annot* pAnnot);
   void Annot_OnLoad(CPDFSDK_Annot* pAnnot);
 
+  WideString Annot_GetText(CPDFSDK_Annot* pAnnot);
   WideString Annot_GetSelectedText(CPDFSDK_Annot* pAnnot);
   void Annot_ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
 
diff --git a/fpdfsdk/cpdfsdk_baannothandler.cpp b/fpdfsdk/cpdfsdk_baannothandler.cpp
index 027527e..24643eb 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.cpp
+++ b/fpdfsdk/cpdfsdk_baannothandler.cpp
@@ -193,6 +193,10 @@
   return pAnnot->GetRect();
 }
 
+WideString CPDFSDK_BAAnnotHandler::GetText(CPDFSDK_Annot* pAnnot) {
+  return WideString();
+}
+
 WideString CPDFSDK_BAAnnotHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
   return WideString();
 }
diff --git a/fpdfsdk/cpdfsdk_baannothandler.h b/fpdfsdk/cpdfsdk_baannothandler.h
index 7bf8034..2a03402 100644
--- a/fpdfsdk/cpdfsdk_baannothandler.h
+++ b/fpdfsdk/cpdfsdk_baannothandler.h
@@ -36,6 +36,7 @@
   void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
   CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
                             CPDFSDK_Annot* pAnnot) override;
+  WideString GetText(CPDFSDK_Annot* pAnnot) override;
   WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
   void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
   bool HitTest(CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index c1b5221..b7f8cdf 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -240,6 +240,16 @@
 }
 #endif  // PDF_ENABLE_XFA
 
+WideString CPDFSDK_PageView::GetFocusedFormText() {
+  if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
+    CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
+        m_pFormFillEnv->GetAnnotHandlerMgr();
+    return pAnnotHandlerMgr->Annot_GetText(pAnnot);
+  }
+
+  return WideString();
+}
+
 WideString CPDFSDK_PageView::GetSelectedText() {
   if (CPDFSDK_Annot* pAnnot = GetFocusAnnot()) {
     CPDFSDK_AnnotHandlerMgr* pAnnotHandlerMgr =
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index 03f3ab6..9f846cf 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -61,6 +61,7 @@
     return m_pFormFillEnv.Get();
   }
 
+  WideString GetFocusedFormText();
   WideString GetSelectedText();
   void ReplaceSelection(const WideString& text);
 
diff --git a/fpdfsdk/cpdfsdk_widgethandler.cpp b/fpdfsdk/cpdfsdk_widgethandler.cpp
index dcce7b6..6281058 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_widgethandler.cpp
@@ -281,10 +281,15 @@
   return CFX_FloatRect();
 }
 
+WideString CPDFSDK_WidgetHandler::GetText(CPDFSDK_Annot* pAnnot) {
+  if (!pAnnot->IsSignatureWidget() && m_pFormFiller)
+    return m_pFormFiller->GetText(pAnnot);
+  return WideString();
+}
+
 WideString CPDFSDK_WidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
   if (!pAnnot->IsSignatureWidget() && m_pFormFiller)
     return m_pFormFiller->GetSelectedText(pAnnot);
-
   return WideString();
 }
 
diff --git a/fpdfsdk/cpdfsdk_widgethandler.h b/fpdfsdk/cpdfsdk_widgethandler.h
index f8aa7de..fbf9d2e 100644
--- a/fpdfsdk/cpdfsdk_widgethandler.h
+++ b/fpdfsdk/cpdfsdk_widgethandler.h
@@ -37,6 +37,7 @@
   void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
   CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
                             CPDFSDK_Annot* pAnnot) override;
+  WideString GetText(CPDFSDK_Annot* pAnnot) override;
   WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
   void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
   bool HitTest(CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
index e39f8ce..261c27c 100644
--- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
@@ -100,6 +100,14 @@
   return rcWidget;
 }
 
+WideString CPDFSDK_XFAWidgetHandler::GetText(CPDFSDK_Annot* pAnnot) {
+  if (!pAnnot)
+    return WideString();
+
+  CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot);
+  return pWidgetHandler->GetText(pAnnot->GetXFAWidget());
+}
+
 WideString CPDFSDK_XFAWidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
   if (!pAnnot)
     return WideString();
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.h b/fpdfsdk/cpdfsdk_xfawidgethandler.h
index e0dccbe..dbdb99b 100644
--- a/fpdfsdk/cpdfsdk_xfawidgethandler.h
+++ b/fpdfsdk/cpdfsdk_xfawidgethandler.h
@@ -32,6 +32,7 @@
   void ReleaseAnnot(CPDFSDK_Annot* pAnnot) override;
   CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
                             CPDFSDK_Annot* pAnnot) override;
+  WideString GetText(CPDFSDK_Annot* pAnnot) override;
   WideString GetSelectedText(CPDFSDK_Annot* pAnnot) override;
   void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text) override;
   bool HitTest(CPDFSDK_PageView* pPageView,
diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp
index dcbe018..32bbcb7 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_formfiller.cpp
@@ -219,6 +219,17 @@
   return pWnd && pWnd->OnChar(nChar, nFlags);
 }
 
+WideString CFFL_FormFiller::GetText(CPDFSDK_Annot* pAnnot) {
+  if (!IsValid())
+    return WideString();
+
+  CPDFSDK_PageView* pPageView = GetCurPageView(true);
+  ASSERT(pPageView);
+
+  CPWL_Wnd* pWnd = GetPDFWindow(pPageView, false);
+  return pWnd ? pWnd->GetText() : WideString();
+}
+
 WideString CFFL_FormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) {
   if (!IsValid())
     return WideString();
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index 0dfb0bb..a9d90ab 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -75,6 +75,7 @@
                          uint32_t nFlags);
   virtual bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags);
 
+  WideString GetText(CPDFSDK_Annot* pAnnot);
   WideString GetSelectedText(CPDFSDK_Annot* pAnnot);
   void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
 
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
index 83b4257..5972d1d 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
@@ -511,6 +511,12 @@
   return pFormFiller;
 }
 
+WideString CFFL_InteractiveFormFiller::GetText(CPDFSDK_Annot* pAnnot) {
+  ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
+  CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
+  return pFormFiller ? pFormFiller->GetText(pAnnot) : WideString();
+}
+
 WideString CFFL_InteractiveFormFiller::GetSelectedText(CPDFSDK_Annot* pAnnot) {
   ASSERT(pAnnot->GetPDFAnnot()->GetSubtype() == CPDF_Annot::Subtype::WIDGET);
   CFFL_FormFiller* pFormFiller = GetFormFiller(pAnnot, false);
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
index 94ca59d..bb0d223 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
@@ -82,6 +82,7 @@
 
   CFFL_FormFiller* GetFormFiller(CPDFSDK_Annot* pAnnot, bool bRegister);
 
+  WideString GetText(CPDFSDK_Annot* pAnnot);
   WideString GetSelectedText(CPDFSDK_Annot* pAnnot);
   void ReplaceSelection(CPDFSDK_Annot* pAnnot, const WideString& text);
 
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp
index 912db87..7676463 100644
--- a/fpdfsdk/fpdf_formfill.cpp
+++ b/fpdfsdk/fpdf_formfill.cpp
@@ -427,6 +427,19 @@
 }
 
 FPDF_EXPORT unsigned long FPDF_CALLCONV
+FORM_GetFocusedText(FPDF_FORMHANDLE hHandle,
+                    FPDF_PAGE page,
+                    void* buffer,
+                    unsigned long buflen) {
+  CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
+  if (!pPageView)
+    return 0;
+
+  return Utf16EncodeMaybeCopyAndReturnLength(pPageView->GetFocusedFormText(),
+                                             buffer, buflen);
+}
+
+FPDF_EXPORT unsigned long FPDF_CALLCONV
 FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,
                      FPDF_PAGE page,
                      void* buffer,
@@ -435,14 +448,8 @@
   if (!pPageView)
     return 0;
 
-  WideString wide_str_form_text = pPageView->GetSelectedText();
-  ByteString encoded_form_text = wide_str_form_text.UTF16LE_Encode();
-  unsigned long form_text_len = encoded_form_text.GetLength();
-
-  if (buffer && buflen >= form_text_len)
-    memcpy(buffer, encoded_form_text.c_str(), form_text_len);
-
-  return form_text_len;
+  return Utf16EncodeMaybeCopyAndReturnLength(pPageView->GetSelectedText(),
+                                             buffer, buflen);
 }
 
 FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index 99a51fd..5dd4d1e 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -107,20 +107,30 @@
   }
 
   void CheckSelection(const WideStringView& expected_string) {
-    // Calculate expected length for selected text.
-    int num_chars = expected_string.GetLength();
-
-    // Check actual selection against expected selection.
-    const unsigned long expected_length =
-        sizeof(unsigned short) * (num_chars + 1);
-    unsigned long sel_text_len =
+    unsigned long actual_len =
         FORM_GetSelectedText(form_handle(), page_, nullptr, 0);
-    ASSERT_EQ(expected_length, sel_text_len);
+    ASSERT_NE(actual_len, 0U);
+    ASSERT_LT(actual_len, 1000U);
 
-    std::vector<unsigned short> buf(sel_text_len);
-    EXPECT_EQ(expected_length, FORM_GetSelectedText(form_handle(), page_,
-                                                    buf.data(), sel_text_len));
+    std::vector<unsigned short> buf(actual_len);
+    ASSERT_EQ(actual_len, FORM_GetSelectedText(form_handle(), page_, buf.data(),
+                                               actual_len));
 
+    int num_chars = (actual_len / sizeof(unsigned short)) - 1;
+    EXPECT_EQ(expected_string, WideString::FromUTF16LE(buf.data(), num_chars));
+  }
+
+  void CheckFocusedFieldText(const WideStringView& expected_string) {
+    unsigned long actual_len =
+        FORM_GetFocusedText(form_handle(), page_, nullptr, 0);
+    ASSERT_NE(actual_len, 0U);
+    ASSERT_LT(actual_len, 1000U);
+
+    std::vector<unsigned short> buf(actual_len);
+    ASSERT_EQ(actual_len, FORM_GetFocusedText(form_handle(), page_, buf.data(),
+                                              actual_len));
+
+    int num_chars = (actual_len / sizeof(unsigned short)) - 1;
     EXPECT_EQ(expected_string, WideString::FromUTF16LE(buf.data(), num_chars));
   }
 
@@ -589,26 +599,31 @@
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicKeyboard) {
   // Test empty selection.
+  CheckFocusedFieldText(L"");
   CheckSelection(L"");
 
   // Test basic selection.
   TypeTextIntoTextField(3, RegularFormBegin());
+  CheckFocusedFieldText(L"ABC");
   SelectTextWithKeyboard(3, FWL_VKEY_Left, RegularFormAtX(123.0));
   CheckSelection(L"ABC");
 }
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextEmptyAndBasicMouse) {
   // Test empty selection.
+  CheckFocusedFieldText(L"");
   CheckSelection(L"");
 
   // Test basic selection.
   TypeTextIntoTextField(3, RegularFormBegin());
+  CheckFocusedFieldText(L"ABC");
   SelectTextWithMouse(RegularFormAtX(125.0), RegularFormBegin());
   CheckSelection(L"ABC");
 }
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsKeyBoard) {
   TypeTextIntoTextField(12, RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDEFGHIJKL");
 
   // Test selecting first character in forward direction.
   SelectTextWithKeyboard(1, FWL_VKEY_Right, RegularFormBegin());
@@ -629,6 +644,7 @@
   // Test selecting last character in backwards direction.
   SelectTextWithKeyboard(1, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"L");
+  CheckFocusedFieldText(L"ABCDEFGHIJKL");
 }
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, GetSelectedTextFragmentsMouse) {
@@ -659,13 +675,16 @@
        GetSelectedTextEmptyAndBasicNormalComboBox) {
   // Test empty selection.
   CheckSelection(L"");
+  CheckFocusedFieldText(L"");
 
   // Non-editable comboboxes don't allow selection with keyboard.
   SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(142.0));
+  CheckFocusedFieldText(L"Banana");
   CheckSelection(L"Banana");
 
   // Select other another provided option.
   SelectNonEditableFormOption(0);
+  CheckFocusedFieldText(L"Apple");
   CheckSelection(L"Apple");
 }
 
@@ -673,15 +692,18 @@
        GetSelectedTextEmptyAndBasicEditableComboBoxKeyboard) {
   // Test empty selection.
   CheckSelection(L"");
+  CheckFocusedFieldText(L"");
 
   // Test basic selection of text within user editable combobox using keyboard.
   TypeTextIntoTextField(3, EditableFormBegin());
+  CheckFocusedFieldText(L"ABC");
   SelectTextWithKeyboard(3, FWL_VKEY_Left, EditableFormAtX(128.0));
   CheckSelection(L"ABC");
 
   // Select a provided option.
   SelectEditableFormOption(1);
   CheckSelection(L"Bar");
+  CheckFocusedFieldText(L"Bar");
 }
 
 TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
@@ -696,13 +718,17 @@
 
   // Select a provided option.
   SelectEditableFormOption(2);
+  CheckFocusedFieldText(L"Qux");
   CheckSelection(L"Qux");
 }
 
 TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
        GetSelectedTextFragmentsNormalComboBox) {
+  CheckFocusedFieldText(L"");
+
   // Test selecting first character in forward direction.
   SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(107.0));
+  CheckFocusedFieldText(L"Banana");
   CheckSelection(L"B");
 
   // Test selecting entire string in backwards direction.
@@ -720,9 +746,11 @@
   // Test selecting last character in backwards direction.
   SelectTextWithMouse(NonEditableFormAtX(142.0), NonEditableFormAtX(138.0));
   CheckSelection(L"a");
+  CheckFocusedFieldText(L"Banana");
 
   // Select another option and then reset selection as first three chars.
   SelectNonEditableFormOption(2);
+  CheckFocusedFieldText(L"Cherry");
   CheckSelection(L"Cherry");
   SelectTextWithMouse(NonEditableFormBegin(), NonEditableFormAtX(122.0));
   CheckSelection(L"Che");
@@ -730,7 +758,9 @@
 
 TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
        GetSelectedTextFragmentsEditableComboBoxKeyboard) {
+  CheckFocusedFieldText(L"");
   TypeTextIntoTextField(10, EditableFormBegin());
+  CheckFocusedFieldText(L"ABCDEFGHIJ");
 
   // Test selecting first character in forward direction.
   SelectTextWithKeyboard(1, FWL_VKEY_Right, EditableFormBegin());
@@ -757,6 +787,7 @@
   CheckSelection(L"Foo");
   SelectTextWithKeyboard(2, FWL_VKEY_Right, EditableFormBegin());
   CheckSelection(L"Fo");
+  CheckFocusedFieldText(L"Foo");
 }
 
 TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
@@ -782,17 +813,20 @@
   // Test selecting last character in backwards direction.
   SelectTextWithMouse(EditableFormEnd(), EditableFormAtX(174.0));
   CheckSelection(L"J");
+  CheckFocusedFieldText(L"ABCDEFGHIJ");
 }
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, DeleteTextFieldEntireSelection) {
   // Select entire contents of text field.
   TypeTextIntoTextField(12, RegularFormBegin());
   SelectAllRegularFormTextWithMouse();
+  CheckFocusedFieldText(L"ABCDEFGHIJKL");
   CheckSelection(L"ABCDEFGHIJKL");
 
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"");
 
   SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"");
@@ -802,11 +836,13 @@
   // Select middle section of text.
   TypeTextIntoTextField(12, RegularFormBegin());
   SelectTextWithMouse(RegularFormAtX(170.0), RegularFormAtX(125.0));
+  CheckFocusedFieldText(L"ABCDEFGHIJKL");
   CheckSelection(L"DEFGHI");
 
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"ABCJKL");
   SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"ABCJKL");
 }
@@ -820,6 +856,7 @@
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"EFGHIJKL");
   SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"EFGHIJKL");
 }
@@ -833,6 +870,7 @@
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"ABCDEFGH");
   SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"ABCDEFGH");
 }
@@ -844,6 +882,7 @@
 
   // Test that attempt to delete empty text selection has no effect.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"ABCDEFGHIJKL");
   SelectTextWithKeyboard(12, FWL_VKEY_Left, RegularFormEnd());
   CheckSelection(L"ABCDEFGHIJKL");
 }
@@ -858,6 +897,7 @@
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"");
   SelectAllEditableFormTextWithMouse();
   CheckSelection(L"");
 }
@@ -872,6 +912,7 @@
   // Test deleting current text selection. Select what remains after deletion to
   // check that remaining text is as expected.
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"ABCIJ");
   SelectAllEditableFormTextWithMouse();
   CheckSelection(L"ABCIJ");
 }
@@ -917,12 +958,15 @@
 }
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInEmptyTextField) {
+  CheckFocusedFieldText(L"");
   ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"");
 
   // Test inserting text into empty text field.
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Hello");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -932,14 +976,17 @@
 
 TEST_F(FPDFFormFillTextFormEmbeddertest, InsertTextInPopulatedTextFieldLeft) {
   TypeTextIntoTextField(8, RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDEFGH");
 
   // Click on the leftmost part of the text field.
   ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDEFGH");
 
   // Test inserting text in front of existing text in text field.
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"HelloABCDEFGH");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -957,6 +1004,7 @@
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"ABCDHelloEFGH");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -974,6 +1022,7 @@
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"ABCDEFGHHello");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -993,6 +1042,7 @@
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Hello");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -1012,6 +1062,7 @@
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"HelloGHIJKL");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -1060,11 +1111,13 @@
 TEST_F(FPDFFormFillComboBoxFormEmbeddertest,
        InsertTextInEmptyEditableComboBox) {
   ClickOnFormFieldAtPoint(EditableFormBegin());
+  CheckFocusedFieldText(L"");
 
   // Test inserting text into empty user-editable combobox.
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hello");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Hello");
 
   // Select entire contents of user-editable combobox text field to check that
   // insertion worked as expected.
@@ -1206,18 +1259,22 @@
 TEST_F(FPDFFormFillTextFormEmbeddertest,
        InsertTextInEmptyCharLimitTextFieldOverflow) {
   // Click on the textfield.
+  CheckFocusedFieldText(L"");
   ClickOnFormFieldAtPoint(CharLimitFormEnd());
+  CheckFocusedFieldText(L"Elephant");
 
   // Delete pre-filled contents of text field with char limit.
   SelectAllCharLimitFormTextWithMouse();
   CheckSelection(L"Elephant");
   FORM_ReplaceSelection(form_handle(), page(), nullptr);
+  CheckFocusedFieldText(L"");
 
   // Test inserting text into now empty text field so text to be inserted
   // exceeds the char limit and is cut off.
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hippopotamus");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Hippopotam");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -1229,6 +1286,7 @@
        InsertTextInEmptyCharLimitTextFieldFit) {
   // Click on the textfield.
   ClickOnFormFieldAtPoint(CharLimitFormEnd());
+  CheckFocusedFieldText(L"Elephant");
 
   // Delete pre-filled contents of text field with char limit.
   SelectAllCharLimitFormTextWithMouse();
@@ -1240,6 +1298,7 @@
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Zebra");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"Zebra");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -1265,15 +1324,19 @@
 
 TEST_F(FPDFFormFillTextFormEmbeddertest,
        InsertTextInPopulatedCharLimitTextFieldMiddle) {
+  CheckFocusedFieldText(L"");
   TypeTextIntoTextField(8, RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDEFGH");
 
   // Click on the middle of the text field.
   ClickOnFormFieldAtPoint(CharLimitFormAtX(134.0));
+  CheckFocusedFieldText(L"Elephant");
 
   // Test inserting text in the middle of existing text in text field.
   std::unique_ptr<unsigned short, pdfium::FreeDeleter> text_to_insert =
       GetFPDFWideString(L"Hippopotamus");
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+  CheckFocusedFieldText(L"ElephHiant");
 
   // Select entire contents of text field to check that insertion worked
   // as expected.
@@ -1374,3 +1437,110 @@
   SelectAllCharLimitFormTextWithMouse();
   CheckSelection(L"ElepHippop");
 }
+
+TEST_F(FPDFFormFillTextFormEmbeddertest, FocusChanges) {
+  static const CFX_PointF kNonFormPoint(1, 1);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(CharLimitFormEnd());
+  CheckFocusedFieldText(L"Elephant");
+  ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"");
+  TypeTextIntoTextField(3, CharLimitFormBegin());
+  CheckFocusedFieldText(L"ABElephant");
+  TypeTextIntoTextField(5, RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDE");
+  ClickOnFormFieldAtPoint(CharLimitFormEnd());
+  CheckFocusedFieldText(L"ABElephant");
+  ClickOnFormFieldAtPoint(kNonFormPoint);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(kNonFormPoint);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(CharLimitFormBegin());
+  CheckFocusedFieldText(L"ABElephant");
+  ClickOnFormFieldAtPoint(CharLimitFormEnd());
+  CheckFocusedFieldText(L"ABElephant");
+  ClickOnFormFieldAtPoint(RegularFormEnd());
+  CheckFocusedFieldText(L"ABCDE");
+  ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDE");
+  ClickOnFormFieldAtPoint(RegularFormBegin());
+  CheckFocusedFieldText(L"ABCDE");
+  ClickOnFormFieldAtPoint(CharLimitFormBegin());
+  CheckFocusedFieldText(L"ABElephant");
+  FORM_ForceToKillFocus(form_handle());
+  CheckFocusedFieldText(L"");
+}
+
+TEST_F(FPDFFormFillComboBoxFormEmbeddertest, FocusChanges) {
+  static const CFX_PointF kNonFormPoint(1, 1);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(NonEditableFormBegin());
+  CheckFocusedFieldText(L"Banana");
+  ClickOnFormFieldAtPoint(EditableFormBegin());
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(NonEditableFormEnd());
+  CheckFocusedFieldText(L"Banana");
+  ClickOnFormFieldAtPoint(NonEditableFormBegin());
+  CheckFocusedFieldText(L"Banana");
+  FORM_ForceToKillFocus(form_handle());
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(EditableFormBegin());
+  CheckFocusedFieldText(L"");
+  TypeTextIntoTextField(3, EditableFormBegin());
+  CheckFocusedFieldText(L"ABC");
+  ClickOnFormFieldAtPoint(kNonFormPoint);
+  CheckFocusedFieldText(L"");
+  TypeTextIntoTextField(3, EditableFormEnd());
+  CheckFocusedFieldText(L"ABCABC");
+  ClickOnFormFieldAtPoint(kNonFormPoint);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(EditableFormDropDown());
+  CheckFocusedFieldText(L"ABCABC");
+  FORM_ForceToKillFocus(form_handle());
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(NonEditableFormDropDown());
+  CheckFocusedFieldText(L"Banana");
+  ClickOnFormFieldAtPoint(kNonFormPoint);
+  CheckFocusedFieldText(L"");
+  ClickOnFormFieldAtPoint(NonEditableFormEnd());
+  CheckFocusedFieldText(L"Banana");
+
+  // Typing into non-editable field results in selecting a different option.
+  TypeTextIntoTextField(1, NonEditableFormEnd());
+  CheckFocusedFieldText(L"Apple");
+  TypeTextIntoTextField(3, NonEditableFormEnd());
+  CheckFocusedFieldText(L"Cherry");
+  TypeTextIntoTextField(2, NonEditableFormEnd());
+  CheckFocusedFieldText(L"Banana");
+
+  SelectEditableFormOption(0);
+  CheckFocusedFieldText(L"Foo");
+  SelectEditableFormOption(1);
+  CheckFocusedFieldText(L"Bar");
+  SelectEditableFormOption(2);
+  CheckFocusedFieldText(L"Qux");
+  SelectNonEditableFormOption(1);
+  CheckFocusedFieldText(L"Banana");
+  SelectNonEditableFormOption(0);
+  CheckFocusedFieldText(L"Apple");
+  SelectNonEditableFormOption(2);
+  CheckFocusedFieldText(L"Cherry");
+
+  // Typing into an editable field changes the text in the option.
+  SelectEditableFormOption(0);
+  CheckFocusedFieldText(L"Foo");
+  TypeTextIntoTextField(5, EditableFormBegin());
+  CheckFocusedFieldText(L"ABCDEFoo");
+  SelectEditableFormOption(2);
+  CheckFocusedFieldText(L"Qux");
+  TypeTextIntoTextField(2, EditableFormEnd());
+  CheckFocusedFieldText(L"QuxAB");
+
+  // But a previously edited option is reset when selected again.
+  SelectEditableFormOption(0);
+  CheckFocusedFieldText(L"Foo");
+  TypeTextIntoTextField(1, EditableFormBegin());
+  CheckFocusedFieldText(L"AFoo");
+  SelectEditableFormOption(0);
+  CheckFocusedFieldText(L"Foo");
+}
diff --git a/fpdfsdk/fpdf_view_c_api_test.c b/fpdfsdk/fpdf_view_c_api_test.c
index fbfa71c..114693c 100644
--- a/fpdfsdk/fpdf_view_c_api_test.c
+++ b/fpdfsdk/fpdf_view_c_api_test.c
@@ -213,6 +213,7 @@
     CHK(FORM_OnKeyDown);
     CHK(FORM_OnKeyUp);
     CHK(FORM_OnChar);
+    CHK(FORM_GetFocusedText);
     CHK(FORM_GetSelectedText);
     CHK(FORM_ReplaceSelection);
     CHK(FORM_ForceToKillFocus);
diff --git a/fpdfsdk/ipdfsdk_annothandler.h b/fpdfsdk/ipdfsdk_annothandler.h
index bffeac6..91fd5ce 100644
--- a/fpdfsdk/ipdfsdk_annothandler.h
+++ b/fpdfsdk/ipdfsdk_annothandler.h
@@ -35,6 +35,7 @@
   virtual void ReleaseAnnot(CPDFSDK_Annot* pAnnot) = 0;
   virtual CFX_FloatRect GetViewBBox(CPDFSDK_PageView* pPageView,
                                     CPDFSDK_Annot* pAnnot) = 0;
+  virtual WideString GetText(CPDFSDK_Annot* pAnnot) = 0;
   virtual WideString GetSelectedText(CPDFSDK_Annot* pAnnot) = 0;
   virtual void ReplaceSelection(CPDFSDK_Annot* pAnnot,
                                 const WideString& text) = 0;