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_defaultrenderdevice.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/cxfa_ffdocview.h"
     33 #include "xfa/fxfa/cxfa_ffpageview.h"
     34 #include "xfa/fxfa/cxfa_ffwidget.h"
     35 
     36 static_assert(static_cast<int>(FormType::kNone) == FORMTYPE_NONE,
     37               "None form types must match");
     38 static_assert(static_cast<int>(FormType::kAcroForm) == FORMTYPE_ACRO_FORM,
     39               "AcroForm form types must match");
     40 static_assert(static_cast<int>(FormType::kXFAFull) == FORMTYPE_XFA_FULL,
     41               "XFA full form types must match");
     42 static_assert(static_cast<int>(FormType::kXFAForeground) ==
     43                   FORMTYPE_XFA_FOREGROUND,
     44               "XFA foreground form types must match");
     45 #endif  // PDF_ENABLE_XFA
     46 
     47 static_assert(static_cast<int>(FormFieldType::kUnknown) ==
     48                   FPDF_FORMFIELD_UNKNOWN,
     49               "Unknown form field types must match");
     50 static_assert(static_cast<int>(FormFieldType::kPushButton) ==
     51                   FPDF_FORMFIELD_PUSHBUTTON,
     52               "PushButton form field types must match");
     53 static_assert(static_cast<int>(FormFieldType::kCheckBox) ==
     54                   FPDF_FORMFIELD_CHECKBOX,
     55               "CheckBox form field types must match");
     56 static_assert(static_cast<int>(FormFieldType::kRadioButton) ==
     57                   FPDF_FORMFIELD_RADIOBUTTON,
     58               "RadioButton form field types must match");
     59 static_assert(static_cast<int>(FormFieldType::kComboBox) ==
     60                   FPDF_FORMFIELD_COMBOBOX,
     61               "ComboBox form field types must match");
     62 static_assert(static_cast<int>(FormFieldType::kListBox) ==
     63                   FPDF_FORMFIELD_LISTBOX,
     64               "ListBox form field types must match");
     65 static_assert(static_cast<int>(FormFieldType::kTextField) ==
     66                   FPDF_FORMFIELD_TEXTFIELD,
     67               "TextField form field types must match");
     68 static_assert(static_cast<int>(FormFieldType::kSignature) ==
     69                   FPDF_FORMFIELD_SIGNATURE,
     70               "Signature form field types must match");
     71 #ifdef PDF_ENABLE_XFA
     72 static_assert(static_cast<int>(FormFieldType::kXFA) == FPDF_FORMFIELD_XFA,
     73               "XFA form field types must match");
     74 static_assert(static_cast<int>(FormFieldType::kXFA_CheckBox) ==
     75                   FPDF_FORMFIELD_XFA_CHECKBOX,
     76               "XFA CheckBox form field types must match");
     77 static_assert(static_cast<int>(FormFieldType::kXFA_ComboBox) ==
     78                   FPDF_FORMFIELD_XFA_COMBOBOX,
     79               "XFA ComboBox form field types must match");
     80 static_assert(static_cast<int>(FormFieldType::kXFA_ImageField) ==
     81                   FPDF_FORMFIELD_XFA_IMAGEFIELD,
     82               "XFA ImageField form field types must match");
     83 static_assert(static_cast<int>(FormFieldType::kXFA_ListBox) ==
     84                   FPDF_FORMFIELD_XFA_LISTBOX,
     85               "XFA ListBox form field types must match");
     86 static_assert(static_cast<int>(FormFieldType::kXFA_PushButton) ==
     87                   FPDF_FORMFIELD_XFA_PUSHBUTTON,
     88               "XFA PushButton form field types must match");
     89 static_assert(static_cast<int>(FormFieldType::kXFA_Signature) ==
     90                   FPDF_FORMFIELD_XFA_SIGNATURE,
     91               "XFA Signature form field types must match");
     92 static_assert(static_cast<int>(FormFieldType::kXFA_TextField) ==
     93                   FPDF_FORMFIELD_XFA_TEXTFIELD,
     94               "XFA TextField form field types must match");
     95 #endif  // PDF_ENABLE_XFA
     96 static_assert(kFormFieldTypeCount == FPDF_FORMFIELD_COUNT,
     97               "Number of form field types must match");
     98 
     99 namespace {
    100 
    101 CPDFSDK_FormFillEnvironment* HandleToCPDFSDKEnvironment(
    102     FPDF_FORMHANDLE handle) {
    103   return static_cast<CPDFSDK_FormFillEnvironment*>(handle);
    104 }
    105 
    106 CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle) {
    107   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    108       HandleToCPDFSDKEnvironment(hHandle);
    109   return pFormFillEnv ? pFormFillEnv->GetInterForm() : nullptr;
    110 }
    111 
    112 CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle,
    113                                        FPDF_PAGE page) {
    114   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
    115   if (!pPage)
    116     return nullptr;
    117 
    118   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    119       HandleToCPDFSDKEnvironment(hHandle);
    120   return pFormFillEnv ? pFormFillEnv->GetPageView(pPage, true) : nullptr;
    121 }
    122 
    123 #ifdef PDF_ENABLE_XFA
    124 std::vector<ByteString>* FromFPDFStringHandle(FPDF_STRINGHANDLE handle) {
    125   return static_cast<std::vector<ByteString>*>(handle);
    126 }
    127 
    128 FPDF_STRINGHANDLE ToFPDFStringHandle(std::vector<ByteString>* strings) {
    129   return static_cast<FPDF_STRINGHANDLE>(strings);
    130 }
    131 #endif  // PDF_ENABLE_XFA
    132 
    133 void FFLCommon(FPDF_FORMHANDLE hHandle,
    134                FPDF_BITMAP bitmap,
    135                FPDF_RECORDER recorder,
    136                FPDF_PAGE page,
    137                int start_x,
    138                int start_y,
    139                int size_x,
    140                int size_y,
    141                int rotate,
    142                int flags) {
    143   if (!hHandle)
    144     return;
    145 
    146   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
    147   if (!pPage)
    148     return;
    149 
    150 #ifdef PDF_ENABLE_XFA
    151   CPDFXFA_Context* pContext = pPage->GetContext();
    152   if (!pContext)
    153     return;
    154   CPDF_Document* pPDFDoc = pContext->GetPDFDoc();
    155   if (!pPDFDoc)
    156     return;
    157   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    158       HandleToCPDFSDKEnvironment(hHandle);
    159   if (!pFormFillEnv)
    160     return;
    161 #endif  // PDF_ENABLE_XFA
    162 
    163   CFX_Matrix matrix =
    164       pPage->GetDisplayMatrix(start_x, start_y, size_x, size_y, rotate);
    165   FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y);
    166 
    167   auto pDevice = pdfium::MakeUnique<CFX_DefaultRenderDevice>();
    168 #ifdef _SKIA_SUPPORT_
    169   pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
    170 #endif
    171   RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap));
    172   pDevice->Attach(holder, false, nullptr, false);
    173   {
    174     CFX_RenderDevice::StateRestorer restorer(pDevice.get());
    175     pDevice->SetClip_Rect(clip);
    176 
    177     CPDF_RenderOptions options;
    178     uint32_t option_flags = options.GetFlags();
    179     if (flags & FPDF_LCD_TEXT)
    180       option_flags |= RENDER_CLEARTYPE;
    181     else
    182       option_flags &= ~RENDER_CLEARTYPE;
    183     options.SetFlags(option_flags);
    184 
    185     // Grayscale output
    186     if (flags & FPDF_GRAYSCALE)
    187       options.SetColorMode(CPDF_RenderOptions::kGray);
    188 
    189     options.SetDrawAnnots(flags & FPDF_ANNOT);
    190 
    191 #ifdef PDF_ENABLE_XFA
    192     options.SetOCContext(
    193         pdfium::MakeRetain<CPDF_OCContext>(pPDFDoc, CPDF_OCContext::View));
    194     if (CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, true))
    195       pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options, clip);
    196 #else   // PDF_ENABLE_XFA
    197     options.SetOCContext(pdfium::MakeRetain<CPDF_OCContext>(
    198         pPage->m_pDocument.Get(), CPDF_OCContext::View));
    199     if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
    200       pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
    201 #endif  // PDF_ENABLE_XFA
    202   }
    203 #ifdef _SKIA_SUPPORT_PATHS_
    204   pDevice->Flush(true);
    205   holder->UnPreMultiply();
    206 #endif
    207 }
    208 
    209 }  // namespace
    210 
    211 FPDF_EXPORT int FPDF_CALLCONV
    212 FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
    213                              FPDF_PAGE page,
    214                              double page_x,
    215                              double page_y) {
    216   if (!hHandle)
    217     return -1;
    218   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
    219   if (pPage) {
    220     CPDF_InterForm interform(pPage->m_pDocument.Get());
    221     CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
    222         pPage,
    223         CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
    224         nullptr);
    225     if (!pFormCtrl)
    226       return -1;
    227     CPDF_FormField* pFormField = pFormCtrl->GetField();
    228     return pFormField ? static_cast<int>(pFormField->GetFieldType()) : -1;
    229   }
    230 
    231 #ifdef PDF_ENABLE_XFA
    232   CPDFXFA_Page* pXFAPage = UnderlyingFromFPDFPage(page);
    233   if (!pXFAPage)
    234     return -1;
    235 
    236   CXFA_FFPageView* pPageView = pXFAPage->GetXFAPageView();
    237   if (!pPageView)
    238     return -1;
    239 
    240   CXFA_FFDocView* pDocView = pPageView->GetDocView();
    241   if (!pDocView)
    242     return -1;
    243 
    244   CXFA_FFWidgetHandler* pWidgetHandler = pDocView->GetWidgetHandler();
    245   if (!pWidgetHandler)
    246     return -1;
    247 
    248   std::unique_ptr<IXFA_WidgetIterator> pWidgetIterator(
    249       pPageView->CreateWidgetIterator(XFA_TRAVERSEWAY_Form,
    250                                       XFA_WidgetStatus_Viewable));
    251   if (!pWidgetIterator)
    252     return -1;
    253 
    254   CXFA_FFWidget* pXFAAnnot;
    255   while ((pXFAAnnot = pWidgetIterator->MoveToNext()) != nullptr) {
    256     CFX_RectF rcBBox = pXFAAnnot->GetBBox(0);
    257     CFX_FloatRect rcWidget(rcBBox.left, rcBBox.top, rcBBox.left + rcBBox.width,
    258                            rcBBox.top + rcBBox.height);
    259     rcWidget.Inflate(1.0f, 1.0f);
    260     if (rcWidget.Contains(CFX_PointF(static_cast<float>(page_x),
    261                                      static_cast<float>(page_y)))) {
    262       return static_cast<int>(pXFAAnnot->GetFormFieldType());
    263     }
    264   }
    265 #endif  // PDF_ENABLE_XFA
    266   return -1;
    267 }
    268 
    269 FPDF_EXPORT int FPDF_CALLCONV
    270 FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
    271                                 FPDF_PAGE page,
    272                                 double page_x,
    273                                 double page_y) {
    274   if (!hHandle)
    275     return -1;
    276   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
    277   if (!pPage)
    278     return -1;
    279   CPDF_InterForm interform(pPage->m_pDocument.Get());
    280   int z_order = -1;
    281   (void)interform.GetControlAtPoint(
    282       pPage, CFX_PointF(static_cast<float>(page_x), static_cast<float>(page_y)),
    283       &z_order);
    284   return z_order;
    285 }
    286 
    287 FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV
    288 FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document,
    289                                 FPDF_FORMFILLINFO* formInfo) {
    290 #ifdef PDF_ENABLE_XFA
    291   const int kRequiredVersion = 2;
    292 #else   // PDF_ENABLE_XFA
    293   const int kRequiredVersion = 1;
    294 #endif  // PDF_ENABLE_XFA
    295   if (!formInfo || formInfo->version != kRequiredVersion)
    296     return nullptr;
    297 
    298   UnderlyingDocumentType* pDocument = UnderlyingFromFPDFDocument(document);
    299   if (!pDocument)
    300     return nullptr;
    301 
    302 #ifdef PDF_ENABLE_XFA
    303   // If the CPDFXFA_Context has a FormFillEnvironment already then we've done
    304   // this and can just return the old Env. Otherwise, we'll end up setting a new
    305   // environment into the XFADocument and, that could get weird.
    306   if (pDocument->GetFormFillEnv())
    307     return pDocument->GetFormFillEnv();
    308 #endif
    309 
    310   auto pFormFillEnv =
    311       pdfium::MakeUnique<CPDFSDK_FormFillEnvironment>(pDocument, formInfo);
    312 
    313 #ifdef PDF_ENABLE_XFA
    314   pDocument->SetFormFillEnv(pFormFillEnv.get());
    315 #endif  // PDF_ENABLE_XFA
    316 
    317   return pFormFillEnv.release();  // Caller takes ownership.
    318 }
    319 
    320 FPDF_EXPORT void FPDF_CALLCONV
    321 FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle) {
    322   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    323       HandleToCPDFSDKEnvironment(hHandle);
    324   if (!pFormFillEnv)
    325     return;
    326 
    327 #ifdef PDF_ENABLE_XFA
    328   // Reset the focused annotations and remove the SDK document from the
    329   // XFA document.
    330   pFormFillEnv->ClearAllFocusedAnnots();
    331   // If the document was closed first, it's possible the XFA document
    332   // is now a nullptr.
    333   if (pFormFillEnv->GetXFAContext())
    334     pFormFillEnv->GetXFAContext()->SetFormFillEnv(nullptr);
    335 #endif  // PDF_ENABLE_XFA
    336   delete pFormFillEnv;
    337 }
    338 
    339 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnMouseMove(FPDF_FORMHANDLE hHandle,
    340                                                      FPDF_PAGE page,
    341                                                      int modifier,
    342                                                      double page_x,
    343                                                      double page_y) {
    344   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    345   if (!pPageView)
    346     return false;
    347   return pPageView->OnMouseMove(CFX_PointF(page_x, page_y), modifier);
    348 }
    349 
    350 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnFocus(FPDF_FORMHANDLE hHandle,
    351                                                  FPDF_PAGE page,
    352                                                  int modifier,
    353                                                  double page_x,
    354                                                  double page_y) {
    355   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    356   if (!pPageView)
    357     return false;
    358   return pPageView->OnFocus(CFX_PointF(page_x, page_y), modifier);
    359 }
    360 
    361 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle,
    362                                                        FPDF_PAGE page,
    363                                                        int modifier,
    364                                                        double page_x,
    365                                                        double page_y) {
    366   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    367   if (!pPageView)
    368     return false;
    369   return pPageView->OnLButtonDown(CFX_PointF(page_x, page_y), modifier);
    370 }
    371 
    372 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle,
    373                                                      FPDF_PAGE page,
    374                                                      int modifier,
    375                                                      double page_x,
    376                                                      double page_y) {
    377   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    378   if (!pPageView)
    379     return false;
    380   return pPageView->OnLButtonUp(CFX_PointF(page_x, page_y), modifier);
    381 }
    382 
    383 #ifdef PDF_ENABLE_XFA
    384 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonDown(FPDF_FORMHANDLE hHandle,
    385                                                        FPDF_PAGE page,
    386                                                        int modifier,
    387                                                        double page_x,
    388                                                        double page_y) {
    389   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    390   if (!pPageView)
    391     return false;
    392   return pPageView->OnRButtonDown(CFX_PointF(page_x, page_y), modifier);
    393 }
    394 
    395 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnRButtonUp(FPDF_FORMHANDLE hHandle,
    396                                                      FPDF_PAGE page,
    397                                                      int modifier,
    398                                                      double page_x,
    399                                                      double page_y) {
    400   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    401   if (!pPageView)
    402     return false;
    403   return pPageView->OnRButtonUp(CFX_PointF(page_x, page_y), modifier);
    404 }
    405 #endif  // PDF_ENABLE_XFA
    406 
    407 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyDown(FPDF_FORMHANDLE hHandle,
    408                                                    FPDF_PAGE page,
    409                                                    int nKeyCode,
    410                                                    int modifier) {
    411   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    412   if (!pPageView)
    413     return false;
    414   return pPageView->OnKeyDown(nKeyCode, modifier);
    415 }
    416 
    417 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnKeyUp(FPDF_FORMHANDLE hHandle,
    418                                                  FPDF_PAGE page,
    419                                                  int nKeyCode,
    420                                                  int modifier) {
    421   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    422   if (!pPageView)
    423     return false;
    424   return pPageView->OnKeyUp(nKeyCode, modifier);
    425 }
    426 
    427 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FORM_OnChar(FPDF_FORMHANDLE hHandle,
    428                                                 FPDF_PAGE page,
    429                                                 int nChar,
    430                                                 int modifier) {
    431   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    432   if (!pPageView)
    433     return false;
    434   return pPageView->OnChar(nChar, modifier);
    435 }
    436 
    437 FPDF_EXPORT unsigned long FPDF_CALLCONV
    438 FORM_GetSelectedText(FPDF_FORMHANDLE hHandle,
    439                      FPDF_PAGE page,
    440                      void* buffer,
    441                      unsigned long buflen) {
    442   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    443   if (!pPageView)
    444     return 0;
    445 
    446   WideString wide_str_form_text = pPageView->GetSelectedText();
    447   ByteString encoded_form_text = wide_str_form_text.UTF16LE_Encode();
    448   unsigned long form_text_len = encoded_form_text.GetLength();
    449 
    450   if (buffer && buflen >= form_text_len)
    451     memcpy(buffer, encoded_form_text.c_str(), form_text_len);
    452 
    453   return form_text_len;
    454 }
    455 
    456 FPDF_EXPORT void FPDF_CALLCONV FORM_ReplaceSelection(FPDF_FORMHANDLE hHandle,
    457                                                      FPDF_PAGE page,
    458                                                      FPDF_WIDESTRING wsText) {
    459   CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
    460   if (!pPageView)
    461     return;
    462 
    463   size_t len = WideString::WStringLength(wsText);
    464   WideString wide_str_text = WideString::FromUTF16LE(wsText, len);
    465 
    466   pPageView->ReplaceSelection(wide_str_text);
    467 }
    468 
    469 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
    470 FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
    471   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    472       HandleToCPDFSDKEnvironment(hHandle);
    473   if (!pFormFillEnv)
    474     return false;
    475   return pFormFillEnv->KillFocusAnnot(0);
    476 }
    477 
    478 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
    479                                             FPDF_BITMAP bitmap,
    480                                             FPDF_PAGE page,
    481                                             int start_x,
    482                                             int start_y,
    483                                             int size_x,
    484                                             int size_y,
    485                                             int rotate,
    486                                             int flags) {
    487   FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y,
    488             rotate, flags);
    489 }
    490 
    491 #ifdef _SKIA_SUPPORT_
    492 FPDF_EXPORT void FPDF_CALLCONV FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
    493                                               FPDF_RECORDER recorder,
    494                                               FPDF_PAGE page,
    495                                               int start_x,
    496                                               int start_y,
    497                                               int size_x,
    498                                               int size_y,
    499                                               int rotate,
    500                                               int flags) {
    501   FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y,
    502             rotate, flags);
    503 }
    504 #endif
    505 
    506 #ifdef PDF_ENABLE_XFA
    507 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Undo(FPDF_DOCUMENT document,
    508                                                 FPDF_WIDGET hWidget) {
    509   if (!hWidget || !document)
    510     return;
    511 
    512   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    513   if (!pContext->ContainsXFAForm())
    514     return;
    515 
    516   static_cast<CXFA_FFWidget*>(hWidget)->Undo();
    517 }
    518 
    519 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Redo(FPDF_DOCUMENT document,
    520                                                 FPDF_WIDGET hWidget) {
    521   if (!hWidget || !document)
    522     return;
    523 
    524   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    525   if (!pContext->ContainsXFAForm())
    526     return;
    527 
    528   static_cast<CXFA_FFWidget*>(hWidget)->Redo();
    529 }
    530 
    531 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_SelectAll(FPDF_DOCUMENT document,
    532                                                      FPDF_WIDGET hWidget) {
    533   if (!hWidget || !document)
    534     return;
    535 
    536   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    537   if (!pContext->ContainsXFAForm())
    538     return;
    539 
    540   static_cast<CXFA_FFWidget*>(hWidget)->SelectAll();
    541 }
    542 
    543 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Copy(FPDF_DOCUMENT document,
    544                                                 FPDF_WIDGET hWidget,
    545                                                 FPDF_WIDESTRING wsText,
    546                                                 FPDF_DWORD* size) {
    547   if (!hWidget || !document)
    548     return;
    549 
    550   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    551   if (!pContext->ContainsXFAForm())
    552     return;
    553 
    554   WideString wsCpText =
    555       static_cast<CXFA_FFWidget*>(hWidget)->Copy().value_or(WideString());
    556 
    557   ByteString bsCpText = wsCpText.UTF16LE_Encode();
    558   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
    559   if (!wsText) {
    560     *size = len;
    561     return;
    562   }
    563 
    564   uint32_t real_size = len < *size ? len : *size;
    565   if (real_size > 0) {
    566     memcpy((void*)wsText,
    567            bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
    568            real_size * sizeof(unsigned short));
    569     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
    570   }
    571   *size = real_size;
    572 }
    573 
    574 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Cut(FPDF_DOCUMENT document,
    575                                                FPDF_WIDGET hWidget,
    576                                                FPDF_WIDESTRING wsText,
    577                                                FPDF_DWORD* size) {
    578   if (!hWidget || !document)
    579     return;
    580 
    581   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    582   if (!pContext->ContainsXFAForm())
    583     return;
    584 
    585   WideString wsCpText =
    586       static_cast<CXFA_FFWidget*>(hWidget)->Cut().value_or(WideString());
    587 
    588   ByteString bsCpText = wsCpText.UTF16LE_Encode();
    589   uint32_t len = bsCpText.GetLength() / sizeof(unsigned short);
    590   if (!wsText) {
    591     *size = len;
    592     return;
    593   }
    594 
    595   uint32_t real_size = len < *size ? len : *size;
    596   if (real_size > 0) {
    597     memcpy((void*)wsText,
    598            bsCpText.GetBuffer(real_size * sizeof(unsigned short)),
    599            real_size * sizeof(unsigned short));
    600     bsCpText.ReleaseBuffer(real_size * sizeof(unsigned short));
    601   }
    602   *size = real_size;
    603 }
    604 
    605 FPDF_EXPORT void FPDF_CALLCONV FPDF_Widget_Paste(FPDF_DOCUMENT document,
    606                                                  FPDF_WIDGET hWidget,
    607                                                  FPDF_WIDESTRING wsText,
    608                                                  FPDF_DWORD size) {
    609   if (!hWidget || !document)
    610     return;
    611 
    612   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    613   if (!pContext->ContainsXFAForm())
    614     return;
    615 
    616   WideString wstr = WideString::FromUTF16LE(wsText, size);
    617   static_cast<CXFA_FFWidget*>(hWidget)->Paste(wstr);
    618 }
    619 
    620 FPDF_EXPORT void FPDF_CALLCONV
    621 FPDF_Widget_ReplaceSpellCheckWord(FPDF_DOCUMENT document,
    622                                   FPDF_WIDGET hWidget,
    623                                   float x,
    624                                   float y,
    625                                   FPDF_BYTESTRING bsText) {
    626   if (!hWidget || !document)
    627     return;
    628 
    629   CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
    630   if (!pContext->ContainsXFAForm())
    631     return;
    632 
    633   CFX_PointF ptPopup;
    634   ptPopup.x = x;
    635   ptPopup.y = y;
    636   ByteStringView bs(bsText);
    637   static_cast<CXFA_FFWidget*>(hWidget)->ReplaceSpellCheckWord(ptPopup, bs);
    638 }
    639 
    640 FPDF_EXPORT void FPDF_CALLCONV
    641 FPDF_Widget_GetSpellCheckWords(FPDF_DOCUMENT document,
    642                                FPDF_WIDGET hWidget,
    643                                float x,
    644                                float y,
    645                                FPDF_STRINGHANDLE* stringHandle) {
    646   if (!hWidget || !document)
    647     return;
    648 
    649   auto* pContext = static_cast<CPDFXFA_Context*>(document);
    650   if (!pContext->ContainsXFAForm())
    651     return;
    652 
    653   CFX_PointF ptPopup;
    654   ptPopup.x = x;
    655   ptPopup.y = y;
    656   auto sSuggestWords = pdfium::MakeUnique<std::vector<ByteString>>();
    657   static_cast<CXFA_FFWidget*>(hWidget)->GetSuggestWords(ptPopup,
    658                                                         sSuggestWords.get());
    659 
    660   // Caller takes ownership.
    661   *stringHandle = ToFPDFStringHandle(sSuggestWords.release());
    662 }
    663 
    664 FPDF_EXPORT int FPDF_CALLCONV
    665 FPDF_StringHandleCounts(FPDF_STRINGHANDLE sHandle) {
    666   std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
    667   return sSuggestWords ? pdfium::CollectionSize<int>(*sSuggestWords) : -1;
    668 }
    669 
    670 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
    671 FPDF_StringHandleGetStringByIndex(FPDF_STRINGHANDLE sHandle,
    672                                   int index,
    673                                   FPDF_BYTESTRING bsText,
    674                                   FPDF_DWORD* size) {
    675   if (!sHandle || !size)
    676     return false;
    677 
    678   int count = FPDF_StringHandleCounts(sHandle);
    679   if (index < 0 || index >= count)
    680     return false;
    681 
    682   std::vector<ByteString>* sSuggestWords = FromFPDFStringHandle(sHandle);
    683   uint32_t len = (*sSuggestWords)[index].GetLength();
    684   if (!bsText) {
    685     *size = len;
    686     return true;
    687   }
    688 
    689   uint32_t real_size = len < *size ? len : *size;
    690   if (real_size > 0)
    691     memcpy((void*)bsText, (*sSuggestWords)[index].c_str(), real_size);
    692   *size = real_size;
    693   return true;
    694 }
    695 
    696 FPDF_EXPORT void FPDF_CALLCONV
    697 FPDF_StringHandleRelease(FPDF_STRINGHANDLE stringHandle) {
    698   delete FromFPDFStringHandle(stringHandle);
    699 }
    700 
    701 FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
    702 FPDF_StringHandleAddString(FPDF_STRINGHANDLE stringHandle,
    703                            FPDF_BYTESTRING bsText,
    704                            FPDF_DWORD size) {
    705   if (!stringHandle || !bsText || size == 0)
    706     return false;
    707 
    708   FromFPDFStringHandle(stringHandle)->push_back(ByteString(bsText, size));
    709   return true;
    710 }
    711 #endif  // PDF_ENABLE_XFA
    712 
    713 FPDF_EXPORT void FPDF_CALLCONV
    714 FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
    715                                 int fieldType,
    716                                 unsigned long color) {
    717   CPDFSDK_InterForm* interForm = FormHandleToInterForm(hHandle);
    718   if (!interForm)
    719     return;
    720 
    721   Optional<FormFieldType> cast_input = IntToFormFieldType(fieldType);
    722   if (!cast_input)
    723     return;
    724 
    725   if (cast_input.value() == FormFieldType::kUnknown) {
    726     interForm->SetAllHighlightColors(color);
    727   } else {
    728     interForm->SetHighlightColor(color, cast_input.value());
    729   }
    730 }
    731 
    732 FPDF_EXPORT void FPDF_CALLCONV
    733 FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha) {
    734   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
    735     pInterForm->SetHighlightAlpha(alpha);
    736 }
    737 
    738 FPDF_EXPORT void FPDF_CALLCONV
    739 FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
    740   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
    741     pInterForm->RemoveAllHighLights();
    742 }
    743 
    744 FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page,
    745                                                     FPDF_FORMHANDLE hHandle) {
    746   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
    747     pPageView->SetValid(true);
    748 }
    749 
    750 FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page,
    751                                                       FPDF_FORMHANDLE hHandle) {
    752   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    753       HandleToCPDFSDKEnvironment(hHandle);
    754   if (!pFormFillEnv)
    755     return;
    756 
    757   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
    758   if (!pPage)
    759     return;
    760 
    761   CPDFSDK_PageView* pPageView = pFormFillEnv->GetPageView(pPage, false);
    762   if (pPageView) {
    763     pPageView->SetValid(false);
    764     // RemovePageView() takes care of the delete for us.
    765     pFormFillEnv->RemovePageView(pPage);
    766   }
    767 }
    768 
    769 FPDF_EXPORT void FPDF_CALLCONV
    770 FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
    771   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    772       HandleToCPDFSDKEnvironment(hHandle);
    773   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
    774     pFormFillEnv->ProcJavascriptFun();
    775 }
    776 
    777 FPDF_EXPORT void FPDF_CALLCONV
    778 FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
    779   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    780       HandleToCPDFSDKEnvironment(hHandle);
    781   if (pFormFillEnv && pFormFillEnv->IsJSInitiated())
    782     pFormFillEnv->ProcOpenAction();
    783 }
    784 
    785 FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
    786                                                       int aaType) {
    787   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    788       HandleToCPDFSDKEnvironment(hHandle);
    789   if (!pFormFillEnv)
    790     return;
    791 
    792   CPDF_Document* pDoc = pFormFillEnv->GetPDFDocument();
    793   const CPDF_Dictionary* pDict = pDoc->GetRoot();
    794   if (!pDict)
    795     return;
    796 
    797   CPDF_AAction aa(pDict->GetDictFor("AA"));
    798   auto type = static_cast<CPDF_AAction::AActionType>(aaType);
    799   if (aa.ActionExist(type)) {
    800     CPDF_Action action = aa.GetAction(type);
    801     CPDFSDK_ActionHandler* pActionHandler =
    802         HandleToCPDFSDKEnvironment(hHandle)->GetActionHandler();
    803     pActionHandler->DoAction_Document(action, type, pFormFillEnv);
    804   }
    805 }
    806 
    807 FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page,
    808                                                   FPDF_FORMHANDLE hHandle,
    809                                                   int aaType) {
    810   CPDFSDK_FormFillEnvironment* pFormFillEnv =
    811       HandleToCPDFSDKEnvironment(hHandle);
    812   if (!pFormFillEnv)
    813     return;
    814 
    815   UnderlyingPageType* pPage = UnderlyingFromFPDFPage(page);
    816   CPDF_Page* pPDFPage = CPDFPageFromFPDFPage(page);
    817   if (!pPDFPage)
    818     return;
    819 
    820   if (!pFormFillEnv->GetPageView(pPage, false))
    821     return;
    822 
    823   CPDFSDK_ActionHandler* pActionHandler = pFormFillEnv->GetActionHandler();
    824   CPDF_Dictionary* pPageDict = pPDFPage->m_pFormDict.Get();
    825   CPDF_AAction aa(pPageDict->GetDictFor("AA"));
    826   CPDF_AAction::AActionType type = aaType == FPDFPAGE_AACTION_OPEN
    827                                        ? CPDF_AAction::OpenPage
    828                                        : CPDF_AAction::ClosePage;
    829   if (aa.ActionExist(type)) {
    830     CPDF_Action action = aa.GetAction(type);
    831     pActionHandler->DoAction_Page(action, type, pFormFillEnv);
    832   }
    833 }
    834