xref: /aosp_15_r20/external/pdfium/fpdfsdk/cpdfsdk_interactiveform.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2016 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_interactiveform.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <stdint.h>
10*3ac0a46fSAndroid Build Coastguard Worker 
11*3ac0a46fSAndroid Build Coastguard Worker #include <algorithm>
12*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
13*3ac0a46fSAndroid Build Coastguard Worker #include <sstream>
14*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
15*3ac0a46fSAndroid Build Coastguard Worker #include <vector>
16*3ac0a46fSAndroid Build Coastguard Worker 
17*3ac0a46fSAndroid Build Coastguard Worker #include "constants/annotation_flags.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_page.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cfdf_document.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_array.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_dictionary.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_document.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_stream.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_action.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_formcontrol.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfdoc/cpdf_interactiveform.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/autorestorer.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_string_wrappers.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_graphstatedata.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_path.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_annot.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_annotiterator.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_pageview.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_widget.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/formfiller/cffl_formfield.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/ijs_event_context.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/ijs_runtime.h"
40*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
41*3ac0a46fSAndroid Build Coastguard Worker 
42*3ac0a46fSAndroid Build Coastguard Worker namespace {
43*3ac0a46fSAndroid Build Coastguard Worker 
44*3ac0a46fSAndroid Build Coastguard Worker constexpr uint32_t kWhiteBGR = FXSYS_BGR(255, 255, 255);
45*3ac0a46fSAndroid Build Coastguard Worker 
IsFormFieldTypeComboOrText(FormFieldType fieldType)46*3ac0a46fSAndroid Build Coastguard Worker bool IsFormFieldTypeComboOrText(FormFieldType fieldType) {
47*3ac0a46fSAndroid Build Coastguard Worker   switch (fieldType) {
48*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kComboBox:
49*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kTextField:
50*3ac0a46fSAndroid Build Coastguard Worker       return true;
51*3ac0a46fSAndroid Build Coastguard Worker     default:
52*3ac0a46fSAndroid Build Coastguard Worker       return false;
53*3ac0a46fSAndroid Build Coastguard Worker   }
54*3ac0a46fSAndroid Build Coastguard Worker }
55*3ac0a46fSAndroid Build Coastguard Worker 
56*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
IsFormFieldTypeXFA(FormFieldType fieldType)57*3ac0a46fSAndroid Build Coastguard Worker bool IsFormFieldTypeXFA(FormFieldType fieldType) {
58*3ac0a46fSAndroid Build Coastguard Worker   switch (fieldType) {
59*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA:
60*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_CheckBox:
61*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_ComboBox:
62*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_ImageField:
63*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_ListBox:
64*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_PushButton:
65*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_Signature:
66*3ac0a46fSAndroid Build Coastguard Worker     case FormFieldType::kXFA_TextField:
67*3ac0a46fSAndroid Build Coastguard Worker       return true;
68*3ac0a46fSAndroid Build Coastguard Worker     default:
69*3ac0a46fSAndroid Build Coastguard Worker       return false;
70*3ac0a46fSAndroid Build Coastguard Worker   }
71*3ac0a46fSAndroid Build Coastguard Worker }
72*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
73*3ac0a46fSAndroid Build Coastguard Worker 
FDFToURLEncodedData(ByteString buffer)74*3ac0a46fSAndroid Build Coastguard Worker ByteString FDFToURLEncodedData(ByteString buffer) {
75*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFDF_Document> pFDF =
76*3ac0a46fSAndroid Build Coastguard Worker       CFDF_Document::ParseMemory(buffer.raw_span());
77*3ac0a46fSAndroid Build Coastguard Worker   if (!pFDF)
78*3ac0a46fSAndroid Build Coastguard Worker     return buffer;
79*3ac0a46fSAndroid Build Coastguard Worker 
80*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Dictionary> pMainDict =
81*3ac0a46fSAndroid Build Coastguard Worker       pFDF->GetRoot()->GetDictFor("FDF");
82*3ac0a46fSAndroid Build Coastguard Worker   if (!pMainDict)
83*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
84*3ac0a46fSAndroid Build Coastguard Worker 
85*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Array> pFields = pMainDict->GetArrayFor("Fields");
86*3ac0a46fSAndroid Build Coastguard Worker   if (!pFields)
87*3ac0a46fSAndroid Build Coastguard Worker     return ByteString();
88*3ac0a46fSAndroid Build Coastguard Worker 
89*3ac0a46fSAndroid Build Coastguard Worker   fxcrt::ostringstream encoded_data;
90*3ac0a46fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < pFields->size(); i++) {
91*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<const CPDF_Dictionary> pField = pFields->GetDictAt(i);
92*3ac0a46fSAndroid Build Coastguard Worker     if (!pField)
93*3ac0a46fSAndroid Build Coastguard Worker       continue;
94*3ac0a46fSAndroid Build Coastguard Worker     WideString name = pField->GetUnicodeTextFor("T");
95*3ac0a46fSAndroid Build Coastguard Worker     ByteString name_b = name.ToDefANSI();
96*3ac0a46fSAndroid Build Coastguard Worker     ByteString csBValue = pField->GetByteStringFor("V");
97*3ac0a46fSAndroid Build Coastguard Worker     WideString csWValue = PDF_DecodeText(csBValue.raw_span());
98*3ac0a46fSAndroid Build Coastguard Worker     ByteString csValue_b = csWValue.ToDefANSI();
99*3ac0a46fSAndroid Build Coastguard Worker     encoded_data << name_b << "=" << csValue_b;
100*3ac0a46fSAndroid Build Coastguard Worker     if (i != pFields->size() - 1)
101*3ac0a46fSAndroid Build Coastguard Worker       encoded_data << "&";
102*3ac0a46fSAndroid Build Coastguard Worker   }
103*3ac0a46fSAndroid Build Coastguard Worker 
104*3ac0a46fSAndroid Build Coastguard Worker   return ByteString(encoded_data);
105*3ac0a46fSAndroid Build Coastguard Worker }
106*3ac0a46fSAndroid Build Coastguard Worker 
107*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
108*3ac0a46fSAndroid Build Coastguard Worker 
CPDFSDK_InteractiveForm(CPDFSDK_FormFillEnvironment * pFormFillEnv)109*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_InteractiveForm::CPDFSDK_InteractiveForm(
110*3ac0a46fSAndroid Build Coastguard Worker     CPDFSDK_FormFillEnvironment* pFormFillEnv)
111*3ac0a46fSAndroid Build Coastguard Worker     : m_pFormFillEnv(pFormFillEnv),
112*3ac0a46fSAndroid Build Coastguard Worker       m_pInteractiveForm(std::make_unique<CPDF_InteractiveForm>(
113*3ac0a46fSAndroid Build Coastguard Worker           m_pFormFillEnv->GetPDFDocument())) {
114*3ac0a46fSAndroid Build Coastguard Worker   m_pInteractiveForm->SetNotifierIface(this);
115*3ac0a46fSAndroid Build Coastguard Worker   RemoveAllHighLights();
116*3ac0a46fSAndroid Build Coastguard Worker }
117*3ac0a46fSAndroid Build Coastguard Worker 
118*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_InteractiveForm::~CPDFSDK_InteractiveForm() = default;
119*3ac0a46fSAndroid Build Coastguard Worker 
GetWidget(CPDF_FormControl * pControl) const120*3ac0a46fSAndroid Build Coastguard Worker CPDFSDK_Widget* CPDFSDK_InteractiveForm::GetWidget(
121*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl* pControl) const {
122*3ac0a46fSAndroid Build Coastguard Worker   if (!pControl)
123*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
124*3ac0a46fSAndroid Build Coastguard Worker 
125*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_Widget* pWidget = nullptr;
126*3ac0a46fSAndroid Build Coastguard Worker   const auto it = m_Map.find(pControl);
127*3ac0a46fSAndroid Build Coastguard Worker   if (it != m_Map.end())
128*3ac0a46fSAndroid Build Coastguard Worker     pWidget = it->second;
129*3ac0a46fSAndroid Build Coastguard Worker   if (pWidget)
130*3ac0a46fSAndroid Build Coastguard Worker     return pWidget;
131*3ac0a46fSAndroid Build Coastguard Worker 
132*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
133*3ac0a46fSAndroid Build Coastguard Worker   CPDFSDK_PageView* pPage = nullptr;
134*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Dictionary> pControlDict = pControl->GetWidgetDict();
135*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<const CPDF_Dictionary> pPageDict = pControlDict->GetDictFor("P");
136*3ac0a46fSAndroid Build Coastguard Worker   if (pPageDict) {
137*3ac0a46fSAndroid Build Coastguard Worker     int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum());
138*3ac0a46fSAndroid Build Coastguard Worker     if (nPageIndex >= 0)
139*3ac0a46fSAndroid Build Coastguard Worker       pPage = m_pFormFillEnv->GetPageViewAtIndex(nPageIndex);
140*3ac0a46fSAndroid Build Coastguard Worker   }
141*3ac0a46fSAndroid Build Coastguard Worker 
142*3ac0a46fSAndroid Build Coastguard Worker   if (!pPage) {
143*3ac0a46fSAndroid Build Coastguard Worker     int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict);
144*3ac0a46fSAndroid Build Coastguard Worker     if (nPageIndex >= 0)
145*3ac0a46fSAndroid Build Coastguard Worker       pPage = m_pFormFillEnv->GetPageViewAtIndex(nPageIndex);
146*3ac0a46fSAndroid Build Coastguard Worker   }
147*3ac0a46fSAndroid Build Coastguard Worker 
148*3ac0a46fSAndroid Build Coastguard Worker   return pPage ? ToCPDFSDKWidget(pPage->GetAnnotByDict(pControlDict)) : nullptr;
149*3ac0a46fSAndroid Build Coastguard Worker }
150*3ac0a46fSAndroid Build Coastguard Worker 
GetWidgets(const WideString & sFieldName,std::vector<ObservedPtr<CPDFSDK_Widget>> * widgets) const151*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::GetWidgets(
152*3ac0a46fSAndroid Build Coastguard Worker     const WideString& sFieldName,
153*3ac0a46fSAndroid Build Coastguard Worker     std::vector<ObservedPtr<CPDFSDK_Widget>>* widgets) const {
154*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0, sz = m_pInteractiveForm->CountFields(sFieldName); i < sz;
155*3ac0a46fSAndroid Build Coastguard Worker        ++i) {
156*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pFormField = m_pInteractiveForm->GetField(i, sFieldName);
157*3ac0a46fSAndroid Build Coastguard Worker     DCHECK(pFormField);
158*3ac0a46fSAndroid Build Coastguard Worker     GetWidgets(pFormField, widgets);
159*3ac0a46fSAndroid Build Coastguard Worker   }
160*3ac0a46fSAndroid Build Coastguard Worker }
161*3ac0a46fSAndroid Build Coastguard Worker 
GetWidgets(CPDF_FormField * pField,std::vector<ObservedPtr<CPDFSDK_Widget>> * widgets) const162*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::GetWidgets(
163*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pField,
164*3ac0a46fSAndroid Build Coastguard Worker     std::vector<ObservedPtr<CPDFSDK_Widget>>* widgets) const {
165*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
166*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl* pFormCtrl = pField->GetControl(i);
167*3ac0a46fSAndroid Build Coastguard Worker     DCHECK(pFormCtrl);
168*3ac0a46fSAndroid Build Coastguard Worker     CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
169*3ac0a46fSAndroid Build Coastguard Worker     if (pWidget)
170*3ac0a46fSAndroid Build Coastguard Worker       widgets->emplace_back(pWidget);
171*3ac0a46fSAndroid Build Coastguard Worker   }
172*3ac0a46fSAndroid Build Coastguard Worker }
173*3ac0a46fSAndroid Build Coastguard Worker 
GetPageIndexByAnnotDict(CPDF_Document * pDocument,const CPDF_Dictionary * pAnnotDict) const174*3ac0a46fSAndroid Build Coastguard Worker int CPDFSDK_InteractiveForm::GetPageIndexByAnnotDict(
175*3ac0a46fSAndroid Build Coastguard Worker     CPDF_Document* pDocument,
176*3ac0a46fSAndroid Build Coastguard Worker     const CPDF_Dictionary* pAnnotDict) const {
177*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(pAnnotDict);
178*3ac0a46fSAndroid Build Coastguard Worker 
179*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) {
180*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<const CPDF_Dictionary> pPageDict =
181*3ac0a46fSAndroid Build Coastguard Worker         pDocument->GetPageDictionary(i);
182*3ac0a46fSAndroid Build Coastguard Worker     if (!pPageDict)
183*3ac0a46fSAndroid Build Coastguard Worker       continue;
184*3ac0a46fSAndroid Build Coastguard Worker 
185*3ac0a46fSAndroid Build Coastguard Worker     RetainPtr<const CPDF_Array> pAnnots = pPageDict->GetArrayFor("Annots");
186*3ac0a46fSAndroid Build Coastguard Worker     if (!pAnnots)
187*3ac0a46fSAndroid Build Coastguard Worker       continue;
188*3ac0a46fSAndroid Build Coastguard Worker 
189*3ac0a46fSAndroid Build Coastguard Worker     for (size_t j = 0, jsz = pAnnots->size(); j < jsz; j++) {
190*3ac0a46fSAndroid Build Coastguard Worker       RetainPtr<const CPDF_Object> pDict = pAnnots->GetDirectObjectAt(j);
191*3ac0a46fSAndroid Build Coastguard Worker       if (pAnnotDict == pDict)
192*3ac0a46fSAndroid Build Coastguard Worker         return i;
193*3ac0a46fSAndroid Build Coastguard Worker     }
194*3ac0a46fSAndroid Build Coastguard Worker   }
195*3ac0a46fSAndroid Build Coastguard Worker   return -1;
196*3ac0a46fSAndroid Build Coastguard Worker }
197*3ac0a46fSAndroid Build Coastguard Worker 
AddMap(CPDF_FormControl * pControl,CPDFSDK_Widget * pWidget)198*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::AddMap(CPDF_FormControl* pControl,
199*3ac0a46fSAndroid Build Coastguard Worker                                      CPDFSDK_Widget* pWidget) {
200*3ac0a46fSAndroid Build Coastguard Worker   m_Map[pdfium::WrapUnowned(pControl)] = pWidget;
201*3ac0a46fSAndroid Build Coastguard Worker }
202*3ac0a46fSAndroid Build Coastguard Worker 
RemoveMap(CPDF_FormControl * pControl)203*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::RemoveMap(CPDF_FormControl* pControl) {
204*3ac0a46fSAndroid Build Coastguard Worker   auto it = m_Map.find(pControl);
205*3ac0a46fSAndroid Build Coastguard Worker   if (it != m_Map.end())
206*3ac0a46fSAndroid Build Coastguard Worker     m_Map.erase(it);
207*3ac0a46fSAndroid Build Coastguard Worker }
208*3ac0a46fSAndroid Build Coastguard Worker 
EnableCalculate(bool bEnabled)209*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::EnableCalculate(bool bEnabled) {
210*3ac0a46fSAndroid Build Coastguard Worker   m_bCalculate = bEnabled;
211*3ac0a46fSAndroid Build Coastguard Worker }
212*3ac0a46fSAndroid Build Coastguard Worker 
IsCalculateEnabled() const213*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::IsCalculateEnabled() const {
214*3ac0a46fSAndroid Build Coastguard Worker   return m_bCalculate;
215*3ac0a46fSAndroid Build Coastguard Worker }
216*3ac0a46fSAndroid Build Coastguard Worker 
217*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
XfaEnableCalculate(bool bEnabled)218*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::XfaEnableCalculate(bool bEnabled) {
219*3ac0a46fSAndroid Build Coastguard Worker   m_bXfaCalculate = bEnabled;
220*3ac0a46fSAndroid Build Coastguard Worker }
221*3ac0a46fSAndroid Build Coastguard Worker 
IsXfaCalculateEnabled() const222*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::IsXfaCalculateEnabled() const {
223*3ac0a46fSAndroid Build Coastguard Worker   return m_bXfaCalculate;
224*3ac0a46fSAndroid Build Coastguard Worker }
225*3ac0a46fSAndroid Build Coastguard Worker 
IsXfaValidationsEnabled()226*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::IsXfaValidationsEnabled() {
227*3ac0a46fSAndroid Build Coastguard Worker   return m_bXfaValidationsEnabled;
228*3ac0a46fSAndroid Build Coastguard Worker }
XfaSetValidationsEnabled(bool bEnabled)229*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::XfaSetValidationsEnabled(bool bEnabled) {
230*3ac0a46fSAndroid Build Coastguard Worker   m_bXfaValidationsEnabled = bEnabled;
231*3ac0a46fSAndroid Build Coastguard Worker }
232*3ac0a46fSAndroid Build Coastguard Worker 
SynchronizeField(CPDF_FormField * pFormField)233*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::SynchronizeField(CPDF_FormField* pFormField) {
234*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
235*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
236*3ac0a46fSAndroid Build Coastguard Worker     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
237*3ac0a46fSAndroid Build Coastguard Worker       pWidget->Synchronize(false);
238*3ac0a46fSAndroid Build Coastguard Worker   }
239*3ac0a46fSAndroid Build Coastguard Worker }
240*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
241*3ac0a46fSAndroid Build Coastguard Worker 
OnCalculate(CPDF_FormField * pFormField)242*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::OnCalculate(CPDF_FormField* pFormField) {
243*3ac0a46fSAndroid Build Coastguard Worker   if (!m_pFormFillEnv->IsJSPlatformPresent())
244*3ac0a46fSAndroid Build Coastguard Worker     return;
245*3ac0a46fSAndroid Build Coastguard Worker 
246*3ac0a46fSAndroid Build Coastguard Worker   if (m_bBusy)
247*3ac0a46fSAndroid Build Coastguard Worker     return;
248*3ac0a46fSAndroid Build Coastguard Worker 
249*3ac0a46fSAndroid Build Coastguard Worker   AutoRestorer<bool> restorer(&m_bBusy);
250*3ac0a46fSAndroid Build Coastguard Worker   m_bBusy = true;
251*3ac0a46fSAndroid Build Coastguard Worker 
252*3ac0a46fSAndroid Build Coastguard Worker   if (!IsCalculateEnabled())
253*3ac0a46fSAndroid Build Coastguard Worker     return;
254*3ac0a46fSAndroid Build Coastguard Worker 
255*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime* pRuntime = m_pFormFillEnv->GetIJSRuntime();
256*3ac0a46fSAndroid Build Coastguard Worker   int nSize = m_pInteractiveForm->CountFieldsInCalculationOrder();
257*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0; i < nSize; i++) {
258*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pField = m_pInteractiveForm->GetFieldInCalculationOrder(i);
259*3ac0a46fSAndroid Build Coastguard Worker     if (!pField)
260*3ac0a46fSAndroid Build Coastguard Worker       continue;
261*3ac0a46fSAndroid Build Coastguard Worker 
262*3ac0a46fSAndroid Build Coastguard Worker     FormFieldType fieldType = pField->GetFieldType();
263*3ac0a46fSAndroid Build Coastguard Worker     if (!IsFormFieldTypeComboOrText(fieldType))
264*3ac0a46fSAndroid Build Coastguard Worker       continue;
265*3ac0a46fSAndroid Build Coastguard Worker 
266*3ac0a46fSAndroid Build Coastguard Worker     CPDF_AAction aAction = pField->GetAdditionalAction();
267*3ac0a46fSAndroid Build Coastguard Worker     if (!aAction.ActionExist(CPDF_AAction::kCalculate))
268*3ac0a46fSAndroid Build Coastguard Worker       continue;
269*3ac0a46fSAndroid Build Coastguard Worker 
270*3ac0a46fSAndroid Build Coastguard Worker     CPDF_Action action = aAction.GetAction(CPDF_AAction::kCalculate);
271*3ac0a46fSAndroid Build Coastguard Worker     if (!action.HasDict())
272*3ac0a46fSAndroid Build Coastguard Worker       continue;
273*3ac0a46fSAndroid Build Coastguard Worker 
274*3ac0a46fSAndroid Build Coastguard Worker     WideString csJS = action.GetJavaScript();
275*3ac0a46fSAndroid Build Coastguard Worker     if (csJS.IsEmpty())
276*3ac0a46fSAndroid Build Coastguard Worker       continue;
277*3ac0a46fSAndroid Build Coastguard Worker 
278*3ac0a46fSAndroid Build Coastguard Worker     WideString sOldValue = pField->GetValue();
279*3ac0a46fSAndroid Build Coastguard Worker     WideString sValue = sOldValue;
280*3ac0a46fSAndroid Build Coastguard Worker     bool bRC = true;
281*3ac0a46fSAndroid Build Coastguard Worker     IJS_Runtime::ScopedEventContext pContext(pRuntime);
282*3ac0a46fSAndroid Build Coastguard Worker     pContext->OnField_Calculate(pFormField, pField, &sValue, &bRC);
283*3ac0a46fSAndroid Build Coastguard Worker 
284*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<IJS_Runtime::JS_Error> err = pContext->RunScript(csJS);
285*3ac0a46fSAndroid Build Coastguard Worker     if (!err.has_value() && bRC && sValue != sOldValue)
286*3ac0a46fSAndroid Build Coastguard Worker       pField->SetValue(sValue, NotificationOption::kNotify);
287*3ac0a46fSAndroid Build Coastguard Worker   }
288*3ac0a46fSAndroid Build Coastguard Worker }
289*3ac0a46fSAndroid Build Coastguard Worker 
OnFormat(CPDF_FormField * pFormField)290*3ac0a46fSAndroid Build Coastguard Worker absl::optional<WideString> CPDFSDK_InteractiveForm::OnFormat(
291*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pFormField) {
292*3ac0a46fSAndroid Build Coastguard Worker   if (!m_pFormFillEnv->IsJSPlatformPresent())
293*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
294*3ac0a46fSAndroid Build Coastguard Worker 
295*3ac0a46fSAndroid Build Coastguard Worker   WideString sValue = pFormField->GetValue();
296*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime* pRuntime = m_pFormFillEnv->GetIJSRuntime();
297*3ac0a46fSAndroid Build Coastguard Worker   if (pFormField->GetFieldType() == FormFieldType::kComboBox &&
298*3ac0a46fSAndroid Build Coastguard Worker       pFormField->CountSelectedItems() > 0) {
299*3ac0a46fSAndroid Build Coastguard Worker     int index = pFormField->GetSelectedIndex(0);
300*3ac0a46fSAndroid Build Coastguard Worker     if (index >= 0)
301*3ac0a46fSAndroid Build Coastguard Worker       sValue = pFormField->GetOptionLabel(index);
302*3ac0a46fSAndroid Build Coastguard Worker   }
303*3ac0a46fSAndroid Build Coastguard Worker 
304*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AAction aAction = pFormField->GetAdditionalAction();
305*3ac0a46fSAndroid Build Coastguard Worker   if (aAction.ActionExist(CPDF_AAction::kFormat)) {
306*3ac0a46fSAndroid Build Coastguard Worker     CPDF_Action action = aAction.GetAction(CPDF_AAction::kFormat);
307*3ac0a46fSAndroid Build Coastguard Worker     if (action.HasDict()) {
308*3ac0a46fSAndroid Build Coastguard Worker       WideString script = action.GetJavaScript();
309*3ac0a46fSAndroid Build Coastguard Worker       if (!script.IsEmpty()) {
310*3ac0a46fSAndroid Build Coastguard Worker         IJS_Runtime::ScopedEventContext pContext(pRuntime);
311*3ac0a46fSAndroid Build Coastguard Worker         pContext->OnField_Format(pFormField, &sValue);
312*3ac0a46fSAndroid Build Coastguard Worker         absl::optional<IJS_Runtime::JS_Error> err = pContext->RunScript(script);
313*3ac0a46fSAndroid Build Coastguard Worker         if (!err.has_value())
314*3ac0a46fSAndroid Build Coastguard Worker           return sValue;
315*3ac0a46fSAndroid Build Coastguard Worker       }
316*3ac0a46fSAndroid Build Coastguard Worker     }
317*3ac0a46fSAndroid Build Coastguard Worker   }
318*3ac0a46fSAndroid Build Coastguard Worker   return absl::nullopt;
319*3ac0a46fSAndroid Build Coastguard Worker }
320*3ac0a46fSAndroid Build Coastguard Worker 
ResetFieldAppearance(CPDF_FormField * pFormField,absl::optional<WideString> sValue)321*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::ResetFieldAppearance(
322*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pFormField,
323*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<WideString> sValue) {
324*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
325*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
326*3ac0a46fSAndroid Build Coastguard Worker     DCHECK(pFormCtrl);
327*3ac0a46fSAndroid Build Coastguard Worker     if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl))
328*3ac0a46fSAndroid Build Coastguard Worker       pWidget->ResetAppearance(sValue, CPDFSDK_Widget::kValueChanged);
329*3ac0a46fSAndroid Build Coastguard Worker   }
330*3ac0a46fSAndroid Build Coastguard Worker }
331*3ac0a46fSAndroid Build Coastguard Worker 
UpdateField(CPDF_FormField * pFormField)332*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::UpdateField(CPDF_FormField* pFormField) {
333*3ac0a46fSAndroid Build Coastguard Worker   auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller();
334*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) {
335*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormControl* pFormCtrl = pFormField->GetControl(i);
336*3ac0a46fSAndroid Build Coastguard Worker     DCHECK(pFormCtrl);
337*3ac0a46fSAndroid Build Coastguard Worker 
338*3ac0a46fSAndroid Build Coastguard Worker     CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl);
339*3ac0a46fSAndroid Build Coastguard Worker     if (!pWidget)
340*3ac0a46fSAndroid Build Coastguard Worker       continue;
341*3ac0a46fSAndroid Build Coastguard Worker 
342*3ac0a46fSAndroid Build Coastguard Worker     IPDF_Page* pPage = pWidget->GetPage();
343*3ac0a46fSAndroid Build Coastguard Worker     FX_RECT rect =
344*3ac0a46fSAndroid Build Coastguard Worker         formfiller->GetViewBBox(m_pFormFillEnv->GetPageView(pPage), pWidget);
345*3ac0a46fSAndroid Build Coastguard Worker     m_pFormFillEnv->Invalidate(pPage, rect);
346*3ac0a46fSAndroid Build Coastguard Worker   }
347*3ac0a46fSAndroid Build Coastguard Worker }
348*3ac0a46fSAndroid Build Coastguard Worker 
OnKeyStrokeCommit(CPDF_FormField * pFormField,const WideString & csValue)349*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::OnKeyStrokeCommit(CPDF_FormField* pFormField,
350*3ac0a46fSAndroid Build Coastguard Worker                                                 const WideString& csValue) {
351*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AAction aAction = pFormField->GetAdditionalAction();
352*3ac0a46fSAndroid Build Coastguard Worker   if (!aAction.ActionExist(CPDF_AAction::kKeyStroke))
353*3ac0a46fSAndroid Build Coastguard Worker     return true;
354*3ac0a46fSAndroid Build Coastguard Worker 
355*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Action action = aAction.GetAction(CPDF_AAction::kKeyStroke);
356*3ac0a46fSAndroid Build Coastguard Worker   if (!action.HasDict())
357*3ac0a46fSAndroid Build Coastguard Worker     return true;
358*3ac0a46fSAndroid Build Coastguard Worker 
359*3ac0a46fSAndroid Build Coastguard Worker   CFFL_FieldAction fa;
360*3ac0a46fSAndroid Build Coastguard Worker   fa.bModifier = false;
361*3ac0a46fSAndroid Build Coastguard Worker   fa.bShift = false;
362*3ac0a46fSAndroid Build Coastguard Worker   fa.sValue = csValue;
363*3ac0a46fSAndroid Build Coastguard Worker   m_pFormFillEnv->DoActionFieldJavaScript(action, CPDF_AAction::kKeyStroke,
364*3ac0a46fSAndroid Build Coastguard Worker                                           pFormField, &fa);
365*3ac0a46fSAndroid Build Coastguard Worker   return fa.bRC;
366*3ac0a46fSAndroid Build Coastguard Worker }
367*3ac0a46fSAndroid Build Coastguard Worker 
OnValidate(CPDF_FormField * pFormField,const WideString & csValue)368*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::OnValidate(CPDF_FormField* pFormField,
369*3ac0a46fSAndroid Build Coastguard Worker                                          const WideString& csValue) {
370*3ac0a46fSAndroid Build Coastguard Worker   CPDF_AAction aAction = pFormField->GetAdditionalAction();
371*3ac0a46fSAndroid Build Coastguard Worker   if (!aAction.ActionExist(CPDF_AAction::kValidate))
372*3ac0a46fSAndroid Build Coastguard Worker     return true;
373*3ac0a46fSAndroid Build Coastguard Worker 
374*3ac0a46fSAndroid Build Coastguard Worker   CPDF_Action action = aAction.GetAction(CPDF_AAction::kValidate);
375*3ac0a46fSAndroid Build Coastguard Worker   if (!action.HasDict())
376*3ac0a46fSAndroid Build Coastguard Worker     return true;
377*3ac0a46fSAndroid Build Coastguard Worker 
378*3ac0a46fSAndroid Build Coastguard Worker   CFFL_FieldAction fa;
379*3ac0a46fSAndroid Build Coastguard Worker   fa.bModifier = false;
380*3ac0a46fSAndroid Build Coastguard Worker   fa.bShift = false;
381*3ac0a46fSAndroid Build Coastguard Worker   fa.sValue = csValue;
382*3ac0a46fSAndroid Build Coastguard Worker   m_pFormFillEnv->DoActionFieldJavaScript(action, CPDF_AAction::kValidate,
383*3ac0a46fSAndroid Build Coastguard Worker                                           pFormField, &fa);
384*3ac0a46fSAndroid Build Coastguard Worker   return fa.bRC;
385*3ac0a46fSAndroid Build Coastguard Worker }
386*3ac0a46fSAndroid Build Coastguard Worker 
DoAction_Hide(const CPDF_Action & action)387*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::DoAction_Hide(const CPDF_Action& action) {
388*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(action.GetDict());
389*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CPDF_FormField*> fields =
390*3ac0a46fSAndroid Build Coastguard Worker       GetFieldFromObjects(action.GetAllFields());
391*3ac0a46fSAndroid Build Coastguard Worker   bool bHide = action.GetHideStatus();
392*3ac0a46fSAndroid Build Coastguard Worker   bool bChanged = false;
393*3ac0a46fSAndroid Build Coastguard Worker 
394*3ac0a46fSAndroid Build Coastguard Worker   for (CPDF_FormField* pField : fields) {
395*3ac0a46fSAndroid Build Coastguard Worker     for (int i = 0, sz = pField->CountControls(); i < sz; ++i) {
396*3ac0a46fSAndroid Build Coastguard Worker       CPDF_FormControl* pControl = pField->GetControl(i);
397*3ac0a46fSAndroid Build Coastguard Worker       DCHECK(pControl);
398*3ac0a46fSAndroid Build Coastguard Worker 
399*3ac0a46fSAndroid Build Coastguard Worker       if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) {
400*3ac0a46fSAndroid Build Coastguard Worker         uint32_t nFlags = pWidget->GetFlags();
401*3ac0a46fSAndroid Build Coastguard Worker         nFlags &= ~pdfium::annotation_flags::kInvisible;
402*3ac0a46fSAndroid Build Coastguard Worker         nFlags &= ~pdfium::annotation_flags::kNoView;
403*3ac0a46fSAndroid Build Coastguard Worker         if (bHide)
404*3ac0a46fSAndroid Build Coastguard Worker           nFlags |= pdfium::annotation_flags::kHidden;
405*3ac0a46fSAndroid Build Coastguard Worker         else
406*3ac0a46fSAndroid Build Coastguard Worker           nFlags &= ~pdfium::annotation_flags::kHidden;
407*3ac0a46fSAndroid Build Coastguard Worker         pWidget->SetFlags(nFlags);
408*3ac0a46fSAndroid Build Coastguard Worker         pWidget->GetPageView()->UpdateView(pWidget);
409*3ac0a46fSAndroid Build Coastguard Worker         bChanged = true;
410*3ac0a46fSAndroid Build Coastguard Worker       }
411*3ac0a46fSAndroid Build Coastguard Worker     }
412*3ac0a46fSAndroid Build Coastguard Worker   }
413*3ac0a46fSAndroid Build Coastguard Worker 
414*3ac0a46fSAndroid Build Coastguard Worker   return bChanged;
415*3ac0a46fSAndroid Build Coastguard Worker }
416*3ac0a46fSAndroid Build Coastguard Worker 
DoAction_SubmitForm(const CPDF_Action & action)417*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::DoAction_SubmitForm(const CPDF_Action& action) {
418*3ac0a46fSAndroid Build Coastguard Worker   WideString sDestination = action.GetFilePath();
419*3ac0a46fSAndroid Build Coastguard Worker   if (sDestination.IsEmpty())
420*3ac0a46fSAndroid Build Coastguard Worker     return false;
421*3ac0a46fSAndroid Build Coastguard Worker 
422*3ac0a46fSAndroid Build Coastguard Worker   if (action.HasFields()) {
423*3ac0a46fSAndroid Build Coastguard Worker     uint32_t dwFlags = action.GetFlags();
424*3ac0a46fSAndroid Build Coastguard Worker     std::vector<CPDF_FormField*> fields =
425*3ac0a46fSAndroid Build Coastguard Worker         GetFieldFromObjects(action.GetAllFields());
426*3ac0a46fSAndroid Build Coastguard Worker     if (!fields.empty()) {
427*3ac0a46fSAndroid Build Coastguard Worker       bool bIncludeOrExclude = !(dwFlags & 0x01);
428*3ac0a46fSAndroid Build Coastguard Worker       if (!m_pInteractiveForm->CheckRequiredFields(&fields, bIncludeOrExclude))
429*3ac0a46fSAndroid Build Coastguard Worker         return false;
430*3ac0a46fSAndroid Build Coastguard Worker 
431*3ac0a46fSAndroid Build Coastguard Worker       return SubmitFields(sDestination, fields, bIncludeOrExclude, false);
432*3ac0a46fSAndroid Build Coastguard Worker     }
433*3ac0a46fSAndroid Build Coastguard Worker   }
434*3ac0a46fSAndroid Build Coastguard Worker   if (!m_pInteractiveForm->CheckRequiredFields(nullptr, true))
435*3ac0a46fSAndroid Build Coastguard Worker     return false;
436*3ac0a46fSAndroid Build Coastguard Worker 
437*3ac0a46fSAndroid Build Coastguard Worker   return SubmitForm(sDestination);
438*3ac0a46fSAndroid Build Coastguard Worker }
439*3ac0a46fSAndroid Build Coastguard Worker 
SubmitFields(const WideString & csDestination,const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude,bool bUrlEncoded)440*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::SubmitFields(
441*3ac0a46fSAndroid Build Coastguard Worker     const WideString& csDestination,
442*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<CPDF_FormField*>& fields,
443*3ac0a46fSAndroid Build Coastguard Worker     bool bIncludeOrExclude,
444*3ac0a46fSAndroid Build Coastguard Worker     bool bUrlEncoded) {
445*3ac0a46fSAndroid Build Coastguard Worker   ByteString text_buf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude);
446*3ac0a46fSAndroid Build Coastguard Worker   if (text_buf.IsEmpty())
447*3ac0a46fSAndroid Build Coastguard Worker     return false;
448*3ac0a46fSAndroid Build Coastguard Worker 
449*3ac0a46fSAndroid Build Coastguard Worker   if (bUrlEncoded) {
450*3ac0a46fSAndroid Build Coastguard Worker     text_buf = FDFToURLEncodedData(text_buf);
451*3ac0a46fSAndroid Build Coastguard Worker     if (text_buf.IsEmpty())
452*3ac0a46fSAndroid Build Coastguard Worker       return false;
453*3ac0a46fSAndroid Build Coastguard Worker   }
454*3ac0a46fSAndroid Build Coastguard Worker 
455*3ac0a46fSAndroid Build Coastguard Worker   m_pFormFillEnv->SubmitForm(text_buf.raw_span(), csDestination);
456*3ac0a46fSAndroid Build Coastguard Worker   return true;
457*3ac0a46fSAndroid Build Coastguard Worker }
458*3ac0a46fSAndroid Build Coastguard Worker 
ExportFieldsToFDFTextBuf(const std::vector<CPDF_FormField * > & fields,bool bIncludeOrExclude)459*3ac0a46fSAndroid Build Coastguard Worker ByteString CPDFSDK_InteractiveForm::ExportFieldsToFDFTextBuf(
460*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<CPDF_FormField*>& fields,
461*3ac0a46fSAndroid Build Coastguard Worker     bool bIncludeOrExclude) {
462*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFDF_Document> pFDF = m_pInteractiveForm->ExportToFDF(
463*3ac0a46fSAndroid Build Coastguard Worker       m_pFormFillEnv->GetFilePath(), fields, bIncludeOrExclude);
464*3ac0a46fSAndroid Build Coastguard Worker 
465*3ac0a46fSAndroid Build Coastguard Worker   return pFDF ? pFDF->WriteToString() : ByteString();
466*3ac0a46fSAndroid Build Coastguard Worker }
467*3ac0a46fSAndroid Build Coastguard Worker 
SubmitForm(const WideString & sDestination)468*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::SubmitForm(const WideString& sDestination) {
469*3ac0a46fSAndroid Build Coastguard Worker   if (sDestination.IsEmpty())
470*3ac0a46fSAndroid Build Coastguard Worker     return false;
471*3ac0a46fSAndroid Build Coastguard Worker 
472*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFDF_Document> pFDFDoc =
473*3ac0a46fSAndroid Build Coastguard Worker       m_pInteractiveForm->ExportToFDF(m_pFormFillEnv->GetFilePath());
474*3ac0a46fSAndroid Build Coastguard Worker   if (!pFDFDoc)
475*3ac0a46fSAndroid Build Coastguard Worker     return false;
476*3ac0a46fSAndroid Build Coastguard Worker 
477*3ac0a46fSAndroid Build Coastguard Worker   ByteString fdf_buffer = pFDFDoc->WriteToString();
478*3ac0a46fSAndroid Build Coastguard Worker   if (fdf_buffer.IsEmpty())
479*3ac0a46fSAndroid Build Coastguard Worker     return false;
480*3ac0a46fSAndroid Build Coastguard Worker 
481*3ac0a46fSAndroid Build Coastguard Worker   m_pFormFillEnv->SubmitForm(fdf_buffer.raw_span(), sDestination);
482*3ac0a46fSAndroid Build Coastguard Worker   return true;
483*3ac0a46fSAndroid Build Coastguard Worker }
484*3ac0a46fSAndroid Build Coastguard Worker 
ExportFormToFDFTextBuf()485*3ac0a46fSAndroid Build Coastguard Worker ByteString CPDFSDK_InteractiveForm::ExportFormToFDFTextBuf() {
486*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFDF_Document> pFDF =
487*3ac0a46fSAndroid Build Coastguard Worker       m_pInteractiveForm->ExportToFDF(m_pFormFillEnv->GetFilePath());
488*3ac0a46fSAndroid Build Coastguard Worker 
489*3ac0a46fSAndroid Build Coastguard Worker   return pFDF ? pFDF->WriteToString() : ByteString();
490*3ac0a46fSAndroid Build Coastguard Worker }
491*3ac0a46fSAndroid Build Coastguard Worker 
DoAction_ResetForm(const CPDF_Action & action)492*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::DoAction_ResetForm(const CPDF_Action& action) {
493*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(action.GetDict());
494*3ac0a46fSAndroid Build Coastguard Worker   if (!action.HasFields()) {
495*3ac0a46fSAndroid Build Coastguard Worker     m_pInteractiveForm->ResetForm();
496*3ac0a46fSAndroid Build Coastguard Worker     return;
497*3ac0a46fSAndroid Build Coastguard Worker   }
498*3ac0a46fSAndroid Build Coastguard Worker   uint32_t dwFlags = action.GetFlags();
499*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CPDF_FormField*> fields =
500*3ac0a46fSAndroid Build Coastguard Worker       GetFieldFromObjects(action.GetAllFields());
501*3ac0a46fSAndroid Build Coastguard Worker   m_pInteractiveForm->ResetForm(fields, !(dwFlags & 0x01));
502*3ac0a46fSAndroid Build Coastguard Worker }
503*3ac0a46fSAndroid Build Coastguard Worker 
GetFieldFromObjects(const std::vector<RetainPtr<const CPDF_Object>> & objects) const504*3ac0a46fSAndroid Build Coastguard Worker std::vector<CPDF_FormField*> CPDFSDK_InteractiveForm::GetFieldFromObjects(
505*3ac0a46fSAndroid Build Coastguard Worker     const std::vector<RetainPtr<const CPDF_Object>>& objects) const {
506*3ac0a46fSAndroid Build Coastguard Worker   std::vector<CPDF_FormField*> fields;
507*3ac0a46fSAndroid Build Coastguard Worker   for (const CPDF_Object* pObject : objects) {
508*3ac0a46fSAndroid Build Coastguard Worker     if (!pObject || !pObject->IsString())
509*3ac0a46fSAndroid Build Coastguard Worker       continue;
510*3ac0a46fSAndroid Build Coastguard Worker 
511*3ac0a46fSAndroid Build Coastguard Worker     WideString csName = pObject->GetUnicodeText();
512*3ac0a46fSAndroid Build Coastguard Worker     CPDF_FormField* pField = m_pInteractiveForm->GetField(0, csName);
513*3ac0a46fSAndroid Build Coastguard Worker     if (pField)
514*3ac0a46fSAndroid Build Coastguard Worker       fields.push_back(pField);
515*3ac0a46fSAndroid Build Coastguard Worker   }
516*3ac0a46fSAndroid Build Coastguard Worker   return fields;
517*3ac0a46fSAndroid Build Coastguard Worker }
518*3ac0a46fSAndroid Build Coastguard Worker 
BeforeValueChange(CPDF_FormField * pField,const WideString & csValue)519*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::BeforeValueChange(CPDF_FormField* pField,
520*3ac0a46fSAndroid Build Coastguard Worker                                                 const WideString& csValue) {
521*3ac0a46fSAndroid Build Coastguard Worker   FormFieldType fieldType = pField->GetFieldType();
522*3ac0a46fSAndroid Build Coastguard Worker   if (!IsFormFieldTypeComboOrText(fieldType))
523*3ac0a46fSAndroid Build Coastguard Worker     return true;
524*3ac0a46fSAndroid Build Coastguard Worker   if (!OnKeyStrokeCommit(pField, csValue))
525*3ac0a46fSAndroid Build Coastguard Worker     return false;
526*3ac0a46fSAndroid Build Coastguard Worker   return OnValidate(pField, csValue);
527*3ac0a46fSAndroid Build Coastguard Worker }
528*3ac0a46fSAndroid Build Coastguard Worker 
AfterValueChange(CPDF_FormField * pField)529*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::AfterValueChange(CPDF_FormField* pField) {
530*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
531*3ac0a46fSAndroid Build Coastguard Worker   SynchronizeField(pField);
532*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
533*3ac0a46fSAndroid Build Coastguard Worker 
534*3ac0a46fSAndroid Build Coastguard Worker   FormFieldType fieldType = pField->GetFieldType();
535*3ac0a46fSAndroid Build Coastguard Worker   if (!IsFormFieldTypeComboOrText(fieldType))
536*3ac0a46fSAndroid Build Coastguard Worker     return;
537*3ac0a46fSAndroid Build Coastguard Worker 
538*3ac0a46fSAndroid Build Coastguard Worker   OnCalculate(pField);
539*3ac0a46fSAndroid Build Coastguard Worker   ResetFieldAppearance(pField, OnFormat(pField));
540*3ac0a46fSAndroid Build Coastguard Worker   UpdateField(pField);
541*3ac0a46fSAndroid Build Coastguard Worker }
542*3ac0a46fSAndroid Build Coastguard Worker 
BeforeSelectionChange(CPDF_FormField * pField,const WideString & csValue)543*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::BeforeSelectionChange(CPDF_FormField* pField,
544*3ac0a46fSAndroid Build Coastguard Worker                                                     const WideString& csValue) {
545*3ac0a46fSAndroid Build Coastguard Worker   if (pField->GetFieldType() != FormFieldType::kListBox)
546*3ac0a46fSAndroid Build Coastguard Worker     return true;
547*3ac0a46fSAndroid Build Coastguard Worker   if (!OnKeyStrokeCommit(pField, csValue))
548*3ac0a46fSAndroid Build Coastguard Worker     return false;
549*3ac0a46fSAndroid Build Coastguard Worker   return OnValidate(pField, csValue);
550*3ac0a46fSAndroid Build Coastguard Worker }
551*3ac0a46fSAndroid Build Coastguard Worker 
AfterSelectionChange(CPDF_FormField * pField)552*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::AfterSelectionChange(CPDF_FormField* pField) {
553*3ac0a46fSAndroid Build Coastguard Worker   if (pField->GetFieldType() != FormFieldType::kListBox)
554*3ac0a46fSAndroid Build Coastguard Worker     return;
555*3ac0a46fSAndroid Build Coastguard Worker 
556*3ac0a46fSAndroid Build Coastguard Worker   OnCalculate(pField);
557*3ac0a46fSAndroid Build Coastguard Worker   ResetFieldAppearance(pField, absl::nullopt);
558*3ac0a46fSAndroid Build Coastguard Worker   UpdateField(pField);
559*3ac0a46fSAndroid Build Coastguard Worker }
560*3ac0a46fSAndroid Build Coastguard Worker 
AfterCheckedStatusChange(CPDF_FormField * pField)561*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::AfterCheckedStatusChange(CPDF_FormField* pField) {
562*3ac0a46fSAndroid Build Coastguard Worker   FormFieldType fieldType = pField->GetFieldType();
563*3ac0a46fSAndroid Build Coastguard Worker   if (fieldType != FormFieldType::kCheckBox &&
564*3ac0a46fSAndroid Build Coastguard Worker       fieldType != FormFieldType::kRadioButton)
565*3ac0a46fSAndroid Build Coastguard Worker     return;
566*3ac0a46fSAndroid Build Coastguard Worker 
567*3ac0a46fSAndroid Build Coastguard Worker   OnCalculate(pField);
568*3ac0a46fSAndroid Build Coastguard Worker   UpdateField(pField);
569*3ac0a46fSAndroid Build Coastguard Worker }
570*3ac0a46fSAndroid Build Coastguard Worker 
AfterFormReset(CPDF_InteractiveForm * pForm)571*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::AfterFormReset(CPDF_InteractiveForm* pForm) {
572*3ac0a46fSAndroid Build Coastguard Worker   OnCalculate(nullptr);
573*3ac0a46fSAndroid Build Coastguard Worker }
574*3ac0a46fSAndroid Build Coastguard Worker 
IsNeedHighLight(FormFieldType fieldType) const575*3ac0a46fSAndroid Build Coastguard Worker bool CPDFSDK_InteractiveForm::IsNeedHighLight(FormFieldType fieldType) const {
576*3ac0a46fSAndroid Build Coastguard Worker   if (fieldType == FormFieldType::kUnknown)
577*3ac0a46fSAndroid Build Coastguard Worker     return false;
578*3ac0a46fSAndroid Build Coastguard Worker 
579*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
580*3ac0a46fSAndroid Build Coastguard Worker   // For the XFA fields, we need to return if the specific field type has
581*3ac0a46fSAndroid Build Coastguard Worker   // highlight enabled or if the general XFA field type has it enabled.
582*3ac0a46fSAndroid Build Coastguard Worker   if (IsFormFieldTypeXFA(fieldType)) {
583*3ac0a46fSAndroid Build Coastguard Worker     if (!m_NeedsHighlight[static_cast<size_t>(fieldType)])
584*3ac0a46fSAndroid Build Coastguard Worker       return m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)];
585*3ac0a46fSAndroid Build Coastguard Worker   }
586*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
587*3ac0a46fSAndroid Build Coastguard Worker   return m_NeedsHighlight[static_cast<size_t>(fieldType)];
588*3ac0a46fSAndroid Build Coastguard Worker }
589*3ac0a46fSAndroid Build Coastguard Worker 
RemoveAllHighLights()590*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::RemoveAllHighLights() {
591*3ac0a46fSAndroid Build Coastguard Worker   std::fill(std::begin(m_HighlightColor), std::end(m_HighlightColor),
592*3ac0a46fSAndroid Build Coastguard Worker             kWhiteBGR);
593*3ac0a46fSAndroid Build Coastguard Worker   std::fill(std::begin(m_NeedsHighlight), std::end(m_NeedsHighlight), false);
594*3ac0a46fSAndroid Build Coastguard Worker }
595*3ac0a46fSAndroid Build Coastguard Worker 
SetHighlightColor(FX_COLORREF clr,FormFieldType fieldType)596*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::SetHighlightColor(FX_COLORREF clr,
597*3ac0a46fSAndroid Build Coastguard Worker                                                 FormFieldType fieldType) {
598*3ac0a46fSAndroid Build Coastguard Worker   if (fieldType == FormFieldType::kUnknown)
599*3ac0a46fSAndroid Build Coastguard Worker     return;
600*3ac0a46fSAndroid Build Coastguard Worker 
601*3ac0a46fSAndroid Build Coastguard Worker   m_HighlightColor[static_cast<size_t>(fieldType)] = clr;
602*3ac0a46fSAndroid Build Coastguard Worker   m_NeedsHighlight[static_cast<size_t>(fieldType)] = true;
603*3ac0a46fSAndroid Build Coastguard Worker }
604*3ac0a46fSAndroid Build Coastguard Worker 
SetAllHighlightColors(FX_COLORREF clr)605*3ac0a46fSAndroid Build Coastguard Worker void CPDFSDK_InteractiveForm::SetAllHighlightColors(FX_COLORREF clr) {
606*3ac0a46fSAndroid Build Coastguard Worker   for (size_t i = 0; i < kFormFieldTypeCount; ++i) {
607*3ac0a46fSAndroid Build Coastguard Worker     m_HighlightColor[i] = clr;
608*3ac0a46fSAndroid Build Coastguard Worker     m_NeedsHighlight[i] = true;
609*3ac0a46fSAndroid Build Coastguard Worker   }
610*3ac0a46fSAndroid Build Coastguard Worker }
611*3ac0a46fSAndroid Build Coastguard Worker 
GetHighlightColor(FormFieldType fieldType)612*3ac0a46fSAndroid Build Coastguard Worker FX_COLORREF CPDFSDK_InteractiveForm::GetHighlightColor(
613*3ac0a46fSAndroid Build Coastguard Worker     FormFieldType fieldType) {
614*3ac0a46fSAndroid Build Coastguard Worker   if (fieldType == FormFieldType::kUnknown)
615*3ac0a46fSAndroid Build Coastguard Worker     return kWhiteBGR;
616*3ac0a46fSAndroid Build Coastguard Worker 
617*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
618*3ac0a46fSAndroid Build Coastguard Worker   // For the XFA fields, we need to return the specific field type highlight
619*3ac0a46fSAndroid Build Coastguard Worker   // colour or the general XFA field type colour if present.
620*3ac0a46fSAndroid Build Coastguard Worker   if (IsFormFieldTypeXFA(fieldType)) {
621*3ac0a46fSAndroid Build Coastguard Worker     if (!m_NeedsHighlight[static_cast<size_t>(fieldType)] &&
622*3ac0a46fSAndroid Build Coastguard Worker         m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)]) {
623*3ac0a46fSAndroid Build Coastguard Worker       return m_HighlightColor[static_cast<size_t>(FormFieldType::kXFA)];
624*3ac0a46fSAndroid Build Coastguard Worker     }
625*3ac0a46fSAndroid Build Coastguard Worker   }
626*3ac0a46fSAndroid Build Coastguard Worker #endif  // PDF_ENABLE_XFA
627*3ac0a46fSAndroid Build Coastguard Worker   return m_HighlightColor[static_cast<size_t>(fieldType)];
628*3ac0a46fSAndroid Build Coastguard Worker }
629