Home | History | Annotate | Download | only in src
      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 
     23 CPDFSDK_Document* FormHandleToSDKDoc(FPDF_FORMHANDLE hHandle) {
     24   CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle;
     25   return pEnv ? pEnv->GetSDKDocument() : nullptr;
     26 }
     27 
     28 CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) {
     29   CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
     30   return pSDKDoc ? pSDKDoc->GetInterForm() : nullptr;
     31 }
     32 
     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 
     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 
    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 
    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
    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
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 }
    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 
    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 }
    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 }
    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 }
    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
    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
    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 }
    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
    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
    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
    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 
    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 
    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 
    651 DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
    652   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
    653     pInterForm->RemoveAllHighLight();
    654 }
    655 
    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 
    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 
    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 
    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 
    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 
    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