• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "public/fpdf_formfill.h"
8 
9 #include <memory>
10 #include <vector>
11 
12 #include "core/fpdfapi/page/cpdf_page.h"
13 #include "core/fpdfapi/parser/cpdf_document.h"
14 #include "core/fpdfapi/render/cpdf_renderoptions.h"
15 #include "core/fpdfdoc/cpdf_formcontrol.h"
16 #include "core/fpdfdoc/cpdf_formfield.h"
17 #include "core/fpdfdoc/cpdf_interform.h"
18 #include "core/fpdfdoc/cpdf_occontext.h"
19 #include "core/fxge/cfx_defaultrenderdevice.h"
20 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
21 #include "fpdfsdk/cpdfsdk_interform.h"
22 #include "fpdfsdk/cpdfsdk_pageview.h"
23 #include "fpdfsdk/fsdk_actionhandler.h"
24 #include "fpdfsdk/fsdk_define.h"
25 #include "public/fpdfview.h"
26 #include "third_party/base/ptr_util.h"
27 #include "third_party/base/stl_util.h"
28 
29 #ifdef PDF_ENABLE_XFA
30 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
31 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
32 #include "xfa/fxfa/cxfa_ffdocview.h"
33 #include "xfa/fxfa/cxfa_ffpageview.h"
34 #include "xfa/fxfa/cxfa_ffwidget.h"
35 
36 static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE,
37               "None form types must match");
38 static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM,
39               "AcroForm form types must match");
40 static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL,
41               "XFA full form types must match");
42 static_assert(static_cast<int>(FormType::kXFAForeground) ==
43                   FORMTYPE_XFA_FOREGROUND,
44               "XFA foreground form types must match");
45 #endif  // PDF_ENABLE_XFA
46 
47 static_assert(static_cast<int>(FormFieldType::kUnknown) ==
48                   FPDF_FORMFIELD_UNKNOWN,
49               "Unknown form field types must match");
50 static_assert(static_cast<int>(FormFieldType::kPushButton) ==
51                   FPDF_FORMFIELD_PUSHBUTTON,
52               "PushButton form field types must match");
53 static_assert(static_cast<int>(FormFieldType::kCheckBox) ==
54                   FPDF_FORMFIELD_CHECKBOX,
55               "CheckBox form field types must match");
56 static_assert(static_cast<int>(FormFieldType::kRadioButton) ==
57                   FPDF_FORMFIELD_RADIOBUTTON,
58               "RadioButton form field types must match");
59 static_assert(static_cast<int>(FormFieldType::kComboBox) ==
60                   FPDF_FORMFIELD_COMBOBOX,
61               "ComboBox form field types must match");
62 static_assert(static_cast<int>(FormFieldType::kListBox) ==
63                   FPDF_FORMFIELD_LISTBOX,
64               "ListBox form field types must match");
65 static_assert(static_cast<int>(FormFieldType::kTextField) ==
66                   FPDF_FORMFIELD_TEXTFIELD,
67               "TextField form field types must match");
68 static_assert(static_cast<int>(FormFieldType::kSignature) ==
69                   FPDF_FORMFIELD_SIGNATURE,
70               "Signature form field types must match");
71 #ifdef PDF_ENABLE_XFA
72 static_assert(static_cast<int>(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA,
73               "XFA form field types must match");
74 static_assert(static_cast<int>(FormFieldType::kXFA_CheckBox) ==
75                   FPDF_FORMFIELD_XFA_CHECKBOX,
76               "XFA CheckBox form field types must match");
77 static_assert(static_cast<int>(FormFieldType::kXFA_ComboBox) ==
78                   FPDF_FORMFIELD_XFA_COMBOBOX,
79               "XFA ComboBox form field types must match");
80 static_assert(static_cast<int>(FormFieldType::kXFA_ImageField) ==
81                   FPDF_FORMFIELD_XFA_IMAGEFIELD,
82               "XFA ImageField form field types must match");
83 static_assert(static_cast<int>(FormFieldType::kXFA_ListBox) ==
84                   FPDF_FORMFIELD_XFA_LISTBOX,
85               "XFA ListBox form field types must match");
86 static_assert(static_cast<int>(FormFieldType::kXFA_PushButton) ==
87                   FPDF_FORMFIELD_XFA_PUSHBUTTON,
88               "XFA PushButton form field types must match");
89 static_assert(static_cast<int>(FormFieldType::kXFA_Signature) ==
90                   FPDF_FORMFIELD_XFA_SIGNATURE,
91               "XFA Signature form field types must match");
92 static_assert(static_cast<int>(FormFieldType::kXFA_TextField) ==
93                   FPDF_FORMFIELD_XFA_TEXTFIELD,
94               "XFA TextField form field types must match");
95 #endif  // PDF_ENABLE_XFA
96 static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT,
97               "Number of form field types must match");
98 
99 namespace {
100 
HandleToCPDFSDKEnvironment(FPDF_FORMHANDLE handle)101 CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment(
102     FPDF_FORMHANDLE handle) {
103   return static_cast<CPDFSDK_FormFillEnvironment*>(handle);
104 }
105 
FormHandleToInterForm(FPDF_FORMHANDLE hHandle)106 CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) {
107   CPDFSDK_FormFillEnvironment* pFormFillEnv =
108       HandleToCPDFSDKEnvironment(hHandle);
109   return pFormFillEnv ? pFormFillEnv->GetInterForm() : nullptr;
110 }
111 
FormHandleToPageView(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)112 CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle,
113                                        FPDF_PAGE page) {
114   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
115   if (!pPage)
116     return nullptr;
117 
118   CPDFSDK_FormFillEnvironment* pFormFillEnv =
119       HandleToCPDFSDKEnvironment(hHandle);
120   return pFormFillEnv ? pFormFillEnv->GetPageView(pPage, true) : nullptr;
121 }
122 
123 #ifdef PDF_ENABLE_XFA
FromFPDFStringHandle(FPDF_STRINGHANDLE handle)124 std::vector<ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) {
125   return static_cast<std::vector<ByteString>*>(handle);
126 }
127 
ToFPDFStringHandle(std::vector<ByteString> * strings)128 FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<ByteString>* strings) {
129   return static_cast<FPDF_STRINGHANDLE>(strings);
130 }
131 #endif  // PDF_ENABLE_XFA
132 
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)133 void FFLCommon(FPDF_FORMHANDLE hHandle,
134                FPDF_BITMAP bitmap,
135                FPDF_RECORDER recorder,
136                FPDF_PAGE page,
137                int start_x,
138                int start_y,
139                int size_x,
140                int size_y,
141                int rotate,
142                int flags) {
143   if (!hHandle)
144     return;
145 
146   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
147   if (!pPage)
148     return;
149 
150 #ifdef PDF_ENABLE_XFA
151   CPDFXFA_Context* pContext = pPage->GetContext();
152   if (!pContext)
153     return;
154   CPDF_Document* pPDFDoc = pContext->GetPDFDoc();
155   if (!pPDFDoc)
156     return;
157   CPDFSDK_FormFillEnvironment* pFormFillEnv =
158       HandleToCPDFSDKEnvironment(hHandle);
159   if (!pFormFillEnv)
160     return;
161 #endif  // PDF_ENABLE_XFA
162 
163   CFX_Matrix matrix =
164       pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
165   FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y);
166 
167   auto pDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>();
168 #ifdef _SKIA_SUPPORT_
169   pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
170 #endif
171   RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap));
172   pDevice->Attach(holder, false, nullptr, false);
173   {
174     CFX_RenderDevice::StateRestorer restorer(pDevice.get());
175     pDevice->SetClip_Rect(clip);
176 
177     CPDF_RenderOptions options;
178     uint32_t option_flags = options.GetFlags();
179     if (flags & FPDF_LCD_TEXT)
180       option_flags |= RENDER_CLEARTYPE;
181     else
182       option_flags &= ~RENDER_CLEARTYPE;
183     options.SetFlags(option_flags);
184 
185     // Grayscale output
186     if (flags & FPDF_GRAYSCALE)
187       options.SetColorMode(CPDF_RenderOptions::kGray);
188 
189     options.SetDrawAnnots(flags & FPDF_ANNOT);
190 
191 #ifdef PDF_ENABLE_XFA
192     options.SetOCContext(
193         pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View));
194     if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true))
195       pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip);
196 #else   // PDF_ENABLE_XFA
197     options.SetOCContext(pdfium::MakeRetain<CPDF_OCContext>(
198         pPage->m_pDocument.Get(), CPDF_OCContext::View));
199     if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
200       pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
201 #endif  // PDF_ENABLE_XFA
202   }
203 #ifdef _SKIA_SUPPORT_PATHS_
204   pDevice->Flush(true);
205   holder->UnPreMultiply();
206 #endif
207 }
208 
209 }  // namespace
210 
211 FPDF_EXPORT int FPDF_CALLCONV
FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)212 FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
213                              FPDF_PAGE page,
214                              double page_x,
215                              double page_y) {
216   if (!hHandle)
217     return -1;
218   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
219   if (pPage) {
220     CPDF_InterForm interform(pPage->m_pDocument.Get());
221     CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
222         pPage,
223         CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
224         nullptr);
225     if (!pFormCtrl)
226       return -1;
227     CPDF_FormField* pFormField = pFormCtrl->GetField();
228     return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1;
229   }
230 
231 #ifdef PDF_ENABLE_XFA
232   CPDFXFA_Page* pXFAPage = UnderlyingFromFPDFPage(page);
233   if (!pXFAPage)
234     return -1;
235 
236   CXFA_FFPageView* pPageView = pXFAPage->GetXFAPageView();
237   if (!pPageView)
238     return -1;
239 
240   CXFA_FFDocView* pDocView = pPageView->GetDocView();
241   if (!pDocView)
242     return -1;
243 
244   CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
245   if (!pWidgetHandler)
246     return -1;
247 
248   std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
249       pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form,
250                                       XFA_WidgetStatus_Viewable));
251   if (!pWidgetIterator)
252     return -1;
253 
254   CXFA_FFWidget* pXFAAnnot;
255   while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) {
256     CFX_RectF rcBBox = pXFAAnnot->GetBBox(0);
257     CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
258                            rcBBox.top + rcBBox.height);
259     rcWidget.Inflate(1.0f, 1.0f);
260     if (rcWidget.Contains(CFX_PointF(static_cast<float>(page_x),
261                                      static_cast<float>(page_y)))) {
262       return static_cast<int>(pXFAAnnot->GetFormFieldType());
263     }
264   }
265 #endif  // PDF_ENABLE_XFA
266   return -1;
267 }
268 
269 FPDF_EXPORT int FPDF_CALLCONV
FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)270 FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
271                                 FPDF_PAGE page,
272                                 double page_x,
273                                 double page_y) {
274   if (!hHandle)
275     return -1;
276   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
277   if (!pPage)
278     return -1;
279   CPDF_InterForm interform(pPage->m_pDocument.Get());
280   int z_order = -1;
281   (void)interform.GetControlAtPoint(
282       pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
283       &z_order);
284   return z_order;
285 }
286 
287 FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV
FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,FPDF_FORMFILLINFO * formInfo)288 FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,
289                                 FPDF_FORMFILLINFO* formInfo) {
290 #ifdef PDF_ENABLE_XFA
291   const int kRequiredVersion = 2;
292 #else   // PDF_ENABLE_XFA
293   const int kRequiredVersion = 1;
294 #endif  // PDF_ENABLE_XFA
295   if (!formInfo || formInfo->version != kRequiredVersion)
296     return nullptr;
297 
298   UnderlyingDocumentType* pDocument = UnderlyingFromFPDFDocument(document);
299   if (!pDocument)
300     return nullptr;
301 
302 #ifdef PDF_ENABLE_XFA
303   // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
304   // this and can just return the old Env. Otherwise, we'll end up setting a new
305   // environment into the XFADocument and, that could get weird.
306   if (pDocument->GetFormFillEnv())
307     return pDocument->GetFormFillEnv();
308 #endif
309 
310   auto pFormFillEnv =
311       pdfium::MakeUnique<CPDFSDK_FormFillEnvironment>(pDocument, formInfo);
312 
313 #ifdef PDF_ENABLE_XFA
314   pDocument->SetFormFillEnv(pFormFillEnv.get());
315 #endif  // PDF_ENABLE_XFA
316 
317   return pFormFillEnv.release();  // Caller takes ownership.
318 }
319 
320 FPDF_EXPORT void FPDF_CALLCONV
FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle)321 FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) {
322   CPDFSDK_FormFillEnvironment* pFormFillEnv =
323       HandleToCPDFSDKEnvironment(hHandle);
324   if (!pFormFillEnv)
325     return;
326 
327 #ifdef PDF_ENABLE_XFA
328   // Reset the focused annotations and remove the SDK document from the
329   // XFA document.
330   pFormFillEnv->ClearAllFocusedAnnots();
331   // If the document was closed first, it's possible the XFA document
332   // is now a nullptr.
333   if (pFormFillEnv->GetXFAContext())
334     pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr);
335 #endif  // PDF_ENABLE_XFA
336   delete pFormFillEnv;
337 }
338 
FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)339 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
340                                                      FPDF_PAGE page,
341                                                      int modifier,
342                                                      double page_x,
343                                                      double page_y) {
344   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
345   if (!pPageView)
346     return false;
347   return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier);
348 }
349 
FORM_OnFocus(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)350 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle,
351                                                  FPDF_PAGE page,
352                                                  int modifier,
353                                                  double page_x,
354                                                  double page_y) {
355   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
356   if (!pPageView)
357     return false;
358   return pPageView->OnFocus(CFX_PointF(page_x, page_y), modifier);
359 }
360 
FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)361 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
362                                                        FPDF_PAGE page,
363                                                        int modifier,
364                                                        double page_x,
365                                                        double page_y) {
366   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
367   if (!pPageView)
368     return false;
369   return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier);
370 }
371 
FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)372 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
373                                                      FPDF_PAGE page,
374                                                      int modifier,
375                                                      double page_x,
376                                                      double page_y) {
377   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
378   if (!pPageView)
379     return false;
380   return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier);
381 }
382 
383 #ifdef PDF_ENABLE_XFA
FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)384 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
385                                                        FPDF_PAGE page,
386                                                        int modifier,
387                                                        double page_x,
388                                                        double page_y) {
389   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
390   if (!pPageView)
391     return false;
392   return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier);
393 }
394 
FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)395 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
396                                                      FPDF_PAGE page,
397                                                      int modifier,
398                                                      double page_x,
399                                                      double page_y) {
400   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
401   if (!pPageView)
402     return false;
403   return pPageView->OnRButtonUp(CFX_PointF(page_x, page_y), modifier);
404 }
405 #endif  // PDF_ENABLE_XFA
406 
FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)407 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
408                                                    FPDF_PAGE page,
409                                                    int nKeyCode,
410                                                    int modifier) {
411   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
412   if (!pPageView)
413     return false;
414   return pPageView->OnKeyDown(nKeyCode, modifier);
415 }
416 
FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)417 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
418                                                  FPDF_PAGE page,
419                                                  int nKeyCode,
420                                                  int modifier) {
421   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
422   if (!pPageView)
423     return false;
424   return pPageView->OnKeyUp(nKeyCode, modifier);
425 }
426 
FORM_OnChar(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nChar,int modifier)427 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle,
428                                                 FPDF_PAGE page,
429                                                 int nChar,
430                                                 int modifier) {
431   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
432   if (!pPageView)
433     return false;
434   return pPageView->OnChar(nChar, modifier);
435 }
436 
437 FPDF_EXPORT unsigned long FPDF_CALLCONV
FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,void * buffer,unsigned long buflen)438 FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,
439                      FPDF_PAGE page,
440                      void* buffer,
441                      unsigned long buflen) {
442   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
443   if (!pPageView)
444     return 0;
445 
446   WideString wide_str_form_text = pPageView->GetSelectedText();
447   ByteString encoded_form_text = wide_str_form_text.UTF16LE_Encode();
448   unsigned long form_text_len = encoded_form_text.GetLength();
449 
450   if (buffer && buflen >= form_text_len)
451     memcpy(buffer, encoded_form_text.c_str(), form_text_len);
452 
453   return form_text_len;
454 }
455 
FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,FPDF_WIDESTRING wsText)456 FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,
457                                                      FPDF_PAGE page,
458                                                      FPDF_WIDESTRING wsText) {
459   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
460   if (!pPageView)
461     return;
462 
463   size_t len = WideString::WStringLength(wsText);
464   WideString wide_str_text = WideString::FromUTF16LE(wsText, len);
465 
466   pPageView->ReplaceSelection(wide_str_text);
467 }
468 
469 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle)470 FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
471   CPDFSDK_FormFillEnvironment* pFormFillEnv =
472       HandleToCPDFSDKEnvironment(hHandle);
473   if (!pFormFillEnv)
474     return false;
475   return pFormFillEnv->KillFocusAnnot(0);
476 }
477 
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)478 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
479                                             FPDF_BITMAP bitmap,
480                                             FPDF_PAGE page,
481                                             int start_x,
482                                             int start_y,
483                                             int size_x,
484                                             int size_y,
485                                             int rotate,
486                                             int flags) {
487   FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y,
488             rotate, flags);
489 }
490 
491 #ifdef _SKIA_SUPPORT_
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)492 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
493                                               FPDF_RECORDER recorder,
494                                               FPDF_PAGE page,
495                                               int start_x,
496                                               int start_y,
497                                               int size_x,
498                                               int size_y,
499                                               int rotate,
500                                               int flags) {
501   FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y,
502             rotate, flags);
503 }
504 #endif
505 
506 #ifdef PDF_ENABLE_XFA
FPDF_Widget_Undo(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)507 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document,
508                                                 FPDF_WIDGET hWidget) {
509   if (!hWidget || !document)
510     return;
511 
512   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
513   if (!pContext->ContainsXFAForm())
514     return;
515 
516   static_cast<CXFA_FFWidget*>(hWidget)->Undo();
517 }
518 
FPDF_Widget_Redo(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)519 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document,
520                                                 FPDF_WIDGET hWidget) {
521   if (!hWidget || !document)
522     return;
523 
524   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
525   if (!pContext->ContainsXFAForm())
526     return;
527 
528   static_cast<CXFA_FFWidget*>(hWidget)->Redo();
529 }
530 
FPDF_Widget_SelectAll(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)531 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document,
532                                                      FPDF_WIDGET hWidget) {
533   if (!hWidget || !document)
534     return;
535 
536   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
537   if (!pContext->ContainsXFAForm())
538     return;
539 
540   static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
541 }
542 
FPDF_Widget_Copy(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD * size)543 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document,
544                                                 FPDF_WIDGET hWidget,
545                                                 FPDF_WIDESTRING wsText,
546                                                 FPDF_DWORD* size) {
547   if (!hWidget || !document)
548     return;
549 
550   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
551   if (!pContext->ContainsXFAForm())
552     return;
553 
554   WideString wsCpText =
555       static_cast<CXFA_FFWidget*>(hWidget)->Copy().value_or(WideString());
556 
557   ByteString bsCpText = wsCpText.UTF16LE_Encode();
558   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
559   if (!wsText) {
560     *size = len;
561     return;
562   }
563 
564   uint32_t real_size = len < *size ? len : *size;
565   if (real_size > 0) {
566     memcpy((void*)wsText,
567            bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
568            real_size * sizeof(unsigned short));
569     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
570   }
571   *size = real_size;
572 }
573 
FPDF_Widget_Cut(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD * size)574 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document,
575                                                FPDF_WIDGET hWidget,
576                                                FPDF_WIDESTRING wsText,
577                                                FPDF_DWORD* size) {
578   if (!hWidget || !document)
579     return;
580 
581   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
582   if (!pContext->ContainsXFAForm())
583     return;
584 
585   WideString wsCpText =
586       static_cast<CXFA_FFWidget*>(hWidget)->Cut().value_or(WideString());
587 
588   ByteString bsCpText = wsCpText.UTF16LE_Encode();
589   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
590   if (!wsText) {
591     *size = len;
592     return;
593   }
594 
595   uint32_t real_size = len < *size ? len : *size;
596   if (real_size > 0) {
597     memcpy((void*)wsText,
598            bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
599            real_size * sizeof(unsigned short));
600     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
601   }
602   *size = real_size;
603 }
604 
FPDF_Widget_Paste(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD size)605 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document,
606                                                  FPDF_WIDGET hWidget,
607                                                  FPDF_WIDESTRING wsText,
608                                                  FPDF_DWORD size) {
609   if (!hWidget || !document)
610     return;
611 
612   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
613   if (!pContext->ContainsXFAForm())
614     return;
615 
616   WideString wstr = WideString::FromUTF16LE(wsText, size);
617   static_cast<CXFA_FFWidget*>(hWidget)->Paste(wstr);
618 }
619 
620 FPDF_EXPORT void FPDF_CALLCONV
FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,float x,float y,FPDF_BYTESTRING bsText)621 FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,
622                                   FPDF_WIDGET hWidget,
623                                   float x,
624                                   float y,
625                                   FPDF_BYTESTRING bsText) {
626   if (!hWidget || !document)
627     return;
628 
629   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
630   if (!pContext->ContainsXFAForm())
631     return;
632 
633   CFX_PointF ptPopup;
634   ptPopup.x = x;
635   ptPopup.y = y;
636   ByteStringView bs(bsText);
637   static_cast<CXFA_FFWidget*>(hWidget)->ReplaceSpellCheckWord(ptPopup, bs);
638 }
639 
640 FPDF_EXPORT void FPDF_CALLCONV
FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,float x,float y,FPDF_STRINGHANDLE * stringHandle)641 FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,
642                                FPDF_WIDGET hWidget,
643                                float x,
644                                float y,
645                                FPDF_STRINGHANDLE* stringHandle) {
646   if (!hWidget || !document)
647     return;
648 
649   auto* pContext = static_cast<CPDFXFA_Context*>(document);
650   if (!pContext->ContainsXFAForm())
651     return;
652 
653   CFX_PointF ptPopup;
654   ptPopup.x = x;
655   ptPopup.y = y;
656   auto sSuggestWords = pdfium::MakeUnique<std::vector<ByteString>>();
657   static_cast<CXFA_FFWidget*>(hWidget)->GetSuggestWords(ptPopup,
658                                                         sSuggestWords.get());
659 
660   // Caller takes ownership.
661   *stringHandle = ToFPDFStringHandle(sSuggestWords.release());
662 }
663 
664 FPDF_EXPORT int FPDF_CALLCONV
FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle)665 FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) {
666   std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
667   return sSuggestWords ? pdfium::CollectionSize<int>(*sSuggestWords) : -1;
668 }
669 
670 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,int index,FPDF_BYTESTRING bsText,FPDF_DWORD * size)671 FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,
672                                   int index,
673                                   FPDF_BYTESTRING bsText,
674                                   FPDF_DWORD* size) {
675   if (!sHandle || !size)
676     return false;
677 
678   int count = FPDF_StringHandleCounts(sHandle);
679   if (index < 0 || index >= count)
680     return false;
681 
682   std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
683   uint32_t len = (*sSuggestWords)[index].GetLength();
684   if (!bsText) {
685     *size = len;
686     return true;
687   }
688 
689   uint32_t real_size = len < *size ? len : *size;
690   if (real_size > 0)
691     memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size);
692   *size = real_size;
693   return true;
694 }
695 
696 FPDF_EXPORT void FPDF_CALLCONV
FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle)697 FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) {
698   delete FromFPDFStringHandle(stringHandle);
699 }
700 
701 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,FPDF_BYTESTRING bsText,FPDF_DWORD size)702 FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,
703                            FPDF_BYTESTRING bsText,
704                            FPDF_DWORD size) {
705   if (!stringHandle || !bsText || size == 0)
706     return false;
707 
708   FromFPDFStringHandle(stringHandle)->push_back(ByteString(bsText, size));
709   return true;
710 }
711 #endif  // PDF_ENABLE_XFA
712 
713 FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,int fieldType,unsigned long color)714 FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
715                                 int fieldType,
716                                 unsigned long color) {
717   CPDFSDK_InterForm* interForm = FormHandleToInterForm(hHandle);
718   if (!interForm)
719     return;
720 
721   Optional<FormFieldType> cast_input = IntToFormFieldType(fieldType);
722   if (!cast_input)
723     return;
724 
725   if (cast_input.value() == FormFieldType::kUnknown) {
726     interForm->SetAllHighlightColors(color);
727   } else {
728     interForm->SetHighlightColor(color, cast_input.value());
729   }
730 }
731 
732 FPDF_EXPORT void FPDF_CALLCONV
FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,unsigned char alpha)733 FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) {
734   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
735     pInterForm->SetHighlightAlpha(alpha);
736 }
737 
738 FPDF_EXPORT void FPDF_CALLCONV
FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle)739 FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
740   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
741     pInterForm->RemoveAllHighLights();
742 }
743 
FORM_OnAfterLoadPage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)744 FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page,
745                                                     FPDF_FORMHANDLE hHandle) {
746   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
747     pPageView->SetValid(true);
748 }
749 
FORM_OnBeforeClosePage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)750 FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page,
751                                                       FPDF_FORMHANDLE hHandle) {
752   CPDFSDK_FormFillEnvironment* pFormFillEnv =
753       HandleToCPDFSDKEnvironment(hHandle);
754   if (!pFormFillEnv)
755     return;
756 
757   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
758   if (!pPage)
759     return;
760 
761   CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, false);
762   if (pPageView) {
763     pPageView->SetValid(false);
764     // RemovePageView() takes care of the delete for us.
765     pFormFillEnv->RemovePageView(pPage);
766   }
767 }
768 
769 FPDF_EXPORT void FPDF_CALLCONV
FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle)770 FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
771   CPDFSDK_FormFillEnvironment* pFormFillEnv =
772       HandleToCPDFSDKEnvironment(hHandle);
773   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
774     pFormFillEnv->ProcJavascriptFun();
775 }
776 
777 FPDF_EXPORT void FPDF_CALLCONV
FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle)778 FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
779   CPDFSDK_FormFillEnvironment* pFormFillEnv =
780       HandleToCPDFSDKEnvironment(hHandle);
781   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
782     pFormFillEnv->ProcOpenAction();
783 }
784 
FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,int aaType)785 FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
786                                                       int aaType) {
787   CPDFSDK_FormFillEnvironment* pFormFillEnv =
788       HandleToCPDFSDKEnvironment(hHandle);
789   if (!pFormFillEnv)
790     return;
791 
792   CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument();
793   const CPDF_Dictionary* pDict = pDoc->GetRoot();
794   if (!pDict)
795     return;
796 
797   CPDF_AAction aa(pDict->GetDictFor("AA"));
798   auto type = static_cast<CPDF_AAction::AActionType>(aaType);
799   if (aa.ActionExist(type)) {
800     CPDF_Action action = aa.GetAction(type);
801     CPDFSDK_ActionHandler* pActionHandler =
802         HandleToCPDFSDKEnvironment(hHandle)->GetActionHandler();
803     pActionHandler->DoAction_Document(action, type, pFormFillEnv);
804   }
805 }
806 
FORM_DoPageAAction(FPDF_PAGE page,FPDF_FORMHANDLE hHandle,int aaType)807 FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page,
808                                                   FPDF_FORMHANDLE hHandle,
809                                                   int aaType) {
810   CPDFSDK_FormFillEnvironment* pFormFillEnv =
811       HandleToCPDFSDKEnvironment(hHandle);
812   if (!pFormFillEnv)
813     return;
814 
815   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
816   CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
817   if (!pPDFPage)
818     return;
819 
820   if (!pFormFillEnv->GetPageView(pPage, false))
821     return;
822 
823   CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
824   CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict.Get();
825   CPDF_AAction aa(pPageDict->GetDictFor("AA"));
826   CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN
827                                        ? CPDF_AAction::OpenPage
828                                        : CPDF_AAction::ClosePage;
829   if (aa.ActionExist(type)) {
830     CPDF_Action action = aa.GetAction(type);
831     pActionHandler->DoAction_Page(action, type, pFormFillEnv);
832   }
833 }
834