• 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_fxgedevice.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/xfa_ffdocview.h"
33 #include "xfa/fxfa/xfa_ffpageview.h"
34 #include "xfa/fxfa/xfa_ffwidget.h"
35 #endif  // PDF_ENABLE_XFA
36 
37 namespace {
38 
HandleToCPDFSDKEnvironment(FPDF_FORMHANDLE handle)39 CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment(
40     FPDF_FORMHANDLE handle) {
41   return static_cast<CPDFSDK_FormFillEnvironment*>(handle);
42 }
43 
FormHandleToInterForm(FPDF_FORMHANDLE hHandle)44 CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) {
45   CPDFSDK_FormFillEnvironment* pFormFillEnv =
46       HandleToCPDFSDKEnvironment(hHandle);
47   return pFormFillEnv ? pFormFillEnv->GetInterForm() : nullptr;
48 }
49 
FormHandleToPageView(FPDF_FORMHANDLE hHandle,FPDF_PAGE page)50 CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle,
51                                        FPDF_PAGE page) {
52   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
53   if (!pPage)
54     return nullptr;
55 
56   CPDFSDK_FormFillEnvironment* pFormFillEnv =
57       HandleToCPDFSDKEnvironment(hHandle);
58   return pFormFillEnv ? pFormFillEnv->GetPageView(pPage, true) : nullptr;
59 }
60 
61 #ifdef PDF_ENABLE_XFA
FromFPDFStringHandle(FPDF_STRINGHANDLE handle)62 std::vector<CFX_ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) {
63   return reinterpret_cast<std::vector<CFX_ByteString>*>(handle);
64 }
65 
ToFPDFStringHandle(std::vector<CFX_ByteString> * strings)66 FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<CFX_ByteString>* strings) {
67   return reinterpret_cast<FPDF_STRINGHANDLE>(strings);
68 }
69 #endif  // PDF_ENABLE_XFA
70 
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)71 void FFLCommon(FPDF_FORMHANDLE hHandle,
72                FPDF_BITMAP bitmap,
73                FPDF_RECORDER recorder,
74                FPDF_PAGE page,
75                int start_x,
76                int start_y,
77                int size_x,
78                int size_y,
79                int rotate,
80                int flags) {
81   if (!hHandle)
82     return;
83 
84   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
85   if (!pPage)
86     return;
87 
88 #ifdef PDF_ENABLE_XFA
89   CPDFXFA_Context* pContext = pPage->GetContext();
90   if (!pContext)
91     return;
92   CPDF_Document* pPDFDoc = pContext->GetPDFDoc();
93   if (!pPDFDoc)
94     return;
95   CPDFSDK_FormFillEnvironment* pFormFillEnv =
96       HandleToCPDFSDKEnvironment(hHandle);
97   if (!pFormFillEnv)
98     return;
99 #endif  // PDF_ENABLE_XFA
100 
101   CFX_Matrix matrix =
102       pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
103   FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y);
104 
105   std::unique_ptr<CFX_FxgeDevice> pDevice(new CFX_FxgeDevice);
106 #ifdef _SKIA_SUPPORT_
107   pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
108 #endif
109   pDevice->Attach(CFXBitmapFromFPDFBitmap(bitmap), false, nullptr, false);
110   pDevice->SaveState();
111   pDevice->SetClip_Rect(clip);
112 
113   CPDF_RenderOptions options;
114   if (flags & FPDF_LCD_TEXT)
115     options.m_Flags |= RENDER_CLEARTYPE;
116   else
117     options.m_Flags &= ~RENDER_CLEARTYPE;
118 
119   // Grayscale output
120   if (flags & FPDF_GRAYSCALE) {
121     options.m_ColorMode = RENDER_COLOR_GRAY;
122     options.m_ForeColor = 0;
123     options.m_BackColor = 0xffffff;
124   }
125   options.m_AddFlags = flags >> 8;
126   options.m_bDrawAnnots = flags & FPDF_ANNOT;
127 
128 #ifdef PDF_ENABLE_XFA
129   options.m_pOCContext =
130       pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View);
131   if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true))
132     pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip);
133 #else   // PDF_ENABLE_XFA
134   options.m_pOCContext = pdfium::MakeRetain<CPDF_OCContext>(
135       pPage->m_pDocument, CPDF_OCContext::View);
136   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
137     pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
138 #endif  // PDF_ENABLE_XFA
139 
140   pDevice->RestoreState(false);
141 #ifdef _SKIA_SUPPORT_PATHS_
142   pDevice->Flush();
143   CFXBitmapFromFPDFBitmap(bitmap)->UnPreMultiply();
144 #endif
145 }
146 
147 }  // namespace
148 
FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)149 DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
150                                                    FPDF_PAGE page,
151                                                    double page_x,
152                                                    double page_y) {
153   if (!hHandle)
154     return -1;
155   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
156   if (pPage) {
157     CPDF_InterForm interform(pPage->m_pDocument);
158     CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
159         pPage, CFX_PointF(static_cast<FX_FLOAT>(page_x),
160                           static_cast<FX_FLOAT>(page_y)),
161         nullptr);
162     if (!pFormCtrl)
163       return -1;
164     CPDF_FormField* pFormField = pFormCtrl->GetField();
165     return pFormField ? pFormField->GetFieldType() : -1;
166   }
167 
168 #ifdef PDF_ENABLE_XFA
169   CPDFXFA_Page* pXFAPage = UnderlyingFromFPDFPage(page);
170   if (!pXFAPage)
171     return -1;
172 
173   CXFA_FFPageView* pPageView = pXFAPage->GetXFAPageView();
174   if (!pPageView)
175     return -1;
176 
177   CXFA_FFDocView* pDocView = pPageView->GetDocView();
178   if (!pDocView)
179     return -1;
180 
181   CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
182   if (!pWidgetHandler)
183     return -1;
184 
185   std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
186       pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form,
187                                       XFA_WidgetStatus_Viewable));
188   if (!pWidgetIterator)
189     return -1;
190 
191   CXFA_FFWidget* pXFAAnnot = pWidgetIterator->MoveToNext();
192   while (pXFAAnnot) {
193     CFX_RectF rcBBox = pXFAAnnot->GetBBox(0);
194     CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
195                            rcBBox.top + rcBBox.height);
196     rcWidget.left -= 1.0f;
197     rcWidget.right += 1.0f;
198     rcWidget.bottom -= 1.0f;
199     rcWidget.top += 1.0f;
200 
201     if (rcWidget.Contains(CFX_PointF(static_cast<FX_FLOAT>(page_x),
202                                      static_cast<FX_FLOAT>(page_y)))) {
203       return FPDF_FORMFIELD_XFA;
204     }
205     pXFAAnnot = pWidgetIterator->MoveToNext();
206   }
207 #endif  // PDF_ENABLE_XFA
208   return -1;
209 }
210 
FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)211 DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
212                                                   FPDF_PAGE page,
213                                                   double page_x,
214                                                   double page_y) {
215   return FPDFPage_HasFormFieldAtPoint(hHandle, page, page_x, page_y);
216 }
217 
FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,double page_x,double page_y)218 DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
219                                                       FPDF_PAGE page,
220                                                       double page_x,
221                                                       double page_y) {
222   if (!hHandle)
223     return -1;
224   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
225   if (!pPage)
226     return -1;
227   CPDF_InterForm interform(pPage->m_pDocument);
228   int z_order = -1;
229   (void)interform.GetControlAtPoint(
230       pPage,
231       CFX_PointF(static_cast<FX_FLOAT>(page_x), static_cast<FX_FLOAT>(page_y)),
232       &z_order);
233   return z_order;
234 }
235 
236 DLLEXPORT FPDF_FORMHANDLE STDCALL
FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,FPDF_FORMFILLINFO * formInfo)237 FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,
238                                 FPDF_FORMFILLINFO* formInfo) {
239 #ifdef PDF_ENABLE_XFA
240   const int kRequiredVersion = 2;
241 #else   // PDF_ENABLE_XFA
242   const int kRequiredVersion = 1;
243 #endif  // PDF_ENABLE_XFA
244   if (!formInfo || formInfo->version != kRequiredVersion)
245     return nullptr;
246 
247   UnderlyingDocumentType* pDocument = UnderlyingFromFPDFDocument(document);
248   if (!pDocument)
249     return nullptr;
250 
251 #ifdef PDF_ENABLE_XFA
252   // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
253   // this and can just return the old Env. Otherwise, we'll end up setting a new
254   // environment into the XFADocument and, that could get weird.
255   if (pDocument->GetFormFillEnv())
256     return pDocument->GetFormFillEnv();
257 #endif
258 
259   CPDFSDK_FormFillEnvironment* pFormFillEnv =
260       new CPDFSDK_FormFillEnvironment(pDocument, formInfo);
261 
262 #ifdef PDF_ENABLE_XFA
263   pDocument->SetFormFillEnv(pFormFillEnv);
264 #endif  // PDF_ENABLE_XFA
265 
266   return pFormFillEnv;
267 }
268 
269 DLLEXPORT void STDCALL
FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle)270 FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) {
271   if (!hHandle)
272     return;
273 
274   CPDFSDK_FormFillEnvironment* pFormFillEnv =
275       HandleToCPDFSDKEnvironment(hHandle);
276 
277 #ifdef PDF_ENABLE_XFA
278   // Reset the focused annotations and remove the SDK document from the
279   // XFA document.
280   pFormFillEnv->ClearAllFocusedAnnots();
281   // If the document was closed first, it's possible the XFA document
282   // is now a nullptr.
283   if (pFormFillEnv->GetXFAContext())
284     pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr);
285 #endif  // PDF_ENABLE_XFA
286 
287   delete pFormFillEnv;
288 }
289 
FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)290 DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
291                                              FPDF_PAGE page,
292                                              int modifier,
293                                              double page_x,
294                                              double page_y) {
295   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
296   if (!pPageView)
297     return false;
298   return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier);
299 }
300 
FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)301 DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
302                                                FPDF_PAGE page,
303                                                int modifier,
304                                                double page_x,
305                                                double page_y) {
306   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
307   if (!pPageView)
308     return false;
309   return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier);
310 }
311 
FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)312 DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
313                                              FPDF_PAGE page,
314                                              int modifier,
315                                              double page_x,
316                                              double page_y) {
317   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
318   if (!pPageView)
319     return false;
320 
321   CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
322   return pPageView->OnLButtonUp(pt, modifier);
323 }
324 
325 #ifdef PDF_ENABLE_XFA
FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)326 DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
327                                                FPDF_PAGE page,
328                                                int modifier,
329                                                double page_x,
330                                                double page_y) {
331   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
332   if (!pPageView)
333     return false;
334   return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier);
335 }
336 
FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int modifier,double page_x,double page_y)337 DLLEXPORT FPDF_BOOL STDCALL FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
338                                              FPDF_PAGE page,
339                                              int modifier,
340                                              double page_x,
341                                              double page_y) {
342   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
343   if (!pPageView)
344     return false;
345 
346   CFX_PointF pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
347   return pPageView->OnRButtonUp(pt, modifier);
348 }
349 #endif  // PDF_ENABLE_XFA
350 
FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)351 DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
352                                            FPDF_PAGE page,
353                                            int nKeyCode,
354                                            int modifier) {
355   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
356   if (!pPageView)
357     return false;
358 
359   return pPageView->OnKeyDown(nKeyCode, modifier);
360 }
361 
FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nKeyCode,int modifier)362 DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
363                                          FPDF_PAGE page,
364                                          int nKeyCode,
365                                          int modifier) {
366   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
367   if (!pPageView)
368     return false;
369 
370   return pPageView->OnKeyUp(nKeyCode, modifier);
371 }
372 
FORM_OnChar(FPDF_FORMHANDLE hHandle,FPDF_PAGE page,int nChar,int modifier)373 DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle,
374                                         FPDF_PAGE page,
375                                         int nChar,
376                                         int modifier) {
377   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
378   if (!pPageView)
379     return false;
380 
381   return pPageView->OnChar(nChar, modifier);
382 }
383 
FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle)384 DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
385   CPDFSDK_FormFillEnvironment* pFormFillEnv =
386       HandleToCPDFSDKEnvironment(hHandle);
387   if (!pFormFillEnv)
388     return false;
389   return pFormFillEnv->KillFocusAnnot(0);
390 }
391 
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)392 DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
393                                     FPDF_BITMAP bitmap,
394                                     FPDF_PAGE page,
395                                     int start_x,
396                                     int start_y,
397                                     int size_x,
398                                     int size_y,
399                                     int rotate,
400                                     int flags) {
401   FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y,
402             rotate, flags);
403 }
404 
405 #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)406 DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
407                                       FPDF_RECORDER recorder,
408                                       FPDF_PAGE page,
409                                       int start_x,
410                                       int start_y,
411                                       int size_x,
412                                       int size_y,
413                                       int rotate,
414                                       int flags) {
415   FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y,
416             rotate, flags);
417 }
418 #endif
419 
420 #ifdef PDF_ENABLE_XFA
FPDF_Widget_Undo(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)421 DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document,
422                                         FPDF_WIDGET hWidget) {
423   if (!hWidget || !document)
424     return;
425 
426   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
427   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
428       pContext->GetDocType() != XFA_DOCTYPE_Static)
429     return;
430 
431   static_cast<CXFA_FFWidget*>(hWidget)->Undo();
432 }
433 
FPDF_Widget_Redo(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)434 DLLEXPORT void STDCALL FPDF_Widget_Redo(FPDF_DOCUMENT document,
435                                         FPDF_WIDGET hWidget) {
436   if (!hWidget || !document)
437     return;
438 
439   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
440   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
441       pContext->GetDocType() != XFA_DOCTYPE_Static)
442     return;
443 
444   static_cast<CXFA_FFWidget*>(hWidget)->Redo();
445 }
446 
FPDF_Widget_SelectAll(FPDF_DOCUMENT document,FPDF_WIDGET hWidget)447 DLLEXPORT void STDCALL FPDF_Widget_SelectAll(FPDF_DOCUMENT document,
448                                              FPDF_WIDGET hWidget) {
449   if (!hWidget || !document)
450     return;
451 
452   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
453   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
454       pContext->GetDocType() != XFA_DOCTYPE_Static)
455     return;
456 
457   static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
458 }
459 
FPDF_Widget_Copy(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD * size)460 DLLEXPORT void STDCALL FPDF_Widget_Copy(FPDF_DOCUMENT document,
461                                         FPDF_WIDGET hWidget,
462                                         FPDF_WIDESTRING wsText,
463                                         FPDF_DWORD* size) {
464   if (!hWidget || !document)
465     return;
466 
467   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
468   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
469       pContext->GetDocType() != XFA_DOCTYPE_Static)
470     return;
471 
472   CFX_WideString wsCpText;
473   static_cast<CXFA_FFWidget*>(hWidget)->Copy(wsCpText);
474 
475   CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode();
476   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
477   if (!wsText) {
478     *size = len;
479     return;
480   }
481 
482   uint32_t real_size = len < *size ? len : *size;
483   if (real_size > 0) {
484     FXSYS_memcpy((void*)wsText,
485                  bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
486                  real_size * sizeof(unsigned short));
487     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
488   }
489   *size = real_size;
490 }
491 
FPDF_Widget_Cut(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD * size)492 DLLEXPORT void STDCALL FPDF_Widget_Cut(FPDF_DOCUMENT document,
493                                        FPDF_WIDGET hWidget,
494                                        FPDF_WIDESTRING wsText,
495                                        FPDF_DWORD* size) {
496   if (!hWidget || !document)
497     return;
498 
499   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
500   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
501       pContext->GetDocType() != XFA_DOCTYPE_Static)
502     return;
503 
504   CFX_WideString wsCpText;
505   static_cast<CXFA_FFWidget*>(hWidget)->Cut(wsCpText);
506 
507   CFX_ByteString bsCpText = wsCpText.UTF16LE_Encode();
508   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
509   if (!wsText) {
510     *size = len;
511     return;
512   }
513 
514   uint32_t real_size = len < *size ? len : *size;
515   if (real_size > 0) {
516     FXSYS_memcpy((void*)wsText,
517                  bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
518                  real_size * sizeof(unsigned short));
519     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
520   }
521   *size = real_size;
522 }
523 
FPDF_Widget_Paste(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,FPDF_WIDESTRING wsText,FPDF_DWORD size)524 DLLEXPORT void STDCALL FPDF_Widget_Paste(FPDF_DOCUMENT document,
525                                          FPDF_WIDGET hWidget,
526                                          FPDF_WIDESTRING wsText,
527                                          FPDF_DWORD size) {
528   if (!hWidget || !document)
529     return;
530 
531   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
532   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
533       pContext->GetDocType() != XFA_DOCTYPE_Static)
534     return;
535 
536   CFX_WideString wstr = CFX_WideString::FromUTF16LE(wsText, size);
537   static_cast<CXFA_FFWidget*>(hWidget)->Paste(wstr);
538 }
539 
540 DLLEXPORT void STDCALL
FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,float x,float y,FPDF_BYTESTRING bsText)541 FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,
542                                   FPDF_WIDGET hWidget,
543                                   float x,
544                                   float y,
545                                   FPDF_BYTESTRING bsText) {
546   if (!hWidget || !document)
547     return;
548 
549   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
550   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
551       pContext->GetDocType() != XFA_DOCTYPE_Static)
552     return;
553 
554   CFX_PointF ptPopup;
555   ptPopup.x = x;
556   ptPopup.y = y;
557   CFX_ByteStringC bs(bsText);
558   static_cast<CXFA_FFWidget*>(hWidget)->ReplaceSpellCheckWord(ptPopup, bs);
559 }
560 
561 DLLEXPORT void STDCALL
FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,FPDF_WIDGET hWidget,float x,float y,FPDF_STRINGHANDLE * stringHandle)562 FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,
563                                FPDF_WIDGET hWidget,
564                                float x,
565                                float y,
566                                FPDF_STRINGHANDLE* stringHandle) {
567   if (!hWidget || !document)
568     return;
569 
570   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
571   if (pContext->GetDocType() != XFA_DOCTYPE_Dynamic &&
572       pContext->GetDocType() != XFA_DOCTYPE_Static)
573     return;
574 
575   std::vector<CFX_ByteString>* sSuggestWords = new std::vector<CFX_ByteString>;
576   CFX_PointF ptPopup;
577   ptPopup.x = x;
578   ptPopup.y = y;
579   static_cast<CXFA_FFWidget*>(hWidget)
580       ->GetSuggestWords(ptPopup, *sSuggestWords);
581   *stringHandle = ToFPDFStringHandle(sSuggestWords);
582 }
583 
FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle)584 DLLEXPORT int STDCALL FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) {
585   std::vector<CFX_ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
586   return sSuggestWords ? pdfium::CollectionSize<int>(*sSuggestWords) : -1;
587 }
588 
589 DLLEXPORT FPDF_BOOL STDCALL
FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,int index,FPDF_BYTESTRING bsText,FPDF_DWORD * size)590 FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,
591                                   int index,
592                                   FPDF_BYTESTRING bsText,
593                                   FPDF_DWORD* size) {
594   if (!sHandle || !size)
595     return false;
596 
597   int count = FPDF_StringHandleCounts(sHandle);
598   if (index < 0 || index >= count)
599     return false;
600 
601   std::vector<CFX_ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
602   uint32_t len = (*sSuggestWords)[index].GetLength();
603   if (!bsText) {
604     *size = len;
605     return true;
606   }
607 
608   uint32_t real_size = len < *size ? len : *size;
609   if (real_size > 0)
610     FXSYS_memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size);
611   *size = real_size;
612   return true;
613 }
614 
615 DLLEXPORT void STDCALL
FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle)616 FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) {
617   delete FromFPDFStringHandle(stringHandle);
618 }
619 
620 DLLEXPORT FPDF_BOOL STDCALL
FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,FPDF_BYTESTRING bsText,FPDF_DWORD size)621 FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,
622                            FPDF_BYTESTRING bsText,
623                            FPDF_DWORD size) {
624   if (!stringHandle || !bsText || size == 0)
625     return false;
626 
627   FromFPDFStringHandle(stringHandle)->push_back(CFX_ByteString(bsText, size));
628   return true;
629 }
630 #endif  // PDF_ENABLE_XFA
631 
FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,int fieldType,unsigned long color)632 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
633                                                        int fieldType,
634                                                        unsigned long color) {
635   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
636     pInterForm->SetHighlightColor(color, fieldType);
637 }
638 
FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,unsigned char alpha)639 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,
640                                                        unsigned char alpha) {
641   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
642     pInterForm->SetHighlightAlpha(alpha);
643 }
644 
FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle)645 DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
646   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
647     pInterForm->RemoveAllHighLight();
648 }
649 
FORM_OnAfterLoadPage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)650 DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page,
651                                             FPDF_FORMHANDLE hHandle) {
652   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
653     pPageView->SetValid(true);
654 }
655 
FORM_OnBeforeClosePage(FPDF_PAGE page,FPDF_FORMHANDLE hHandle)656 DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page,
657                                               FPDF_FORMHANDLE hHandle) {
658   if (!hHandle)
659     return;
660 
661   CPDFSDK_FormFillEnvironment* pFormFillEnv =
662       HandleToCPDFSDKEnvironment(hHandle);
663   if (!pFormFillEnv)
664     return;
665 
666   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
667   if (!pPage)
668     return;
669 
670   CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, false);
671   if (pPageView) {
672     pPageView->SetValid(false);
673     // RemovePageView() takes care of the delete for us.
674     pFormFillEnv->RemovePageView(pPage);
675   }
676 }
677 
FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle)678 DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
679   CPDFSDK_FormFillEnvironment* pFormFillEnv =
680       HandleToCPDFSDKEnvironment(hHandle);
681   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
682     pFormFillEnv->ProcJavascriptFun();
683 }
684 
FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle)685 DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
686   CPDFSDK_FormFillEnvironment* pFormFillEnv =
687       HandleToCPDFSDKEnvironment(hHandle);
688   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
689     pFormFillEnv->ProcOpenAction();
690 }
691 
FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,int aaType)692 DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
693                                               int aaType) {
694   CPDFSDK_FormFillEnvironment* pFormFillEnv =
695       HandleToCPDFSDKEnvironment(hHandle);
696   if (!pFormFillEnv)
697     return;
698 
699   CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument();
700   CPDF_Dictionary* pDic = pDoc->GetRoot();
701   if (!pDic)
702     return;
703 
704   CPDF_AAction aa(pDic->GetDictFor("AA"));
705   if (aa.ActionExist((CPDF_AAction::AActionType)aaType)) {
706     CPDF_Action action = aa.GetAction((CPDF_AAction::AActionType)aaType);
707     CPDFSDK_ActionHandler* pActionHandler =
708         HandleToCPDFSDKEnvironment(hHandle)->GetActionHander();
709     pActionHandler->DoAction_Document(action, (CPDF_AAction::AActionType)aaType,
710                                       pFormFillEnv);
711   }
712 }
713 
FORM_DoPageAAction(FPDF_PAGE page,FPDF_FORMHANDLE hHandle,int aaType)714 DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page,
715                                           FPDF_FORMHANDLE hHandle,
716                                           int aaType) {
717   if (!hHandle)
718     return;
719 
720   CPDFSDK_FormFillEnvironment* pFormFillEnv =
721       HandleToCPDFSDKEnvironment(hHandle);
722   if (!pFormFillEnv)
723     return;
724 
725   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
726   CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
727   if (!pPDFPage)
728     return;
729 
730   if (!pFormFillEnv->GetPageView(pPage, false))
731     return;
732 
733   CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHander();
734   CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict;
735   CPDF_AAction aa(pPageDict->GetDictFor("AA"));
736   if (FPDFPAGE_AACTION_OPEN == aaType) {
737     if (aa.ActionExist(CPDF_AAction::OpenPage)) {
738       CPDF_Action action = aa.GetAction(CPDF_AAction::OpenPage);
739       pActionHandler->DoAction_Page(action, CPDF_AAction::OpenPage,
740                                     pFormFillEnv);
741     }
742   } else {
743     if (aa.ActionExist(CPDF_AAction::ClosePage)) {
744       CPDF_Action action = aa.GetAction(CPDF_AAction::ClosePage);
745       pActionHandler->DoAction_Page(action, CPDF_AAction::ClosePage,
746                                     pFormFillEnv);
747     }
748   }
749 }
750