diff options
Diffstat (limited to 'fpdfsdk/fpdf_formfill.cpp')
-rw-r--r-- | fpdfsdk/fpdf_formfill.cpp | 836 |
1 files changed, 836 insertions, 0 deletions
diff --git a/fpdfsdk/fpdf_formfill.cpp b/fpdfsdk/fpdf_formfill.cpp new file mode 100644 index 0000000000..ddd460da05 --- /dev/null +++ b/fpdfsdk/fpdf_formfill.cpp @@ -0,0 +1,836 @@ +// 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 "public/fpdf_formfill.h" + +#include <memory> +#include <vector> + +#include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/render/cpdf_renderoptions.h" +#include "core/fpdfdoc/cpdf_formcontrol.h" +#include "core/fpdfdoc/cpdf_formfield.h" +#include "core/fpdfdoc/cpdf_interform.h" +#include "core/fpdfdoc/cpdf_occontext.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "fpdfsdk/cpdfsdk_actionhandler.h" +#include "fpdfsdk/cpdfsdk_formfillenvironment.h" +#include "fpdfsdk/cpdfsdk_helpers.h" +#include "fpdfsdk/cpdfsdk_interform.h" +#include "fpdfsdk/cpdfsdk_pageview.h" +#include "public/fpdfview.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +#ifdef PDF_ENABLE_XFA +#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" +#include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" +#include "xfa/fxfa/cxfa_ffdocview.h" +#include "xfa/fxfa/cxfa_ffpageview.h" +#include "xfa/fxfa/cxfa_ffwidget.h" + +static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE, + "None form types must match"); +static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM, + "AcroForm form types must match"); +static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL, + "XFA full form types must match"); +static_assert(static_cast<int>(FormType::kXFAForeground) == + FORMTYPE_XFA_FOREGROUND, + "XFA foreground form types must match"); +#endif // PDF_ENABLE_XFA + +static_assert(static_cast<int>(FormFieldType::kUnknown) == + FPDF_FORMFIELD_UNKNOWN, + "Unknown form field types must match"); +static_assert(static_cast<int>(FormFieldType::kPushButton) == + FPDF_FORMFIELD_PUSHBUTTON, + "PushButton form field types must match"); +static_assert(static_cast<int>(FormFieldType::kCheckBox) == + FPDF_FORMFIELD_CHECKBOX, + "CheckBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kRadioButton) == + FPDF_FORMFIELD_RADIOBUTTON, + "RadioButton form field types must match"); +static_assert(static_cast<int>(FormFieldType::kComboBox) == + FPDF_FORMFIELD_COMBOBOX, + "ComboBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kListBox) == + FPDF_FORMFIELD_LISTBOX, + "ListBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kTextField) == + FPDF_FORMFIELD_TEXTFIELD, + "TextField form field types must match"); +static_assert(static_cast<int>(FormFieldType::kSignature) == + FPDF_FORMFIELD_SIGNATURE, + "Signature form field types must match"); +#ifdef PDF_ENABLE_XFA +static_assert(static_cast<int>(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA, + "XFA form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_CheckBox) == + FPDF_FORMFIELD_XFA_CHECKBOX, + "XFA CheckBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_ComboBox) == + FPDF_FORMFIELD_XFA_COMBOBOX, + "XFA ComboBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_ImageField) == + FPDF_FORMFIELD_XFA_IMAGEFIELD, + "XFA ImageField form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_ListBox) == + FPDF_FORMFIELD_XFA_LISTBOX, + "XFA ListBox form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_PushButton) == + FPDF_FORMFIELD_XFA_PUSHBUTTON, + "XFA PushButton form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_Signature) == + FPDF_FORMFIELD_XFA_SIGNATURE, + "XFA Signature form field types must match"); +static_assert(static_cast<int>(FormFieldType::kXFA_TextField) == + FPDF_FORMFIELD_XFA_TEXTFIELD, + "XFA TextField form field types must match"); +#endif // PDF_ENABLE_XFA +static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT, + "Number of form field types must match"); + +namespace { + +CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment( + FPDF_FORMHANDLE handle) { + return static_cast<CPDFSDK_FormFillEnvironment*>(handle); +} + +CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + return pFormFillEnv ? pFormFillEnv->GetInterForm() : nullptr; +} + +CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page) { + UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); + if (!pPage) + return nullptr; + + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + return pFormFillEnv ? pFormFillEnv->GetPageView(pPage, true) : nullptr; +} + +#ifdef PDF_ENABLE_XFA +std::vector<ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) { + return static_cast<std::vector<ByteString>*>(handle); +} + +FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<ByteString>* strings) { + return static_cast<FPDF_STRINGHANDLE>(strings); +} +#endif // PDF_ENABLE_XFA + +void FFLCommon(FPDF_FORMHANDLE hHandle, + FPDF_BITMAP bitmap, + FPDF_RECORDER recorder, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { + if (!hHandle) + return; + + UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); + if (!pPage) + return; + +#ifdef PDF_ENABLE_XFA + CPDFXFA_Context* pContext = pPage->GetContext(); + if (!pContext) + return; + CPDF_Document* pPDFDoc = pContext->GetPDFDoc(); + if (!pPDFDoc) + return; + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; +#endif // PDF_ENABLE_XFA + + CFX_Matrix matrix = + pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate); + FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y); + + auto pDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>(); +#ifdef _SKIA_SUPPORT_ + pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder)); +#endif + RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap)); + pDevice->Attach(holder, false, nullptr, false); + { + CFX_RenderDevice::StateRestorer restorer(pDevice.get()); + pDevice->SetClip_Rect(clip); + + CPDF_RenderOptions options; + uint32_t option_flags = options.GetFlags(); + if (flags & FPDF_LCD_TEXT) + option_flags |= RENDER_CLEARTYPE; + else + option_flags &= ~RENDER_CLEARTYPE; + options.SetFlags(option_flags); + + // Grayscale output + if (flags & FPDF_GRAYSCALE) + options.SetColorMode(CPDF_RenderOptions::kGray); + + options.SetDrawAnnots(flags & FPDF_ANNOT); + +#ifdef PDF_ENABLE_XFA + options.SetOCContext( + pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View)); + if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true)) + pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip); +#else // PDF_ENABLE_XFA + options.SetOCContext(pdfium::MakeRetain<CPDF_OCContext>( + pPage->m_pDocument.Get(), CPDF_OCContext::View)); + if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage)) + pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options); +#endif // PDF_ENABLE_XFA + } +#ifdef _SKIA_SUPPORT_PATHS_ + pDevice->Flush(true); + holder->UnPreMultiply(); +#endif +} + +} // namespace + +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { + if (!hHandle) + return -1; + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (pPage) { + CPDF_InterForm interform(pPage->m_pDocument.Get()); + CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint( + pPage, + CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)), + nullptr); + if (!pFormCtrl) + return -1; + CPDF_FormField* pFormField = pFormCtrl->GetField(); + return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1; + } + +#ifdef PDF_ENABLE_XFA + CPDFXFA_Page* pXFAPage = UnderlyingFromFPDFPage(page); + if (!pXFAPage) + return -1; + + CXFA_FFPageView* pPageView = pXFAPage->GetXFAPageView(); + if (!pPageView) + return -1; + + CXFA_FFDocView* pDocView = pPageView->GetDocView(); + if (!pDocView) + return -1; + + CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler(); + if (!pWidgetHandler) + return -1; + + std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator( + pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form, + XFA_WidgetStatus_Viewable)); + if (!pWidgetIterator) + return -1; + + CXFA_FFWidget* pXFAAnnot; + while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) { + if (pXFAAnnot->GetFormFieldType() == FormFieldType::kXFA) + continue; + + CFX_RectF rcBBox = pXFAAnnot->GetWidgetRect(); + CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width, + rcBBox.top + rcBBox.height); + rcWidget.Inflate(1.0f, 1.0f); + if (rcWidget.Contains(CFX_PointF(static_cast<float>(page_x), + static_cast<float>(page_y)))) { + return static_cast<int>(pXFAAnnot->GetFormFieldType()); + } + } +#endif // PDF_ENABLE_XFA + return -1; +} + +FPDF_EXPORT int FPDF_CALLCONV +FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + double page_x, + double page_y) { + if (!hHandle) + return -1; + CPDF_Page* pPage = CPDFPageFromFPDFPage(page); + if (!pPage) + return -1; + CPDF_InterForm interform(pPage->m_pDocument.Get()); + int z_order = -1; + (void)interform.GetControlAtPoint( + pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)), + &z_order); + return z_order; +} + +FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV +FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, + FPDF_FORMFILLINFO* formInfo) { +#ifdef PDF_ENABLE_XFA + const int kRequiredVersion = 2; +#else // PDF_ENABLE_XFA + const int kRequiredVersion = 1; +#endif // PDF_ENABLE_XFA + if (!formInfo || formInfo->version != kRequiredVersion) + return nullptr; + + UnderlyingDocumentType* pDocument = UnderlyingFromFPDFDocument(document); + if (!pDocument) + return nullptr; + +#ifdef PDF_ENABLE_XFA + // If the CPDFXFA_Context has a FormFillEnvironment already then we've done + // this and can just return the old Env. Otherwise, we'll end up setting a new + // environment into the XFADocument and, that could get weird. + if (pDocument->GetFormFillEnv()) + return pDocument->GetFormFillEnv(); +#endif + + auto pFormFillEnv = + pdfium::MakeUnique<CPDFSDK_FormFillEnvironment>(pDocument, formInfo); + +#ifdef PDF_ENABLE_XFA + pDocument->SetFormFillEnv(pFormFillEnv.get()); +#endif // PDF_ENABLE_XFA + + return pFormFillEnv.release(); // Caller takes ownership. +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; + +#ifdef PDF_ENABLE_XFA + // Reset the focused annotations and remove the SDK document from the + // XFA document. + pFormFillEnv->ClearAllFocusedAnnots(); + // If the document was closed first, it's possible the XFA document + // is now a nullptr. + if (pFormFillEnv->GetXFAContext()) + pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr); +#endif // PDF_ENABLE_XFA + delete pFormFillEnv; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnFocus(CFX_PointF(page_x, page_y), modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier); +} + +#ifdef PDF_ENABLE_XFA +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int modifier, + double page_x, + double page_y) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnRButtonUp(CFX_PointF(page_x, page_y), modifier); +} +#endif // PDF_ENABLE_XFA + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnKeyDown(nKeyCode, modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nKeyCode, + int modifier) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnKeyUp(nKeyCode, modifier); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + int nChar, + int modifier) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return false; + return pPageView->OnChar(nChar, modifier); +} + +FPDF_EXPORT unsigned long FPDF_CALLCONV +FORM_GetSelectedText(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + void* buffer, + unsigned long buflen) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + 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; +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle, + FPDF_PAGE page, + FPDF_WIDESTRING wsText) { + CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page); + if (!pPageView) + return; + + size_t len = WideString::WStringLength(wsText); + WideString wide_str_text = WideString::FromUTF16LE(wsText, len); + + pPageView->ReplaceSelection(wide_str_text); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return false; + return pFormFillEnv->KillFocusAnnot(0); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, + FPDF_BITMAP bitmap, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { + FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y, + rotate, flags); +} + +#ifdef _SKIA_SUPPORT_ +FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle, + FPDF_RECORDER recorder, + FPDF_PAGE page, + int start_x, + int start_y, + int size_x, + int size_y, + int rotate, + int flags) { + FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y, + rotate, flags); +} +#endif + +#ifdef PDF_ENABLE_XFA +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + static_cast<CXFA_FFWidget*>(hWidget)->Undo(); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + static_cast<CXFA_FFWidget*>(hWidget)->Redo(); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + static_cast<CXFA_FFWidget*>(hWidget)->SelectAll(); +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + WideString wsCpText = + static_cast<CXFA_FFWidget*>(hWidget)->Copy().value_or(WideString()); + + ByteString bsCpText = wsCpText.UTF16LE_Encode(); + uint32_t len = bsCpText.GetLength() / sizeof(unsigned short); + if (!wsText) { + *size = len; + return; + } + + uint32_t real_size = len < *size ? len : *size; + if (real_size > 0) { + memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); + bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); + } + *size = real_size; +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD* size) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + WideString wsCpText = + static_cast<CXFA_FFWidget*>(hWidget)->Cut().value_or(WideString()); + + ByteString bsCpText = wsCpText.UTF16LE_Encode(); + uint32_t len = bsCpText.GetLength() / sizeof(unsigned short); + if (!wsText) { + *size = len; + return; + } + + uint32_t real_size = len < *size ? len : *size; + if (real_size > 0) { + memcpy((void*)wsText, + bsCpText.GetBuffer(real_size * sizeof(unsigned short)), + real_size * sizeof(unsigned short)); + bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short)); + } + *size = real_size; +} + +FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + FPDF_WIDESTRING wsText, + FPDF_DWORD size) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + WideString wstr = WideString::FromUTF16LE(wsText, size); + static_cast<CXFA_FFWidget*>(hWidget)->Paste(wstr); +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + float x, + float y, + FPDF_BYTESTRING bsText) { + if (!hWidget || !document) + return; + + CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + CFX_PointF ptPopup; + ptPopup.x = x; + ptPopup.y = y; + ByteStringView bs(bsText); + static_cast<CXFA_FFWidget*>(hWidget)->ReplaceSpellCheckWord(ptPopup, bs); +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document, + FPDF_WIDGET hWidget, + float x, + float y, + FPDF_STRINGHANDLE* stringHandle) { + if (!hWidget || !document) + return; + + auto* pContext = static_cast<CPDFXFA_Context*>(document); + if (!pContext->ContainsXFAForm()) + return; + + CFX_PointF ptPopup; + ptPopup.x = x; + ptPopup.y = y; + auto sSuggestWords = pdfium::MakeUnique<std::vector<ByteString>>(); + static_cast<CXFA_FFWidget*>(hWidget)->GetSuggestWords(ptPopup, + sSuggestWords.get()); + + // Caller takes ownership. + *stringHandle = ToFPDFStringHandle(sSuggestWords.release()); +} + +FPDF_EXPORT int FPDF_CALLCONV +FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) { + std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle); + return sSuggestWords ? pdfium::CollectionSize<int>(*sSuggestWords) : -1; +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle, + int index, + FPDF_BYTESTRING bsText, + FPDF_DWORD* size) { + if (!sHandle || !size) + return false; + + int count = FPDF_StringHandleCounts(sHandle); + if (index < 0 || index >= count) + return false; + + std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle); + uint32_t len = (*sSuggestWords)[index].GetLength(); + if (!bsText) { + *size = len; + return true; + } + + uint32_t real_size = len < *size ? len : *size; + if (real_size > 0) + memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size); + *size = real_size; + return true; +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) { + delete FromFPDFStringHandle(stringHandle); +} + +FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV +FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle, + FPDF_BYTESTRING bsText, + FPDF_DWORD size) { + if (!stringHandle || !bsText || size == 0) + return false; + + FromFPDFStringHandle(stringHandle)->push_back(ByteString(bsText, size)); + return true; +} +#endif // PDF_ENABLE_XFA + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, + int fieldType, + unsigned long color) { + CPDFSDK_InterForm* interForm = FormHandleToInterForm(hHandle); + if (!interForm) + return; + + Optional<FormFieldType> cast_input = IntToFormFieldType(fieldType); + if (!cast_input) + return; + + if (cast_input.value() == FormFieldType::kUnknown) { + interForm->SetAllHighlightColors(color); + } else { + interForm->SetHighlightColor(color, cast_input.value()); + } +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) { + if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle)) + pInterForm->SetHighlightAlpha(alpha); +} + +FPDF_EXPORT void FPDF_CALLCONV +FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) { + if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle)) + pInterForm->RemoveAllHighLights(); +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle) { + if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page)) + pPageView->SetValid(true); +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; + + UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); + if (!pPage) + return; + + CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, false); + if (pPageView) { + pPageView->SetValid(false); + // RemovePageView() takes care of the delete for us. + pFormFillEnv->RemovePageView(pPage); + } +} + +FPDF_EXPORT void FPDF_CALLCONV +FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (pFormFillEnv && pFormFillEnv->IsJSPlatformPresent()) + pFormFillEnv->ProcJavascriptFun(); +} + +FPDF_EXPORT void FPDF_CALLCONV +FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (pFormFillEnv && pFormFillEnv->IsJSPlatformPresent()) + pFormFillEnv->ProcOpenAction(); +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, + int aaType) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; + + CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument(); + const CPDF_Dictionary* pDict = pDoc->GetRoot(); + if (!pDict) + return; + + CPDF_AAction aa(pDict->GetDictFor("AA")); + auto type = static_cast<CPDF_AAction::AActionType>(aaType); + if (aa.ActionExist(type)) { + CPDF_Action action = aa.GetAction(type); + CPDFSDK_ActionHandler* pActionHandler = + HandleToCPDFSDKEnvironment(hHandle)->GetActionHandler(); + pActionHandler->DoAction_Document(action, type, pFormFillEnv); + } +} + +FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page, + FPDF_FORMHANDLE hHandle, + int aaType) { + CPDFSDK_FormFillEnvironment* pFormFillEnv = + HandleToCPDFSDKEnvironment(hHandle); + if (!pFormFillEnv) + return; + + UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page); + CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page); + if (!pPDFPage) + return; + + if (!pFormFillEnv->GetPageView(pPage, false)) + return; + + CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler(); + CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict.Get(); + CPDF_AAction aa(pPageDict->GetDictFor("AA")); + CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN + ? CPDF_AAction::OpenPage + : CPDF_AAction::ClosePage; + if (aa.ActionExist(type)) { + CPDF_Action action = aa.GetAction(type); + pActionHandler->DoAction_Page(action, type, pFormFillEnv); + } +} |