Index: fpdfsdk/cpdfsdk_formfillenvironment.cpp |
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp |
index 7b41ea148c04413c53fdeb0825adcbd19501f407..2beaadeb1a9e5d59349eb7503f693159a02b5526 100644 |
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp |
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp |
@@ -8,8 +8,12 @@ |
#include <memory> |
+#include "core/fpdfapi/parser/cpdf_array.h" |
+#include "core/fpdfdoc/cpdf_docjsactions.h" |
#include "fpdfsdk/cpdfsdk_annothandlermgr.h" |
-#include "fpdfsdk/cpdfsdk_document.h" |
+#include "fpdfsdk/cpdfsdk_interform.h" |
+#include "fpdfsdk/cpdfsdk_pageview.h" |
+#include "fpdfsdk/cpdfsdk_widget.h" |
#include "fpdfsdk/formfiller/cffl_interactiveformfiller.h" |
#include "fpdfsdk/fsdk_actionhandler.h" |
#include "fpdfsdk/javascript/ijs_runtime.h" |
@@ -34,11 +38,19 @@ CPDFSDK_FormFillEnvironment::CPDFSDK_FormFillEnvironment( |
UnderlyingDocumentType* pDoc, |
FPDF_FORMFILLINFO* pFFinfo) |
: m_pInfo(pFFinfo), |
- m_pSDKDoc(new CPDFSDK_Document(pDoc, this)), |
m_pUnderlyingDoc(pDoc), |
- m_pSysHandler(new CFX_SystemHandler(this)) {} |
+ m_pSysHandler(new CFX_SystemHandler(this)), |
+ m_bChangeMask(FALSE), |
+ m_bBeingDestroyed(FALSE) {} |
CPDFSDK_FormFillEnvironment::~CPDFSDK_FormFillEnvironment() { |
+ m_bBeingDestroyed = TRUE; |
+ |
+ ClearAllFocusedAnnots(); |
+ for (auto& it : m_pageMap) |
Tom Sepez
2016/10/12 18:52:59
nit: map of unique_ptrs (keep .clear() if order im
dsinclair
2016/10/12 19:44:29
Done.
|
+ delete it.second; |
+ m_pageMap.clear(); |
+ |
// |m_pAnnotHandlerMgr| will try to access |m_pFormFiller| |
// when it cleans up. So, we must make sure it is cleaned up before |
// |m_pFormFiller|. |
@@ -562,3 +574,202 @@ void CPDFSDK_FormFillEnvironment::PageEvent(int iPageCount, |
m_pInfo->FFI_PageEvent(m_pInfo, iPageCount, dwEventType); |
} |
#endif // PDF_ENABLE_XFA |
+ |
+void CPDFSDK_FormFillEnvironment::ClearAllFocusedAnnots() { |
+ for (auto& it : m_pageMap) { |
+ if (it.second->IsValidSDKAnnot(GetFocusAnnot())) |
+ KillFocusAnnot(0); |
+ } |
+} |
+ |
+CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView( |
+ UnderlyingPageType* pUnderlyingPage, |
+ bool ReNew) { |
Tom Sepez
2016/10/12 18:52:59
nit: |renew| or |bRenew| (has bugged me for years
dsinclair
2016/10/12 19:44:29
Done.
|
+ auto it = m_pageMap.find(pUnderlyingPage); |
+ if (it != m_pageMap.end()) |
+ return it->second; |
+ |
+ if (!ReNew) |
+ return nullptr; |
+ |
+ CPDFSDK_PageView* pPageView = new CPDFSDK_PageView(this, pUnderlyingPage); |
+ m_pageMap[pUnderlyingPage] = pPageView; |
+ // Delay to load all the annotations, to avoid endless loop. |
+ pPageView->LoadFXAnnots(); |
+ return pPageView; |
+} |
+ |
+CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetCurrentView() { |
+ UnderlyingPageType* pPage = |
+ UnderlyingFromFPDFPage(GetCurrentPage(m_pUnderlyingDoc)); |
+ return pPage ? GetPageView(pPage, true) : nullptr; |
+} |
+ |
+CPDFSDK_PageView* CPDFSDK_FormFillEnvironment::GetPageView(int nIndex) { |
+ UnderlyingPageType* pTempPage = |
+ UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); |
+ if (!pTempPage) |
+ return nullptr; |
+ |
+ auto it = m_pageMap.find(pTempPage); |
+ return it != m_pageMap.end() ? it->second : nullptr; |
+} |
+ |
+void CPDFSDK_FormFillEnvironment::ProcJavascriptFun() { |
+ CPDF_Document* pPDFDoc = GetPDFDocument(); |
+ CPDF_DocJSActions docJS(pPDFDoc); |
+ int iCount = docJS.CountJSActions(); |
+ if (iCount < 1) |
+ return; |
+ for (int i = 0; i < iCount; i++) { |
+ CFX_ByteString csJSName; |
+ CPDF_Action jsAction = docJS.GetJSAction(i, csJSName); |
+ if (GetActionHander()) { |
+ GetActionHander()->DoAction_JavaScript( |
+ jsAction, CFX_WideString::FromLocal(csJSName.AsStringC()), this); |
+ } |
+ } |
+} |
+ |
+FX_BOOL CPDFSDK_FormFillEnvironment::ProcOpenAction() { |
+ if (!m_pUnderlyingDoc) |
+ return FALSE; |
+ |
+ CPDF_Dictionary* pRoot = GetPDFDocument()->GetRoot(); |
+ if (!pRoot) |
+ return FALSE; |
+ |
+ CPDF_Object* pOpenAction = pRoot->GetDictFor("OpenAction"); |
+ if (!pOpenAction) |
+ pOpenAction = pRoot->GetArrayFor("OpenAction"); |
+ |
+ if (!pOpenAction) |
+ return FALSE; |
+ |
+ if (pOpenAction->IsArray()) |
+ return TRUE; |
+ |
+ if (CPDF_Dictionary* pDict = pOpenAction->AsDictionary()) { |
+ CPDF_Action action(pDict); |
+ if (GetActionHander()) |
+ GetActionHander()->DoAction_DocOpen(action, this); |
+ return TRUE; |
+ } |
+ return FALSE; |
+} |
+ |
+void CPDFSDK_FormFillEnvironment::RemovePageView( |
+ UnderlyingPageType* pUnderlyingPage) { |
+ auto it = m_pageMap.find(pUnderlyingPage); |
+ if (it == m_pageMap.end()) |
+ return; |
+ |
+ CPDFSDK_PageView* pPageView = it->second; |
+ if (pPageView->IsLocked() || pPageView->IsBeingDestroyed()) |
+ return; |
+ |
+ // Mark the page view so we do not come into |RemovePageView| a second |
+ // time while we're in the process of removing. |
+ pPageView->SetBeingDestroyed(); |
+ |
+ // This must happen before we remove |pPageView| from the map because |
+ // |KillFocusAnnot| can call into the |GetPage| method which will |
+ // look for this page view in the map, if it doesn't find it a new one will |
+ // be created. We then have two page views pointing to the same page and |
+ // bad things happen. |
+ if (pPageView->IsValidSDKAnnot(GetFocusAnnot())) |
+ KillFocusAnnot(0); |
+ |
+ // Remove the page from the map to make sure we don't accidentally attempt |
+ // to use the |pPageView| while we're cleaning it up. |
+ m_pageMap.erase(it); |
+ |
+ delete pPageView; |
+} |
+ |
+UnderlyingPageType* CPDFSDK_FormFillEnvironment::GetPage(int nIndex) { |
+ return UnderlyingFromFPDFPage(GetPage(m_pUnderlyingDoc, nIndex)); |
+} |
+ |
+CPDFSDK_InterForm* CPDFSDK_FormFillEnvironment::GetInterForm() { |
+ if (!m_pInterForm) |
+ m_pInterForm = pdfium::MakeUnique<CPDFSDK_InterForm>(this); |
+ return m_pInterForm.get(); |
+} |
+ |
+void CPDFSDK_FormFillEnvironment::UpdateAllViews(CPDFSDK_PageView* pSender, |
+ CPDFSDK_Annot* pAnnot) { |
+ for (const auto& it : m_pageMap) { |
+ CPDFSDK_PageView* pPageView = it.second; |
+ if (pPageView != pSender) |
+ pPageView->UpdateView(pAnnot); |
+ } |
+} |
+ |
+FX_BOOL CPDFSDK_FormFillEnvironment::SetFocusAnnot( |
+ CPDFSDK_Annot::ObservedPtr* pAnnot) { |
+ if (m_bBeingDestroyed) |
+ return FALSE; |
+ if (m_pFocusAnnot == *pAnnot) |
+ return TRUE; |
+ if (m_pFocusAnnot && !KillFocusAnnot(0)) |
+ return FALSE; |
+ if (!*pAnnot) |
+ return FALSE; |
+ |
+#ifdef PDF_ENABLE_XFA |
+ CPDFSDK_Annot::ObservedPtr pLastFocusAnnot(m_pFocusAnnot.Get()); |
+#endif // PDF_ENABLE_XFA |
+ CPDFSDK_PageView* pPageView = (*pAnnot)->GetPageView(); |
+ if (pPageView && pPageView->IsValid()) { |
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); |
+ if (!m_pFocusAnnot) { |
+#ifdef PDF_ENABLE_XFA |
+ if (!pAnnotHandler->Annot_OnChangeFocus(pAnnot, &pLastFocusAnnot)) |
+ return FALSE; |
+#endif // PDF_ENABLE_XFA |
+ if (!pAnnotHandler->Annot_OnSetFocus(pAnnot, 0)) |
+ return FALSE; |
+ if (!m_pFocusAnnot) { |
+ m_pFocusAnnot.Reset(pAnnot->Get()); |
+ return TRUE; |
+ } |
+ } |
+ } |
+ return FALSE; |
+} |
+ |
+FX_BOOL CPDFSDK_FormFillEnvironment::KillFocusAnnot(uint32_t nFlag) { |
+ if (m_pFocusAnnot) { |
+ CPDFSDK_AnnotHandlerMgr* pAnnotHandler = GetAnnotHandlerMgr(); |
+ CPDFSDK_Annot::ObservedPtr pFocusAnnot(m_pFocusAnnot.Get()); |
+ m_pFocusAnnot.Reset(); |
+ |
+#ifdef PDF_ENABLE_XFA |
+ CPDFSDK_Annot::ObservedPtr pNull; |
+ if (!pAnnotHandler->Annot_OnChangeFocus(&pNull, &pFocusAnnot)) |
+ return FALSE; |
+#endif // PDF_ENABLE_XFA |
+ |
+ if (pAnnotHandler->Annot_OnKillFocus(&pFocusAnnot, nFlag)) { |
+ if (pFocusAnnot->GetAnnotSubtype() == CPDF_Annot::Subtype::WIDGET) { |
+ CPDFSDK_Widget* pWidget = |
+ static_cast<CPDFSDK_Widget*>(pFocusAnnot.Get()); |
+ int nFieldType = pWidget->GetFieldType(); |
+ if (FIELDTYPE_TEXTFIELD == nFieldType || |
+ FIELDTYPE_COMBOBOX == nFieldType) { |
+ OnSetFieldInputFocus(nullptr, 0, FALSE); |
+ } |
+ } |
+ if (!m_pFocusAnnot) |
+ return TRUE; |
+ } else { |
+ m_pFocusAnnot.Reset(pFocusAnnot.Get()); |
+ } |
+ } |
+ return FALSE; |
+} |
+ |
+FX_BOOL CPDFSDK_FormFillEnvironment::GetPermissions(int nFlag) { |
+ return GetPDFDocument()->GetUserPermissions() & nFlag; |
+} |