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