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