summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn1
-rw-r--r--fpdfsdk/cpdfsdk_xfawidgethandler.cpp18
-rw-r--r--xfa/fwl/cfwl_edit.cpp39
-rw-r--r--xfa/fwl/cfwl_edit.h2
-rw-r--r--xfa/fwl/cfwl_edit_embeddertest.cpp67
-rw-r--r--xfa/fxfa/cxfa_fftextedit.cpp67
-rw-r--r--xfa/fxfa/cxfa_fftextedit.h16
-rw-r--r--xfa/fxfa/cxfa_ffwidgethandler.cpp17
-rw-r--r--xfa/fxfa/cxfa_ffwidgethandler.h3
9 files changed, 204 insertions, 26 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 9c8d221552..2cf6552f21 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2051,6 +2051,7 @@ test("pdfium_embeddertests") {
sources += [
"testing/xfa_js_embedder_test.cpp",
"testing/xfa_js_embedder_test.h",
+ "xfa/fwl/cfwl_edit_embeddertest.cpp",
"xfa/fxfa/fm2js/cxfa_fm2jscontext_embeddertest.cpp",
"xfa/fxfa/parser/cxfa_simple_parser_embeddertest.cpp",
]
diff --git a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
index b5c52a89cc..c1ef2bdb23 100644
--- a/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
+++ b/fpdfsdk/cpdfsdk_xfawidgethandler.cpp
@@ -97,16 +97,22 @@ CFX_FloatRect CPDFSDK_XFAWidgetHandler::GetViewBBox(CPDFSDK_PageView* pPageView,
return rcWidget;
}
-// TODO(bug 840): Implement so selected text can be obtained from XFA
-// fields.
WideString CPDFSDK_XFAWidgetHandler::GetSelectedText(CPDFSDK_Annot* pAnnot) {
- return WideString();
+ if (!pAnnot)
+ return WideString();
+
+ CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot);
+ return pWidgetHandler->GetSelectedText(pAnnot->GetXFAWidget());
}
-// TODO(bug 840): Implement so text can be inserted into and deleted from XFA
-// fields.
void CPDFSDK_XFAWidgetHandler::ReplaceSelection(CPDFSDK_Annot* pAnnot,
- const WideString& text) {}
+ const WideString& text) {
+ if (!pAnnot)
+ return;
+
+ CXFA_FFWidgetHandler* pWidgetHandler = GetXFAWidgetHandler(pAnnot);
+ return pWidgetHandler->PasteText(pAnnot->GetXFAWidget(), text);
+}
bool CPDFSDK_XFAWidgetHandler::HitTest(CPDFSDK_PageView* pPageView,
CPDFSDK_Annot* pAnnot,
diff --git a/xfa/fwl/cfwl_edit.cpp b/xfa/fwl/cfwl_edit.cpp
index 426d46e761..d1f0c99a39 100644
--- a/xfa/fwl/cfwl_edit.cpp
+++ b/xfa/fwl/cfwl_edit.cpp
@@ -1120,7 +1120,7 @@ void CFWL_Edit::OnProcessMessage(CFWL_Message* pMessage) {
OnMouseMove(pMsg);
break;
case FWL_MouseCommand::RightButtonDown:
- DoButtonDown(pMsg);
+ DoRButtonDown(pMsg);
break;
default:
break;
@@ -1159,17 +1159,11 @@ void CFWL_Edit::OnDrawWidget(CXFA_Graphics* pGraphics,
DrawWidget(pGraphics, matrix);
}
-void CFWL_Edit::DoButtonDown(CFWL_MessageMouse* pMsg) {
+void CFWL_Edit::DoRButtonDown(CFWL_MessageMouse* pMsg) {
if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
SetFocus(true);
- // TODO(dsinclair): Handle DoButtonDown
- // bool bBefore = true;
- // int32_t nIndex =
- // std::max(0, pPage->GetCharIndex(DeviceToEngine(pMsg->m_pos),
- // bBefore));
-
- // SetCursorPosition(nIndex);
+ m_CursorPosition = m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos));
}
void CFWL_Edit::OnFocusChanged(CFWL_Message* pMsg, bool bSet) {
@@ -1206,7 +1200,9 @@ void CFWL_Edit::OnLButtonDown(CFWL_MessageMouse* pMsg) {
m_bLButtonDown = true;
SetGrab(true);
- DoButtonDown(pMsg);
+
+ if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)
+ SetFocus(true);
bool bRepaint = false;
if (m_EdtEngine.HasSelection()) {
@@ -1216,13 +1212,16 @@ void CFWL_Edit::OnLButtonDown(CFWL_MessageMouse* pMsg) {
size_t index_at_click =
m_EdtEngine.GetIndexForPoint(DeviceToEngine(pMsg->m_pos));
+
if (index_at_click != m_CursorPosition &&
!!(pMsg->m_dwFlags & FWL_KEYFLAG_Shift)) {
size_t start = std::min(m_CursorPosition, index_at_click);
size_t end = std::max(m_CursorPosition, index_at_click);
- m_EdtEngine.SetSelection(start, end);
+ m_EdtEngine.SetSelection(start, end - start);
bRepaint = true;
+ } else {
+ m_CursorPosition = index_at_click;
}
if (bRepaint)
@@ -1259,14 +1258,16 @@ void CFWL_Edit::OnMouseMove(CFWL_MessageMouse* pMsg) {
if (m_CursorPosition > length)
SetCursorPosition(length);
- size_t sel_start;
- size_t count;
- std::tie(sel_start, count) = m_EdtEngine.GetSelection();
- size_t original_end = sel_start + count;
- sel_start = std::min(sel_start, m_CursorPosition);
- m_EdtEngine.SetSelection(
- std::min(sel_start, m_CursorPosition),
- std::max(original_end, m_CursorPosition) - sel_start);
+ size_t sel_start = 0;
+ size_t count = 0;
+ if (m_EdtEngine.HasSelection())
+ std::tie(sel_start, count) = m_EdtEngine.GetSelection();
+ else
+ sel_start = old_cursor_pos;
+
+ size_t start_pos = std::min(sel_start, m_CursorPosition);
+ size_t end_pos = std::max(sel_start, m_CursorPosition);
+ m_EdtEngine.SetSelection(start_pos, end_pos - start_pos);
}
void CFWL_Edit::OnKeyDown(CFWL_MessageKey* pMsg) {
diff --git a/xfa/fwl/cfwl_edit.h b/xfa/fwl/cfwl_edit.h
index cfebb25146..b7c252668b 100644
--- a/xfa/fwl/cfwl_edit.h
+++ b/xfa/fwl/cfwl_edit.h
@@ -142,7 +142,7 @@ class CFWL_Edit : public CFWL_Widget, public CFDE_TextEditEngine::Delegate {
void SetCursorPosition(size_t position);
void UpdateCursorRect();
- void DoButtonDown(CFWL_MessageMouse* pMsg);
+ void DoRButtonDown(CFWL_MessageMouse* pMsg);
void OnFocusChanged(CFWL_Message* pMsg, bool bSet);
void OnLButtonDown(CFWL_MessageMouse* pMsg);
void OnLButtonUp(CFWL_MessageMouse* pMsg);
diff --git a/xfa/fwl/cfwl_edit_embeddertest.cpp b/xfa/fwl/cfwl_edit_embeddertest.cpp
new file mode 100644
index 0000000000..c1575689eb
--- /dev/null
+++ b/xfa/fwl/cfwl_edit_embeddertest.cpp
@@ -0,0 +1,67 @@
+// 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.
+
+#include "core/fxcrt/widestring.h"
+#include "public/fpdf_formfill.h"
+#include "public/fpdf_fwlevent.h"
+#include "testing/embedder_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CFWLEditEmbeddertest : public EmbedderTest {
+ protected:
+ void SetUp() override {
+ EmbedderTest::SetUp();
+ CreateAndInitializeFormPDF();
+ }
+
+ void TearDown() override {
+ UnloadPage(page());
+ EmbedderTest::TearDown();
+ }
+
+ void CreateAndInitializeFormPDF() {
+ EXPECT_TRUE(OpenDocument("xfa/email_recommended.pdf"));
+ page_ = LoadPage(0);
+ ASSERT_TRUE(page_);
+ }
+
+ FPDF_PAGE page() const { return page_; }
+
+ private:
+ FPDF_PAGE page_;
+};
+
+TEST_F(CFWLEditEmbeddertest, LeftClickMouseSelection) {
+ FORM_OnLButtonDown(form_handle(), page(), 0, 115, 58);
+ for (size_t i = 0; i < 10; ++i)
+ FORM_OnChar(form_handle(), page(), 'a' + i, 0);
+
+ // Mouse selection
+ FORM_OnLButtonDown(form_handle(), page(), 0, 128, 58);
+ FORM_OnLButtonDown(form_handle(), page(), FWL_EVENTFLAG_ShiftKey, 152, 58);
+
+ // 12 == (2 * strlen(defgh)) + 2 (for \0\0)
+ EXPECT_EQ(12UL, FORM_GetSelectedText(form_handle(), page(), nullptr, 0));
+
+ unsigned short buf[128];
+ unsigned long len = FORM_GetSelectedText(form_handle(), page(), &buf, 128);
+ EXPECT_STREQ(L"defgh", WideString::FromUTF16LE(buf, len).c_str());
+}
+
+TEST_F(CFWLEditEmbeddertest, DragMouseSelection) {
+ FORM_OnLButtonDown(form_handle(), page(), 0, 115, 58);
+ for (size_t i = 0; i < 10; ++i)
+ FORM_OnChar(form_handle(), page(), 'a' + i, 0);
+
+ // Mouse selection
+ FORM_OnLButtonDown(form_handle(), page(), 0, 128, 58);
+ FORM_OnMouseMove(form_handle(), page(), FWL_EVENTFLAG_ShiftKey, 152, 58);
+
+ // 12 == (2 * strlen(defgh)) + 2 (for \0\0)
+ EXPECT_EQ(12UL, FORM_GetSelectedText(form_handle(), page(), nullptr, 0));
+
+ unsigned short buf[128];
+ unsigned long len = FORM_GetSelectedText(form_handle(), page(), &buf, 128);
+ EXPECT_STREQ(L"defgh", WideString::FromUTF16LE(buf, len).c_str());
+}
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index 82b6f63b59..8f68368757 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -20,6 +20,14 @@
#include "xfa/fxfa/cxfa_ffapp.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+namespace {
+
+CFWL_Edit* ToEdit(CFWL_Widget* widget) {
+ return static_cast<CFWL_Edit*>(widget);
+}
+
+} // namespace
+
CXFA_FFTextEdit::CXFA_FFTextEdit(CXFA_WidgetAcc* pDataAcc)
: CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {}
@@ -356,3 +364,62 @@ void CXFA_FFTextEdit::OnDrawWidget(CXFA_Graphics* pGraphics,
const CFX_Matrix& matrix) {
m_pOldDelegate->OnDrawWidget(pGraphics, matrix);
}
+
+bool CXFA_FFTextEdit::CanUndo() {
+ return ToEdit(m_pNormalWidget.get())->CanUndo();
+}
+
+bool CXFA_FFTextEdit::CanRedo() {
+ return ToEdit(m_pNormalWidget.get())->CanRedo();
+}
+
+bool CXFA_FFTextEdit::Undo() {
+ return ToEdit(m_pNormalWidget.get())->Undo();
+}
+
+bool CXFA_FFTextEdit::Redo() {
+ return ToEdit(m_pNormalWidget.get())->Redo();
+}
+
+bool CXFA_FFTextEdit::CanCopy() {
+ return ToEdit(m_pNormalWidget.get())->HasSelection();
+}
+
+bool CXFA_FFTextEdit::CanCut() {
+ if (ToEdit(m_pNormalWidget.get())->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly)
+ return false;
+ return ToEdit(m_pNormalWidget.get())->HasSelection();
+}
+
+bool CXFA_FFTextEdit::CanPaste() {
+ return !(ToEdit(m_pNormalWidget.get())->GetStylesEx() &
+ FWL_STYLEEXT_EDT_ReadOnly);
+}
+
+bool CXFA_FFTextEdit::CanSelectAll() {
+ return ToEdit(m_pNormalWidget.get())->GetTextLength() > 0;
+}
+
+bool CXFA_FFTextEdit::Copy(WideString& wsCopy) {
+ return ToEdit(m_pNormalWidget.get())->Copy(wsCopy);
+}
+
+bool CXFA_FFTextEdit::Cut(WideString& wsCut) {
+ return ToEdit(m_pNormalWidget.get())->Copy(wsCut);
+}
+
+bool CXFA_FFTextEdit::Paste(const WideString& wsPaste) {
+ return ToEdit(m_pNormalWidget.get())->Paste(wsPaste);
+}
+
+void CXFA_FFTextEdit::SelectAll() {
+ ToEdit(m_pNormalWidget.get())->SelectAll();
+}
+
+void CXFA_FFTextEdit::Delete() {
+ ToEdit(m_pNormalWidget.get())->ClearText();
+}
+
+void CXFA_FFTextEdit::DeSelect() {
+ ToEdit(m_pNormalWidget.get())->ClearSelection();
+}
diff --git a/xfa/fxfa/cxfa_fftextedit.h b/xfa/fxfa/cxfa_fftextedit.h
index 9735b9e7d8..dd3801b4df 100644
--- a/xfa/fxfa/cxfa_fftextedit.h
+++ b/xfa/fxfa/cxfa_fftextedit.h
@@ -42,6 +42,22 @@ class CXFA_FFTextEdit : public CXFA_FFField {
void OnTextFull(CFWL_Widget* pWidget);
bool CheckWord(const ByteStringView& sWord);
+ // CXFA_FFWidget
+ bool CanUndo() override;
+ bool CanRedo() override;
+ bool Undo() override;
+ bool Redo() override;
+ bool CanCopy() override;
+ bool CanCut() override;
+ bool CanPaste() override;
+ bool CanSelectAll() override;
+ bool Copy(WideString& wsCopy) override;
+ bool Cut(WideString& wsCut) override;
+ bool Paste(const WideString& wsPaste) override;
+ void SelectAll() override;
+ void Delete() override;
+ void DeSelect() override;
+
protected:
uint32_t GetAlignment();
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp
index 524bbed9e2..8f916d804b 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.cpp
+++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp
@@ -142,6 +142,23 @@ bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget,
return bRet;
}
+WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) {
+ if (!widget->CanCopy())
+ return WideString();
+
+ WideString val;
+ widget->Copy(val);
+ return val;
+}
+
+void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget,
+ const WideString& text) {
+ if (!widget->CanPaste())
+ return;
+
+ widget->Paste(text);
+}
+
FWL_WidgetHit CXFA_FFWidgetHandler::OnHitTest(CXFA_FFWidget* hWidget,
const CFX_PointF& point) {
if (!(hWidget->GetStatus() & XFA_WidgetStatus_Visible))
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.h b/xfa/fxfa/cxfa_ffwidgethandler.h
index 474412069e..e2b50dc27c 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.h
+++ b/xfa/fxfa/cxfa_ffwidgethandler.h
@@ -53,6 +53,9 @@ class CXFA_FFWidgetHandler {
uint32_t dwFlags,
const CFX_PointF& point);
+ WideString GetSelectedText(CXFA_FFWidget* widget);
+ void PasteText(CXFA_FFWidget* widget, const WideString& text);
+
bool OnKeyDown(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags);
bool OnKeyUp(CXFA_FFWidget* hWidget, uint32_t dwKeyCode, uint32_t dwFlags);
bool OnChar(CXFA_FFWidget* hWidget, uint32_t dwChar, uint32_t dwFlags);