7#include "core/fpdfdoc/cpdf_formfield.h"
13#include "constants/form_fields.h"
14#include "constants/form_flags.h"
15#include "core/fpdfapi/font/cpdf_font.h"
16#include "core/fpdfapi/page/cpdf_docpagedata.h"
17#include "core/fpdfapi/parser/cfdf_document.h"
18#include "core/fpdfapi/parser/cpdf_array.h"
19#include "core/fpdfapi/parser/cpdf_dictionary.h"
20#include "core/fpdfapi/parser/cpdf_name.h"
21#include "core/fpdfapi/parser/cpdf_number.h"
22#include "core/fpdfapi/parser/cpdf_stream.h"
23#include "core/fpdfapi/parser/cpdf_string.h"
24#include "core/fpdfapi/parser/fpdf_parser_decode.h"
25#include "core/fpdfapi/parser/fpdf_parser_utility.h"
26#include "core/fpdfdoc/cpdf_defaultappearance.h"
27#include "core/fpdfdoc/cpdf_formcontrol.h"
28#include "core/fpdfdoc/cpdf_generateap.h"
29#include "core/fpdfdoc/cpdf_interactiveform.h"
30#include "core/fxcrt/stl_util.h"
31#include "third_party/base/check.h"
32#include "third_party/base/containers/contains.h"
37 const CPDF_Dictionary* pFieldDict,
38 const ByteString& name,
40 static constexpr int kGetFieldMaxRecursion = 32;
41 if (!pFieldDict || nLevel > kGetFieldMaxRecursion)
48 return GetFieldAttrRecursive(
49 pFieldDict->GetDictFor(pdfium::form_fields::kParent).Get(), name,
80 value <
static_cast<
int>(kFormFieldTypeCount)) {
88 const CPDF_Dictionary* pFieldDict,
89 const ByteString& name) {
90 return GetFieldAttrRecursive(pFieldDict, name, 0);
95 CPDF_Dictionary* pFieldDict,
96 const ByteString& name) {
97 return pdfium::WrapRetain(
const_cast<CPDF_Object*>(
98 GetFieldAttrRecursive(pFieldDict, name, 0).Get()));
103 const CPDF_Dictionary* pFieldDict) {
104 WideString full_name;
105 std::set<
const CPDF_Dictionary*> visited;
106 const CPDF_Dictionary* pLevel = pFieldDict;
108 visited.insert(pLevel);
112 full_name =
std::move(short_name);
114 full_name
= short_name
+ L'.'
+ full_name;
117 if (pdfium::Contains(visited, pLevel))
133 GetFieldAttrInternal(pdfium::form_fields::kFT);
134 ByteString type_name = ft_attr ? ft_attr->GetString() : ByteString
();
170 return GetFullNameForDict(m_pDict.Get());
174 const ByteString& name)
const {
175 return GetFieldAttrInternal(name);
179 return pdfium::WrapRetain(GetFieldDictInternal());
189 for (
int i = 0; i < iCount; i++) {
193 m_pForm->NotifyAfterCheckedStatusChange(
this);
203 if (!NotifyListOrComboBoxBeforeChange(csValue)) {
207 NotifyListOrComboBoxAfterChange();
221 csDValue = pDV->GetUnicodeText();
225 csValue = pV->GetUnicodeText();
229 if (!bHasRV && (csDValue
== csValue))
232 if (!m_pForm->NotifyBeforeValueChange(
this, csDValue))
244 m_pDict->SetFor(pdfium::form_fields::kV, std::move(pClone));
246 m_pDict->SetFor(pdfium::form_fields::kRV, pDV->Clone());
249 m_pDict->RemoveFor(pdfium::form_fields::kV);
250 m_pDict->RemoveFor(pdfium::form_fields::kRV);
253 m_pForm->NotifyAfterValueChange(
this);
261 return fxcrt::CollectionSize<
int>(GetControls());
265 return GetControls()[index];
272 const auto& controls = GetControls();
273 auto it =
std::find(controls.begin(), controls.end(), pControl);
274 if (it == controls.end())
277 return pdfium::base::checked_cast<
int>(it - controls.begin());
305 GetFieldAttrInternal(pdfium::form_fields::kAA);
311 GetFieldAttrInternal(pdfium::form_fields::kTU);
312 return pObj ? pObj->GetUnicodeText() : WideString
();
317 GetFieldAttrInternal(pdfium::form_fields::kTM);
318 return pObj ? pObj->GetUnicodeText() : WideString
();
323 GetFieldAttrInternal(pdfium::form_fields::kFf);
324 return pObj ? pObj->GetInteger() : 0;
328 m_pDict->SetNewFor<CPDF_Number>(pdfium::form_fields::kFf,
329 static_cast<
int>(dwFlags));
337 bDefault ? GetDefaultValueObject() : GetValueObject();
339 if (!bDefault && m_Type !=
kText)
340 pValue = GetDefaultValueObject();
345 switch (pValue->GetType()) {
348 return pValue->GetUnicodeText();
351 pValue->AsArray()->GetDirectObjectAt(0);
353 return pNewValue->GetUnicodeText();
363 return GetValue(
false);
367 return GetValue(
true);
376 SetCheckValue(value, bDefault, notify);
383 WideString csValue = value;
384 if (notify == NotificationOption::kNotify &&
385 !m_pForm->NotifyBeforeValueChange(
this, csValue)) {
390 m_pDict->SetNewFor<CPDF_String>(key, csValue.AsStringView());
400 m_pDict->SetFor(pdfium::form_fields::kRV,
401 m_pDict->GetObjectFor(key)->Clone());
403 m_pDict->RemoveFor(
"I");
410 if (notify == NotificationOption::kNotify)
411 m_pForm->NotifyAfterValueChange(
this);
422 if (notify == NotificationOption::kNotify &&
423 !m_pForm->NotifyBeforeSelectionChange(
this, value)) {
430 if (notify == NotificationOption::kNotify)
431 m_pForm->NotifyAfterSelectionChange(
this);
442 return SetValue(value,
false, notify);
448 return pObj->GetInteger();
450 for (
auto& pControl : GetControls()) {
454 RetainPtr<
const CPDF_Dictionary> pWidgetDict = pControl->GetWidgetDict();
455 if (pWidgetDict->KeyExist(
"MaxLen"))
456 return pWidgetDict->GetIntegerFor(
"MaxLen");
462 const CPDF_Object* pValue = GetValueOrSelectedIndicesObject();
469 return pArray ?
fxcrt::CollectionSize<
int>(*pArray) : 0;
473 const CPDF_Object* pValue = GetValueOrSelectedIndicesObject();
480 WideString sel_value;
487 if (!pArray || index < 0)
491 pArray->GetDirectObjectAt(index);
492 sel_value = elementValue ? elementValue->GetUnicodeText() : WideString
();
497 if (csOpt
== sel_value)
513 if (!NotifyListOrComboBoxBeforeChange(csValue))
516 m_pDict->RemoveFor(pdfium::form_fields::kV);
517 m_pDict->RemoveFor(
"I");
519 NotifyListOrComboBoxAfterChange();
540 !NotifyListOrComboBoxBeforeChange(opt_value)) {
544 SetItemSelectionSelected(index, opt_value);
548 if (!m_bUseSelectedIndices)
552 NotifyListOrComboBoxAfterChange();
557 const WideString& opt_value) {
559 m_pDict->SetNewFor<CPDF_String>(pdfium::form_fields::kV,
560 opt_value.AsStringView());
561 auto pI = m_pDict->SetNewFor<CPDF_Array>(
"I");
562 pI->AppendNew<CPDF_Number>(index);
567 if (!m_bIsMultiSelectListBox) {
568 m_pDict->SetNewFor<CPDF_String>(pdfium::form_fields::kV,
569 opt_value.AsStringView());
573 auto pArray = m_pDict->SetNewFor<CPDF_Array>(pdfium::form_fields::kV);
585 WideString csDV = pValue->GetUnicodeText();
597 RetainPtr<
const CPDF_Array> pArray = ToArray(GetFieldAttrInternal(
"Opt"));
598 return pArray ?
fxcrt::CollectionSize<
int>(*pArray) : 0;
601WideString
CPDF_FormField::GetOptionText(
int index,
int sub_index)
const {
603 RetainPtr<
const CPDF_Array> pArray = ToArray(GetFieldAttrInternal(
"Opt"));
611 const CPDF_Array* pOptionArray = pOption->AsArray();
613 pOption = pOptionArray->GetDirectObjectAt(sub_index);
618 const CPDF_String* pString = pOption->AsString();
623 return GetOptionText(index, 1);
627 return GetOptionText(index, 0);
641 DCHECK(GetType() == kCheckBox || GetType() == kRadioButton);
650 for (
int i = 0; i < iCount; i++) {
654 if (csEValue
== csWExport) {
659 }
else if (bChecked) {
663 if (i == iControlIndex)
671 if (!ToArray(pOpt)) {
672 ByteString csBExport = PDF_EncodeText(csWExport.AsStringView());
674 m_pDict->SetNewFor<CPDF_Name>(pdfium::form_fields::kV, csBExport);
680 if (csV == csBExport)
681 m_pDict->SetNewFor<CPDF_Name>(pdfium::form_fields::kV,
"Off");
683 }
else if (bChecked) {
684 m_pDict->SetNewFor<CPDF_Name>(pdfium::form_fields::kV,
685 ByteString::FormatInteger(iControlIndex));
687 if (notify == NotificationOption::kNotify)
688 m_pForm->NotifyAfterCheckedStatusChange(
this);
693 DCHECK(GetType() == kCheckBox || GetType() == kRadioButton);
694 WideString csExport = L"Off";
696 for (
int i = 0; i < iCount; i++) {
711 DCHECK(GetType() == kCheckBox || GetType() == kRadioButton);
713 for (
int i = 0; i < iCount; i++) {
716 bool val = csExport
== value;
724 if (notify == NotificationOption::kNotify)
725 m_pForm->NotifyAfterCheckedStatusChange(
this);
731 return pObj ? pObj->GetInteger() : 0;
735 RetainPtr<
const CPDF_Array> pArray = ToArray(GetSelectedIndicesObject());
736 return pArray ?
fxcrt::CollectionSize<
int>(*pArray) : 0;
743 RetainPtr<
const CPDF_Array> pArray = ToArray(GetSelectedIndicesObject());
747 return index <
fxcrt::CollectionSize<
int>(*pArray)
748 ? pArray->GetIntegerAt(index)
757 const CPDF_Array* pValueArray = pValueObject->AsArray();
760 for (
const auto& pObj : locker) {
761 if (pObj->IsString() && pObj->GetUnicodeText() == wsOptValue)
766 return pValueObject->IsString() &&
767 pValueObject->GetUnicodeText() == wsOptValue;
772 GetSelectedIndicesObject();
773 if (!pSelectedIndicesObject)
776 const CPDF_Array* pSelectedIndicesArray = pSelectedIndicesObject->AsArray();
777 if (pSelectedIndicesArray) {
779 for (
const auto& pObj : locker) {
780 if (pObj->IsNumber() && pObj->GetInteger() == iOptIndex)
785 return pSelectedIndicesObject->IsNumber() &&
786 pSelectedIndicesObject->GetInteger() == iOptIndex;
790 RetainPtr<CPDF_Array> pArray = m_pDict->GetOrCreateArrayFor(
"I");
791 for (size_t i = 0; i < pArray->size(); i++) {
792 int iFind = pArray->GetIntegerAt(i);
793 if (iFind == iOptIndex)
796 if (iFind > iOptIndex) {
797 pArray->InsertNewAt<CPDF_Number>(i, iOptIndex);
801 pArray->AppendNew<CPDF_Number>(iOptIndex);
808 GetSelectedIndicesObject();
809 if (!pSelectedIndicesObject)
819 size_t selected_indices_size;
820 const CPDF_Array* pSelectedIndicesArray = pSelectedIndicesObject->AsArray();
821 if (pSelectedIndicesArray)
822 selected_indices_size = pSelectedIndicesArray->size();
823 else if (pSelectedIndicesObject->IsNumber())
824 selected_indices_size = 1;
831 std::map<WideString, size_t> values;
832 const CPDF_Array* pValueArray = pValueObject->AsArray();
834 if (pValueArray->size() != selected_indices_size)
837 for (
const auto& pObj : locker) {
838 if (pObj->IsString())
839 values[pObj->GetUnicodeText()]++;
841 }
else if (pValueObject->IsString()) {
842 if (selected_indices_size != 1)
844 values[pValueObject->GetUnicodeText()]++;
851 if (pSelectedIndicesArray) {
853 for (
const auto& pObj : locker) {
854 if (!pObj->IsNumber())
857 int index = pObj->GetInteger();
858 if (index < 0 || index >= num_options)
861 WideString wsOptValue = GetOptionValue(index);
862 auto it = values.find(wsOptValue);
863 if (it == values.end())
871 return values.empty();
874 DCHECK(pSelectedIndicesObject->IsNumber());
875 int index = pSelectedIndicesObject->GetInteger();
876 if (index < 0 || index >= num_options)
882bool CPDF_FormField::NotifyListOrComboBoxBeforeChange(
const WideString& value) {
885 return m_pForm->NotifyBeforeSelectionChange(
this, value);
887 return m_pForm->NotifyBeforeValueChange(
this, value);
896 m_pForm->NotifyAfterSelectionChange(
this);
899 m_pForm->NotifyAfterValueChange(
this);
907 const ByteString& name)
const {
908 return GetFieldAttrRecursive(m_pDict.Get(), name, 0);
911const CPDF_Dictionary*
CPDF_FormField::GetFieldDictInternal()
const {
912 return m_pDict.Get();
916 return GetFieldAttrInternal(pdfium::form_fields::kDV);
920 return GetFieldAttrInternal(pdfium::form_fields::kV);
925 return GetFieldAttrInternal(
"I");
932 return pValue ? pValue : GetSelectedIndicesObject();
935const std::vector<UnownedPtr<CPDF_FormControl>>&
CPDF_FormField::GetControls()
937 return m_pForm->GetControlsForField(
this);
CPDF_ArrayLocker(const CPDF_Array *pArray)
RetainPtr< const CPDF_Dictionary > GetDictFor(const ByteString &key) const
WideString GetUnicodeTextFor(const ByteString &key) const
virtual WideString GetUnicodeText() const
virtual ByteString GetString() const
const CPDF_Array * AsArray() const
virtual int GetInteger() const
WideString GetUnicodeText() const override
ByteString(const char *ptr)
bool operator==(const ByteString &other) const
bool operator==(const char *ptr) const
ByteString & operator=(ByteString &&that) noexcept
bool operator==(const WideString &other) const
WideString & operator=(WideString &&that) noexcept
WideString operator+(const WideString &str1, const WideString &str2)
WideString operator+(const WideString &str1, wchar_t ch)