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