| // Copyright 2016 The PDFium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h" |
| |
| #include <utility> |
| |
| #include "constants/catalog.h" |
| #include "core/fpdfapi/parser/cpdf_array.h" |
| #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| #include "core/fpdfapi/parser/cpdf_stream.h" |
| #include "core/fpdfapi/parser/cpdf_stream_acc.h" |
| #include "core/fpdfapi/parser/cpdf_string.h" |
| #include "core/fxcrt/check.h" |
| #include "core/fxcrt/retain_ptr.h" |
| #include "fpdfsdk/cpdfsdk_formfillenvironment.h" |
| #include "fpdfsdk/cpdfsdk_helpers.h" |
| #include "fpdfsdk/cpdfsdk_interactiveform.h" |
| #include "fpdfsdk/cpdfsdk_pageview.h" |
| #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" |
| #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h" |
| #include "xfa/fxfa/cxfa_ffdocview.h" |
| #include "xfa/fxfa/cxfa_ffwidget.h" |
| #include "xfa/fxfa/cxfa_ffwidgethandler.h" |
| #include "xfa/fxfa/cxfa_readynodeiterator.h" |
| #include "xfa/fxfa/parser/cxfa_node.h" |
| #include "xfa/fxfa/parser/cxfa_submit.h" |
| |
| #define IDS_XFA_Validate_Input \ |
| "At least one required field was empty. Please fill in the required " \ |
| "fields\r\n(highlighted) before continuing." |
| |
| // Although there isn't direct casting between these types at present, |
| // keep the internal and exernal types in sync. |
| static_assert(FXFA_PAGEVIEWEVENT_POSTADDED == |
| static_cast<int>(CXFA_FFDoc::PageViewEvent::kPostAdded), |
| "kPostAdded mismatch"); |
| static_assert(FXFA_PAGEVIEWEVENT_POSTREMOVED == |
| static_cast<int>(CXFA_FFDoc::PageViewEvent::kPostRemoved), |
| "kPostRemoved mismatch"); |
| |
| CPDFXFA_DocEnvironment::CPDFXFA_DocEnvironment(CPDFXFA_Context* context) |
| : context_(context) { |
| DCHECK(context_); |
| } |
| |
| CPDFXFA_DocEnvironment::~CPDFXFA_DocEnvironment() = default; |
| |
| void CPDFXFA_DocEnvironment::SetChangeMark(CXFA_FFDoc* hDoc) { |
| if (hDoc == context_->GetXFADoc() && context_->GetFormFillEnv()) { |
| context_->GetFormFillEnv()->SetChangeMark(); |
| } |
| } |
| |
| void CPDFXFA_DocEnvironment::InvalidateRect(CXFA_FFPageView* pPageView, |
| const CFX_RectF& rt) { |
| if (!context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return; |
| } |
| |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pPage = context_->GetXFAPage(pPageView); |
| if (!pPage) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| pFormFillEnv->Invalidate(pPage.Get(), rt.ToFloatRect().ToFxRect()); |
| } |
| |
| void CPDFXFA_DocEnvironment::DisplayCaret(CXFA_FFWidget* hWidget, |
| bool bVisible, |
| const CFX_RectF* pRtAnchor) { |
| if (!hWidget || !pRtAnchor || !context_->GetXFADoc() || |
| !context_->GetFormFillEnv() || !context_->GetXFADocView()) { |
| return; |
| } |
| |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return; |
| } |
| |
| CXFA_FFWidgetHandler* pWidgetHandler = |
| context_->GetXFADocView()->GetWidgetHandler(); |
| if (!pWidgetHandler) { |
| return; |
| } |
| |
| CXFA_FFPageView* pPageView = hWidget->GetPageView(); |
| if (!pPageView) { |
| return; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pPage = context_->GetXFAPage(pPageView); |
| if (!pPage) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| CFX_FloatRect rcCaret = pRtAnchor->ToFloatRect(); |
| pFormFillEnv->DisplayCaret(pPage.Get(), bVisible, rcCaret.left, rcCaret.top, |
| rcCaret.right, rcCaret.bottom); |
| } |
| |
| bool CPDFXFA_DocEnvironment::GetPopupPos(CXFA_FFWidget* hWidget, |
| float fMinPopup, |
| float fMaxPopup, |
| const CFX_RectF& rtAnchor, |
| CFX_RectF* pPopupRect) { |
| if (!hWidget) { |
| return false; |
| } |
| |
| CXFA_FFPageView* pXFAPageView = hWidget->GetPageView(); |
| if (!pXFAPageView) { |
| return false; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pPage = context_->GetXFAPage(pXFAPageView); |
| if (!pPage) { |
| return false; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return false; |
| } |
| |
| FS_RECTF page_view_rect = pFormFillEnv->GetPageViewRect(pPage.Get()); |
| int nRotate = hWidget->GetNode()->GetRotate(); |
| |
| int space_available_below_anchor; |
| int space_available_above_anchor; |
| switch (nRotate) { |
| case 0: |
| default: { |
| space_available_below_anchor = |
| static_cast<int>(page_view_rect.bottom - rtAnchor.bottom()); |
| space_available_above_anchor = |
| static_cast<int>(rtAnchor.top - page_view_rect.top); |
| |
| if (rtAnchor.left < page_view_rect.left) { |
| pPopupRect->left += page_view_rect.left - rtAnchor.left; |
| } |
| if (rtAnchor.right() > page_view_rect.right) { |
| pPopupRect->left -= rtAnchor.right() - page_view_rect.right; |
| } |
| break; |
| } |
| case 90: { |
| space_available_below_anchor = |
| static_cast<int>(page_view_rect.right - rtAnchor.right()); |
| space_available_above_anchor = |
| static_cast<int>(rtAnchor.left - page_view_rect.left); |
| |
| if (rtAnchor.bottom() > page_view_rect.bottom) { |
| pPopupRect->left += rtAnchor.bottom() - page_view_rect.bottom; |
| } |
| if (rtAnchor.top < page_view_rect.top) { |
| pPopupRect->left -= page_view_rect.top - rtAnchor.top; |
| } |
| break; |
| } |
| case 180: { |
| space_available_below_anchor = |
| static_cast<int>(rtAnchor.top - page_view_rect.top); |
| space_available_above_anchor = |
| static_cast<int>(page_view_rect.bottom - rtAnchor.bottom()); |
| |
| if (rtAnchor.right() > page_view_rect.right) { |
| pPopupRect->left += rtAnchor.right() - page_view_rect.right; |
| } |
| if (rtAnchor.left < page_view_rect.left) { |
| pPopupRect->left -= page_view_rect.left - rtAnchor.left; |
| } |
| break; |
| } |
| case 270: { |
| space_available_below_anchor = |
| static_cast<int>(rtAnchor.left - page_view_rect.left); |
| space_available_above_anchor = |
| static_cast<int>(page_view_rect.right - rtAnchor.right()); |
| |
| if (rtAnchor.top < page_view_rect.top) { |
| pPopupRect->left += page_view_rect.top - rtAnchor.top; |
| } |
| if (rtAnchor.bottom() > page_view_rect.bottom) { |
| pPopupRect->left -= rtAnchor.bottom() - page_view_rect.bottom; |
| } |
| break; |
| } |
| } |
| |
| // If there is no space on either side, the popup can't be rendered. |
| if (space_available_below_anchor <= 0 && space_available_above_anchor <= 0) { |
| return false; |
| } |
| |
| // Determine whether to draw above or below the anchor. |
| bool draw_below_anchor; |
| if (space_available_below_anchor <= 0) { |
| draw_below_anchor = false; |
| } else if (space_available_above_anchor <= 0) { |
| draw_below_anchor = true; |
| } else if (space_available_below_anchor > space_available_above_anchor) { |
| draw_below_anchor = true; |
| } else { |
| draw_below_anchor = false; |
| } |
| |
| int space_available = (draw_below_anchor ? space_available_below_anchor |
| : space_available_above_anchor); |
| |
| // Set the popup height and y position according to what was decided above. |
| float popup_height; |
| if (space_available < fMinPopup) { |
| popup_height = fMinPopup; |
| } else if (space_available > fMaxPopup) { |
| popup_height = fMaxPopup; |
| } else { |
| popup_height = static_cast<float>(space_available); |
| } |
| |
| switch (nRotate) { |
| case 0: |
| case 180: { |
| if (draw_below_anchor) { |
| pPopupRect->top = rtAnchor.height; |
| } else { |
| pPopupRect->top = -popup_height; |
| } |
| break; |
| } |
| case 90: |
| case 270: { |
| if (draw_below_anchor) { |
| pPopupRect->top = rtAnchor.width; |
| } else { |
| pPopupRect->top = -popup_height; |
| } |
| break; |
| } |
| default: |
| break; |
| } |
| |
| pPopupRect->height = popup_height; |
| return true; |
| } |
| |
| bool CPDFXFA_DocEnvironment::PopupMenu(CXFA_FFWidget* hWidget, |
| const CFX_PointF& ptPopup) { |
| if (!hWidget) { |
| return false; |
| } |
| |
| CXFA_FFPageView* pXFAPageView = hWidget->GetPageView(); |
| if (!pXFAPageView) { |
| return false; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pPage = context_->GetXFAPage(pXFAPageView); |
| if (!pPage) { |
| return false; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return false; |
| } |
| |
| int menuFlag = 0; |
| if (hWidget->CanUndo()) { |
| menuFlag |= FXFA_MENU_UNDO; |
| } |
| if (hWidget->CanRedo()) { |
| menuFlag |= FXFA_MENU_REDO; |
| } |
| if (hWidget->CanPaste()) { |
| menuFlag |= FXFA_MENU_PASTE; |
| } |
| if (hWidget->CanCopy()) { |
| menuFlag |= FXFA_MENU_COPY; |
| } |
| if (hWidget->CanCut()) { |
| menuFlag |= FXFA_MENU_CUT; |
| } |
| if (hWidget->CanSelectAll()) { |
| menuFlag |= FXFA_MENU_SELECTALL; |
| } |
| |
| return pFormFillEnv->PopupMenu(pPage.Get(), menuFlag, ptPopup); |
| } |
| |
| void CPDFXFA_DocEnvironment::OnPageViewEvent(CXFA_FFPageView* pPageView, |
| CXFA_FFDoc::PageViewEvent eEvent) { |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| if (context_->GetLoadStatus() == CPDFXFA_Context::LoadStatus::kLoading || |
| context_->GetLoadStatus() == CPDFXFA_Context::LoadStatus::kClosing || |
| eEvent != CXFA_FFDoc::PageViewEvent::kStopLayout) { |
| return; |
| } |
| int nNewCount = context_->GetPageCount(); |
| if (nNewCount == context_->GetOriginalPageCount()) { |
| return; |
| } |
| |
| CXFA_FFDocView* pXFADocView = context_->GetXFADocView(); |
| if (!pXFADocView) { |
| return; |
| } |
| |
| for (int i = 0; i < context_->GetOriginalPageCount(); ++i) { |
| RetainPtr<CPDFXFA_Page> pPage = context_->GetXFAPage(i); |
| if (!pPage) { |
| continue; |
| } |
| |
| context_->GetFormFillEnv()->RemovePageView(pPage.Get()); |
| pPage->SetXFAPageViewIndex(i); |
| } |
| |
| int flag = (nNewCount < context_->GetOriginalPageCount()) |
| ? FXFA_PAGEVIEWEVENT_POSTREMOVED |
| : FXFA_PAGEVIEWEVENT_POSTADDED; |
| int count = abs(nNewCount - context_->GetOriginalPageCount()); |
| context_->SetOriginalPageCount(nNewCount); |
| pFormFillEnv->PageEvent(count, flag); |
| } |
| |
| void CPDFXFA_DocEnvironment::WidgetPostAdd(CXFA_FFWidget* hWidget) { |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return; |
| } |
| |
| CXFA_FFPageView* pPageView = hWidget->GetPageView(); |
| if (!pPageView) { |
| return; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pXFAPage = context_->GetXFAPage(pPageView); |
| if (!pXFAPage) { |
| return; |
| } |
| |
| auto* formfill = context_->GetFormFillEnv(); |
| formfill->GetOrCreatePageView(pXFAPage.Get())->AddAnnotForFFWidget(hWidget); |
| } |
| |
| void CPDFXFA_DocEnvironment::WidgetPreRemove(CXFA_FFWidget* hWidget) { |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return; |
| } |
| |
| CXFA_FFPageView* pPageView = hWidget->GetPageView(); |
| if (!pPageView) { |
| return; |
| } |
| |
| RetainPtr<CPDFXFA_Page> pXFAPage = context_->GetXFAPage(pPageView); |
| if (!pXFAPage) { |
| return; |
| } |
| |
| CPDFSDK_PageView* pSdkPageView = |
| context_->GetFormFillEnv()->GetOrCreatePageView(pXFAPage.Get()); |
| pSdkPageView->DeleteAnnotForFFWidget(hWidget); |
| } |
| |
| int32_t CPDFXFA_DocEnvironment::CountPages(const CXFA_FFDoc* hDoc) const { |
| if (hDoc == context_->GetXFADoc() && context_->GetFormFillEnv()) { |
| return context_->GetPageCount(); |
| } |
| return 0; |
| } |
| |
| int32_t CPDFXFA_DocEnvironment::GetCurrentPage(const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return -1; |
| } |
| |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return -1; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| return pFormFillEnv ? pFormFillEnv->GetCurrentPageIndex() : -1; |
| } |
| |
| void CPDFXFA_DocEnvironment::SetCurrentPage(CXFA_FFDoc* hDoc, |
| int32_t iCurPage) { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv() || |
| !context_->ContainsExtensionForm() || iCurPage < 0 || |
| iCurPage >= context_->GetFormFillEnv()->GetPageCount()) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| pFormFillEnv->SetCurrentPage(iCurPage); |
| } |
| |
| bool CPDFXFA_DocEnvironment::IsCalculationsEnabled( |
| const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return false; |
| } |
| auto* pForm = context_->GetFormFillEnv()->GetInteractiveForm(); |
| return pForm->IsXfaCalculateEnabled(); |
| } |
| |
| void CPDFXFA_DocEnvironment::SetCalculationsEnabled(CXFA_FFDoc* hDoc, |
| bool bEnabled) { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return; |
| } |
| context_->GetFormFillEnv()->GetInteractiveForm()->XfaEnableCalculate( |
| bEnabled); |
| } |
| |
| WideString CPDFXFA_DocEnvironment::GetTitle(const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc()) { |
| return WideString(); |
| } |
| |
| CPDF_Document* pPDFDoc = context_->GetPDFDoc(); |
| if (!pPDFDoc) { |
| return WideString(); |
| } |
| |
| RetainPtr<const CPDF_Dictionary> pInfoDict = pPDFDoc->GetInfo(); |
| if (!pInfoDict) { |
| return WideString(); |
| } |
| |
| ByteString csTitle = pInfoDict->GetByteStringFor("Title"); |
| return WideString::FromDefANSI(csTitle.AsStringView()); |
| } |
| |
| void CPDFXFA_DocEnvironment::SetTitle(CXFA_FFDoc* hDoc, |
| const WideString& wsTitle) { |
| if (hDoc != context_->GetXFADoc()) { |
| return; |
| } |
| |
| CPDF_Document* pPDFDoc = context_->GetPDFDoc(); |
| if (!pPDFDoc) { |
| return; |
| } |
| |
| RetainPtr<CPDF_Dictionary> pInfoDict = pPDFDoc->GetInfo(); |
| if (pInfoDict) { |
| pInfoDict->SetNewFor<CPDF_String>("Title", wsTitle.AsStringView()); |
| } |
| } |
| |
| void CPDFXFA_DocEnvironment::ExportData(CXFA_FFDoc* hDoc, |
| const WideString& wsFilePath, |
| bool bXDP) { |
| if (hDoc != context_->GetXFADoc()) { |
| return; |
| } |
| |
| if (!context_->ContainsExtensionForm()) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| int fileType = bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML; |
| ByteString bs = wsFilePath.ToUTF16LE(); |
| if (wsFilePath.IsEmpty()) { |
| if (!pFormFillEnv->IsJSPlatformPresent()) { |
| return; |
| } |
| WideString filepath = pFormFillEnv->JS_fieldBrowse(); |
| bs = filepath.ToUTF16LE(); |
| } |
| |
| FPDF_FILEHANDLER* pFileHandler = pFormFillEnv->OpenFile( |
| bXDP ? FXFA_SAVEAS_XDP : FXFA_SAVEAS_XML, AsFPDFWideString(&bs), "wb"); |
| if (!pFileHandler) { |
| return; |
| } |
| |
| RetainPtr<IFX_SeekableStream> fileWrite = MakeSeekableStream(pFileHandler); |
| if (fileType == FXFA_SAVEAS_XML) { |
| fileWrite->WriteString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"); |
| CXFA_FFDoc* ffdoc = context_->GetXFADocView()->GetDoc(); |
| ffdoc->SavePackage( |
| ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Data)), fileWrite); |
| } else if (fileType == FXFA_SAVEAS_XDP) { |
| if (!context_->GetPDFDoc()) { |
| return; |
| } |
| |
| const CPDF_Dictionary* pRoot = context_->GetPDFDoc()->GetRoot(); |
| if (!pRoot) { |
| return; |
| } |
| |
| RetainPtr<const CPDF_Dictionary> pAcroForm = |
| pRoot->GetDictFor(pdfium::catalog::kAcroForm); |
| if (!pAcroForm) { |
| return; |
| } |
| |
| RetainPtr<const CPDF_Array> pArray = |
| ToArray(pAcroForm->GetObjectFor("XFA")); |
| if (!pArray) { |
| return; |
| } |
| |
| for (size_t i = 1; i < pArray->size(); i += 2) { |
| RetainPtr<const CPDF_Object> pPDFObj = pArray->GetObjectAt(i); |
| RetainPtr<const CPDF_Object> pPrePDFObj = pArray->GetObjectAt(i - 1); |
| if (!pPrePDFObj->IsString()) { |
| continue; |
| } |
| if (!pPDFObj->IsReference()) { |
| continue; |
| } |
| |
| RetainPtr<const CPDF_Stream> pStream = ToStream(pPDFObj->GetDirect()); |
| if (!pStream) { |
| continue; |
| } |
| if (pPrePDFObj->GetString() == "form") { |
| CXFA_FFDoc* ffdoc = context_->GetXFADocView()->GetDoc(); |
| ffdoc->SavePackage( |
| ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Form)), |
| fileWrite); |
| continue; |
| } |
| if (pPrePDFObj->GetString() == "datasets") { |
| CXFA_FFDoc* ffdoc = context_->GetXFADocView()->GetDoc(); |
| ffdoc->SavePackage( |
| ToNode(ffdoc->GetXFADoc()->GetXFAObject(XFA_HASHCODE_Datasets)), |
| fileWrite); |
| continue; |
| } |
| if (i == pArray->size() - 1) { |
| WideString wPath = WideString::FromUTF16LE(bs.unsigned_span()); |
| ByteString bPath = wPath.ToUTF8(); |
| static const char kFormat[] = |
| "\n<pdf href=\"%s\" xmlns=\"http://ns.adobe.com/xdp/pdf/\"/>"; |
| ByteString content = ByteString::Format(kFormat, bPath.c_str()); |
| fileWrite->WriteString(content.AsStringView()); |
| } |
| auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pStream)); |
| pAcc->LoadAllDataFiltered(); |
| fileWrite->WriteBlock(pAcc->GetSpan()); |
| } |
| } |
| fileWrite->Flush(); |
| } |
| |
| void CPDFXFA_DocEnvironment::GotoURL(CXFA_FFDoc* hDoc, |
| const WideString& wsURL) { |
| if (hDoc != context_->GetXFADoc()) { |
| return; |
| } |
| |
| if (context_->GetFormType() != FormType::kXFAFull) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| pFormFillEnv->GotoURL(wsURL); |
| } |
| |
| bool CPDFXFA_DocEnvironment::IsValidationsEnabled( |
| const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return false; |
| } |
| |
| auto* pForm = context_->GetFormFillEnv()->GetInteractiveForm(); |
| return pForm->IsXfaValidationsEnabled(); |
| } |
| |
| void CPDFXFA_DocEnvironment::SetValidationsEnabled(CXFA_FFDoc* hDoc, |
| bool bEnabled) { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return; |
| } |
| |
| context_->GetFormFillEnv()->GetInteractiveForm()->XfaSetValidationsEnabled( |
| bEnabled); |
| } |
| |
| void CPDFXFA_DocEnvironment::SetFocusWidget(CXFA_FFDoc* hDoc, |
| CXFA_FFWidget* hWidget) { |
| if (hDoc != context_->GetXFADoc()) { |
| return; |
| } |
| |
| if (!hWidget) { |
| ObservedPtr<CPDFSDK_Annot> pNull; |
| context_->GetFormFillEnv()->SetFocusAnnot(pNull); |
| return; |
| } |
| |
| int pageViewCount = context_->GetFormFillEnv()->GetPageViewCount(); |
| for (int i = 0; i < pageViewCount; i++) { |
| CPDFSDK_PageView* pPageView = |
| context_->GetFormFillEnv()->GetPageViewAtIndex(i); |
| if (!pPageView) { |
| continue; |
| } |
| |
| ObservedPtr<CPDFSDK_Annot> pAnnot(pPageView->GetAnnotForFFWidget(hWidget)); |
| if (pAnnot) { |
| context_->GetFormFillEnv()->SetFocusAnnot(pAnnot); |
| break; |
| } |
| } |
| } |
| |
| void CPDFXFA_DocEnvironment::Print(CXFA_FFDoc* hDoc, |
| int32_t nStartPage, |
| int32_t nEndPage, |
| Mask<XFA_PrintOpt> dwOptions) { |
| if (hDoc != context_->GetXFADoc()) { |
| return; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return; |
| } |
| |
| IPDF_JSPLATFORM* js_platform = pFormFillEnv->GetJSPlatform(); |
| if (!js_platform || !js_platform->Doc_print) { |
| return; |
| } |
| |
| js_platform->Doc_print(js_platform, !!(dwOptions & XFA_PrintOpt::kShowDialog), |
| nStartPage, nEndPage, |
| !!(dwOptions & XFA_PrintOpt::kCanCancel), |
| !!(dwOptions & XFA_PrintOpt::kShrinkPage), |
| !!(dwOptions & XFA_PrintOpt::kAsImage), |
| !!(dwOptions & XFA_PrintOpt::kReverseOrder), |
| !!(dwOptions & XFA_PrintOpt::kPrintAnnot)); |
| } |
| |
| FX_ARGB CPDFXFA_DocEnvironment::GetHighlightColor( |
| const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc() || !context_->GetFormFillEnv()) { |
| return 0; |
| } |
| |
| CPDFSDK_InteractiveForm* pForm = |
| context_->GetFormFillEnv()->GetInteractiveForm(); |
| return AlphaAndColorRefToArgb(pForm->GetHighlightAlpha(), |
| pForm->GetHighlightColor(FormFieldType::kXFA)); |
| } |
| |
| IJS_Runtime* CPDFXFA_DocEnvironment::GetIJSRuntime( |
| const CXFA_FFDoc* hDoc) const { |
| if (hDoc != context_->GetXFADoc()) { |
| return nullptr; |
| } |
| |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| return pFormFillEnv ? pFormFillEnv->GetIJSRuntime() : nullptr; |
| } |
| |
| CFX_XMLDocument* CPDFXFA_DocEnvironment::GetXMLDoc() const { |
| return context_->GetXMLDoc(); |
| } |
| |
| RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile( |
| CXFA_FFDoc* hDoc, |
| const WideString& wsLink) { |
| CPDFSDK_FormFillEnvironment* pFormFillEnv = context_->GetFormFillEnv(); |
| if (!pFormFillEnv) { |
| return nullptr; |
| } |
| |
| ByteString bs = wsLink.ToUTF16LE(); |
| FPDF_FILEHANDLER* pFileHandler = |
| pFormFillEnv->OpenFile(0, AsFPDFWideString(&bs), "rb"); |
| if (!pFileHandler) { |
| return nullptr; |
| } |
| |
| return MakeSeekableStream(pFileHandler); |
| } |