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
21namespace {
22
23CPDFSDK_Document* FormHandleToSDKDoc(FPDF_FORMHANDLE hHandle) {
24  CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle;
25  return pEnv ? pEnv->GetSDKDocument() : nullptr;
26}
27
28CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) {
29  CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
30  return pSDKDoc ? pSDKDoc->GetInterForm() : nullptr;
31}
32
33CPDFSDK_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
45DLLEXPORT 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
121DLLEXPORT 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
128DLLEXPORT 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
144DLLEXPORT FPDF_FORMHANDLE STDCALL
145FPDFDOC_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
170DLLEXPORT void STDCALL
171FPDFDOC_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
187DLLEXPORT 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
200DLLEXPORT 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
213DLLEXPORT 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
227DLLEXPORT 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
240DLLEXPORT 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
254DLLEXPORT 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
265DLLEXPORT 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
276DLLEXPORT 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
287DLLEXPORT 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
295DLLEXPORT 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
387DLLEXPORT 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}
404DLLEXPORT 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
422DLLEXPORT 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}
439DLLEXPORT 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}
475DLLEXPORT 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}
510DLLEXPORT 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}
530DLLEXPORT void STDCALL
531FPDF_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}
555DLLEXPORT void STDCALL
556FPDF_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}
582DLLEXPORT 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}
588DLLEXPORT FPDF_BOOL STDCALL
589FPDF_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}
615DLLEXPORT void STDCALL
616FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) {
617  if (stringHandle == NULL)
618    return;
619  CFX_ByteStringArray* sSuggestWords = (CFX_ByteStringArray*)stringHandle;
620  delete sSuggestWords;
621}
622
623DLLEXPORT FPDF_BOOL STDCALL
624FPDF_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
638DLLEXPORT 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
645DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,
646                                                       unsigned char alpha) {
647  if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
648    pInterForm->SetHighlightAlpha(alpha);
649}
650
651DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
652  if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
653    pInterForm->RemoveAllHighLight();
654}
655
656DLLEXPORT 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
662DLLEXPORT 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
683DLLEXPORT 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
689DLLEXPORT 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
695DLLEXPORT 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
716DLLEXPORT 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