// Copyright 2014 PDFium Authors. All rights reserved. | |
// 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 "../../include/fpdfdoc/fpdf_doc.h" | |
CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict); | |
void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray); | |
FX_BOOL PDF_FormField_IsUnison(CPDF_FormField *pField) | |
{ | |
FX_BOOL bUnison = FALSE; | |
if (pField->GetType() == CPDF_FormField::CheckBox) { | |
bUnison = TRUE; | |
} else { | |
FX_DWORD dwFlags = pField->GetFieldFlags(); | |
bUnison = ((dwFlags & 0x2000000) != 0); | |
} | |
return bUnison; | |
} | |
CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict) | |
{ | |
m_pDict = pDict; | |
m_Type = Unknown; | |
m_pForm = pForm; | |
m_pFont = NULL; | |
m_FontSize = 0; | |
SyncFieldFlags(); | |
} | |
CPDF_FormField::~CPDF_FormField() | |
{ | |
} | |
void CPDF_FormField::SyncFieldFlags() | |
{ | |
CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT")->GetString(); | |
FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger(); | |
m_Flags = 0; | |
if (flags & 1) { | |
m_Flags |= FORMFIELD_READONLY; | |
} | |
if (flags & 2) { | |
m_Flags |= FORMFIELD_REQUIRED; | |
} | |
if (flags & 4) { | |
m_Flags |= FORMFIELD_NOEXPORT; | |
} | |
if (type_name == "Btn") { | |
if (flags & 0x8000) { | |
m_Type = RadioButton; | |
if (flags & 0x4000) { | |
m_Flags |= FORMRADIO_NOTOGGLEOFF; | |
} | |
if (flags & 0x2000000) { | |
m_Flags |= FORMRADIO_UNISON; | |
} | |
} else if (flags & 0x10000) { | |
m_Type = PushButton; | |
} else { | |
m_Type = CheckBox; | |
} | |
} else if (type_name == "Tx") { | |
if (flags & 0x100000) { | |
m_Type = File; | |
} else if (flags & 0x2000000) { | |
m_Type = RichText; | |
} else { | |
m_Type = Text; | |
if (flags & 0x1000) { | |
m_Flags |= FORMTEXT_MULTILINE; | |
} | |
if (flags & 0x2000) { | |
m_Flags |= FORMTEXT_PASSWORD; | |
} | |
if (flags & 0x800000) { | |
m_Flags |= FORMTEXT_NOSCROLL; | |
} | |
if (flags & 0x100000) { | |
m_Flags |= FORMTEXT_COMB; | |
} | |
} | |
LoadDA(); | |
} else if (type_name == "Ch") { | |
if (flags & 0x20000) { | |
m_Type = ComboBox; | |
if (flags & 0x40000) { | |
m_Flags |= FORMCOMBO_EDIT; | |
} | |
} else { | |
m_Type = ListBox; | |
if (flags & 0x200000) { | |
m_Flags |= FORMLIST_MULTISELECT; | |
} | |
} | |
LoadDA(); | |
} else if (type_name == "Sig") { | |
m_Type = Sign; | |
} | |
} | |
CFX_WideString CPDF_FormField::GetFullName() | |
{ | |
return ::GetFullName(m_pDict); | |
} | |
FX_BOOL CPDF_FormField::ResetField(FX_BOOL bNotify) | |
{ | |
switch (m_Type) { | |
case CPDF_FormField::CheckBox: | |
case CPDF_FormField::RadioButton: { | |
CFX_ByteArray statusArray; | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
SaveCheckedFieldStatus(this, statusArray); | |
} | |
int iCount = CountControls(); | |
if (iCount) { | |
if (PDF_FormField_IsUnison(this)) { | |
for(int i = 0; i < iCount; i++) { | |
CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE); | |
} | |
} else { | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pControl = GetControl(i); | |
FX_BOOL bChecked = pControl->IsDefaultChecked(); | |
CheckControl(i, bChecked, FALSE); | |
} | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray); | |
} | |
} | |
break; | |
case CPDF_FormField::ComboBox: { | |
CFX_WideString csValue; | |
ClearSelection(); | |
int iIndex = GetDefaultSelectedItem(); | |
if (iIndex >= 0) { | |
csValue = GetOptionLabel(iIndex); | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
SetItemSelection(iIndex, TRUE); | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
} | |
break; | |
case CPDF_FormField::ListBox: { | |
CFX_WideString csValue; | |
ClearSelection(); | |
int iIndex = GetDefaultSelectedItem(); | |
if (iIndex >= 0) { | |
csValue = GetOptionLabel(iIndex); | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
SetItemSelection(iIndex, TRUE); | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
} | |
break; | |
case CPDF_FormField::Text: | |
case CPDF_FormField::RichText: | |
case CPDF_FormField::File: | |
default: { | |
CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV"); | |
CFX_WideString csDValue; | |
if (pDV != NULL) { | |
csDValue = pDV->GetUnicodeText(); | |
} | |
CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V"); | |
CFX_WideString csValue; | |
if (pV != NULL) { | |
csValue = pV->GetUnicodeText(); | |
} | |
CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV"); | |
if (!pRV && (csDValue == csValue)) { | |
return FALSE; | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csDValue); | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
if (pDV == NULL) { | |
m_pDict->RemoveAt("V"); | |
m_pDict->RemoveAt("RV"); | |
} else { | |
CPDF_Object* pClone = pDV->Clone(); | |
if (pClone == NULL) { | |
return FALSE; | |
} | |
m_pDict->SetAt("V", pClone); | |
if(pRV) { | |
CPDF_Object* pCloneR = pDV->Clone(); | |
m_pDict->SetAt("RV", pCloneR); | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
} | |
break; | |
} | |
return TRUE; | |
} | |
int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl) | |
{ | |
if (pControl == NULL) { | |
return -1; | |
} | |
int iCount = m_ControlList.GetSize(); | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pFind = (CPDF_FormControl*)m_ControlList.GetAt(i); | |
if (pFind == pControl) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
int CPDF_FormField::GetFieldType() | |
{ | |
switch (m_Type) { | |
case PushButton: | |
return FIELDTYPE_PUSHBUTTON; | |
case CheckBox: | |
return FIELDTYPE_CHECKBOX; | |
case RadioButton: | |
return FIELDTYPE_RADIOBUTTON; | |
case ComboBox: | |
return FIELDTYPE_COMBOBOX; | |
case ListBox: | |
return FIELDTYPE_LISTBOX; | |
case Text: | |
case RichText: | |
case File: | |
return FIELDTYPE_TEXTFIELD; | |
case Sign: | |
return FIELDTYPE_SIGNATURE; | |
default: | |
break; | |
} | |
return FIELDTYPE_UNKNOWN; | |
} | |
CPDF_AAction CPDF_FormField::GetAdditionalAction() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA"); | |
if (pObj == NULL) { | |
return NULL; | |
} | |
return pObj->GetDict(); | |
} | |
CFX_WideString CPDF_FormField::GetAlternateName() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU"); | |
if (pObj == NULL) { | |
return L""; | |
} | |
return pObj->GetUnicodeText(); | |
} | |
CFX_WideString CPDF_FormField::GetMappingName() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM"); | |
if (pObj == NULL) { | |
return L""; | |
} | |
return pObj->GetUnicodeText(); | |
} | |
FX_DWORD CPDF_FormField::GetFieldFlags() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff"); | |
if (pObj == NULL) { | |
return 0; | |
} | |
return pObj->GetInteger(); | |
} | |
CFX_ByteString CPDF_FormField::GetDefaultStyle() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS"); | |
if (pObj == NULL) { | |
return ""; | |
} | |
return pObj->GetString(); | |
} | |
CFX_WideString CPDF_FormField::GetRichTextString() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV"); | |
if (pObj == NULL) { | |
return L""; | |
} | |
return pObj->GetUnicodeText(); | |
} | |
CFX_WideString CPDF_FormField::GetValue(FX_BOOL bDefault) | |
{ | |
if (GetType() == CheckBox || GetType() == RadioButton) { | |
return GetCheckValue(bDefault); | |
} | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V"); | |
if (pValue == NULL) { | |
if (!bDefault) { | |
if (m_Type == RichText) { | |
pValue = FPDF_GetFieldAttr(m_pDict, "V"); | |
} | |
if (pValue == NULL && m_Type != Text) { | |
pValue = FPDF_GetFieldAttr(m_pDict, "DV"); | |
} | |
} | |
if (pValue == NULL) { | |
return CFX_WideString(); | |
} | |
} | |
switch (pValue->GetType()) { | |
case PDFOBJ_STRING: | |
case PDFOBJ_STREAM: | |
return pValue->GetUnicodeText(); | |
case PDFOBJ_ARRAY: | |
pValue = ((CPDF_Array*)pValue)->GetElementValue(0); | |
return pValue->GetUnicodeText(); | |
break; | |
} | |
return CFX_WideString(); | |
} | |
CFX_WideString CPDF_FormField::GetValue() | |
{ | |
return GetValue(FALSE); | |
} | |
CFX_WideString CPDF_FormField::GetDefaultValue() | |
{ | |
return GetValue(TRUE); | |
} | |
FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify) | |
{ | |
switch (m_Type) { | |
case CheckBox: | |
case RadioButton: { | |
SetCheckValue(value, bDefault, bNotify); | |
return TRUE; | |
} | |
case File: | |
case RichText: | |
case Text: | |
case ComboBox: { | |
CFX_WideString csValue = value; | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
int iIndex = FindOptionValue(csValue); | |
if (iIndex < 0) { | |
CFX_ByteString bsEncodeText = PDF_EncodeText(csValue); | |
m_pDict->SetAtString(bDefault ? "DV" : "V", bsEncodeText); | |
if (m_Type == RichText && !bDefault) { | |
m_pDict->SetAtString("RV", bsEncodeText); | |
} | |
m_pDict->RemoveAt("I"); | |
} else { | |
m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue)); | |
if (bDefault) { | |
} else { | |
ClearSelection(); | |
SetItemSelection(iIndex, TRUE); | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
} | |
break; | |
case ListBox: { | |
int iIndex = FindOptionValue(value); | |
if (iIndex < 0) { | |
return FALSE; | |
} | |
if (bDefault && iIndex == GetDefaultSelectedItem()) { | |
return FALSE; | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
CFX_WideString csValue = value; | |
int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
if (bDefault) { | |
} else { | |
ClearSelection(); | |
SetItemSelection(iIndex, TRUE); | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
break; | |
} | |
default: | |
break; | |
} | |
if (CPDF_InterForm::m_bUpdateAP) { | |
UpdateAP(NULL); | |
} | |
return TRUE; | |
} | |
FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify) | |
{ | |
return SetValue(value, FALSE, bNotify); | |
} | |
int CPDF_FormField::GetMaxLen() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen"); | |
if (pObj == NULL) { | |
int iCount = m_ControlList.GetSize(); | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pControl = (CPDF_FormControl*)m_ControlList.GetAt(i); | |
if (pControl == NULL) { | |
continue; | |
} | |
CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict; | |
if (pWidgetDict->KeyExist("MaxLen")) { | |
return pWidgetDict->GetInteger("MaxLen"); | |
} | |
} | |
return 0; | |
} | |
return pObj->GetInteger(); | |
} | |
int CPDF_FormField::CountSelectedItems() | |
{ | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); | |
if (pValue == NULL) { | |
pValue = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pValue == NULL) { | |
return 0; | |
} | |
} | |
if (pValue->GetType() == PDFOBJ_STRING) { | |
if (pValue->GetString().IsEmpty()) { | |
return 0; | |
} | |
return 1; | |
} | |
if (pValue->GetType() == PDFOBJ_NUMBER) { | |
if (pValue->GetString().IsEmpty()) { | |
return 0; | |
} | |
return 1; | |
} | |
if (pValue->GetType() != PDFOBJ_ARRAY) { | |
return 0; | |
} | |
return ((CPDF_Array*)pValue)->GetCount(); | |
} | |
int CPDF_FormField::GetSelectedIndex(int index) | |
{ | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); | |
if (pValue == NULL) { | |
pValue = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pValue == NULL) { | |
return -1; | |
} | |
} | |
CFX_WideString sel_value; | |
if (pValue->GetType() == PDFOBJ_STRING) { | |
if (index != 0) { | |
return -1; | |
} | |
sel_value = pValue->GetUnicodeText(); | |
} else if (pValue->GetType() == PDFOBJ_NUMBER) { | |
return pValue->GetInteger(); | |
} else { | |
if (pValue->GetType() != PDFOBJ_ARRAY) { | |
return -1; | |
} | |
if (index < 0) { | |
return -1; | |
} | |
sel_value = ((CPDF_Array*)pValue)->GetElementValue(index)->GetUnicodeText(); | |
} | |
if (index < CountSelectedOptions()) { | |
int iOptIndex = GetSelectedOptionIndex(index); | |
CFX_WideString csOpt = GetOptionValue(iOptIndex); | |
if (csOpt == sel_value) { | |
return iOptIndex; | |
} | |
} | |
int nOpts = CountOptions(); | |
for (int i = 0; i < nOpts; i ++) { | |
if (sel_value == GetOptionValue(i)) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify) | |
{ | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = 0; | |
CFX_WideString csValue; | |
int iIndex = GetSelectedIndex(0); | |
if (iIndex >= 0) { | |
csValue = GetOptionLabel(iIndex); | |
} | |
if (GetType() == ListBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
} | |
if (GetType() == ComboBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
} | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
m_pDict->RemoveAt("V"); | |
m_pDict->RemoveAt("I"); | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
if (GetType() == ListBox) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
if (GetType() == ComboBox) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
} | |
if (CPDF_InterForm::m_bUpdateAP) { | |
UpdateAP(NULL); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
FX_BOOL CPDF_FormField::IsItemSelected(int index) | |
{ | |
ASSERT(GetType() == ComboBox || GetType() == ListBox); | |
if (index < 0 || index >= CountOptions()) { | |
return FALSE; | |
} | |
if (IsOptionSelected(index)) { | |
return TRUE; | |
} | |
CFX_WideString opt_value = GetOptionValue(index); | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); | |
if (pValue == NULL) { | |
pValue = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pValue == NULL) { | |
return FALSE; | |
} | |
} | |
if (pValue->GetType() == PDFOBJ_STRING) { | |
if (pValue->GetUnicodeText() == opt_value) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
if (pValue->GetType() == PDFOBJ_NUMBER) { | |
if (pValue->GetString().IsEmpty()) { | |
return FALSE; | |
} | |
if (pValue->GetInteger() == index) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
if (pValue->GetType() != PDFOBJ_ARRAY) { | |
return FALSE; | |
} | |
CPDF_Array* pArray = (CPDF_Array*)pValue; | |
int iPos = -1; | |
for (int j = 0; j < CountSelectedOptions(); j ++) { | |
if (GetSelectedOptionIndex(j) == index) { | |
iPos = j; | |
break; | |
} | |
} | |
for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) | |
if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value && (int)i == iPos) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
FX_BOOL CPDF_FormField::SetItemSelection(int index, FX_BOOL bSelected, FX_BOOL bNotify) | |
{ | |
ASSERT(GetType() == ComboBox || GetType() == ListBox); | |
if (index < 0 || index >= CountOptions()) { | |
return FALSE; | |
} | |
CFX_WideString opt_value = GetOptionValue(index); | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = 0; | |
if (GetType() == ListBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value); | |
} | |
if (GetType() == ComboBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value); | |
} | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
if (!bSelected) { | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V"); | |
if (pValue != NULL) { | |
if (m_Type == ListBox) { | |
SelectOption(index, FALSE); | |
if (pValue->GetType() == PDFOBJ_STRING) { | |
if (pValue->GetUnicodeText() == opt_value) { | |
m_pDict->RemoveAt("V"); | |
} | |
} else if (pValue->GetType() == PDFOBJ_ARRAY) { | |
CPDF_Array* pArray = CPDF_Array::Create(); | |
if (pArray == NULL) { | |
return FALSE; | |
} | |
int iCount = CountOptions(); | |
for (int i = 0; i < iCount; i ++) { | |
if (i != index) { | |
if (IsItemSelected(i)) { | |
opt_value = GetOptionValue(i); | |
pArray->AddString(PDF_EncodeText(opt_value)); | |
} | |
} | |
} | |
if (pArray->GetCount() < 1) { | |
pArray->Release(); | |
} else { | |
m_pDict->SetAt("V", pArray); | |
} | |
} | |
} else if (m_Type == ComboBox) { | |
m_pDict->RemoveAt("V"); | |
m_pDict->RemoveAt("I"); | |
} | |
} | |
} else { | |
if (m_Type == ListBox) { | |
SelectOption(index, TRUE); | |
if (!(m_Flags & FORMLIST_MULTISELECT)) { | |
m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength())); | |
} else { | |
CPDF_Array* pArray = CPDF_Array::Create(); | |
if (pArray == NULL) { | |
return FALSE; | |
} | |
FX_BOOL bSelected; | |
int iCount = CountOptions(); | |
for (int i = 0; i < iCount; i ++) { | |
if (i != index) { | |
bSelected = IsItemSelected(i); | |
} else { | |
bSelected = TRUE; | |
} | |
if (bSelected) { | |
opt_value = GetOptionValue(i); | |
pArray->AddString(PDF_EncodeText(opt_value)); | |
} | |
} | |
m_pDict->SetAt("V", pArray); | |
} | |
} else if (m_Type == ComboBox) { | |
m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength())); | |
CPDF_Array* pI = CPDF_Array::Create(); | |
if (pI == NULL) { | |
return FALSE; | |
} | |
pI->AddInteger(index); | |
m_pDict->SetAt("I", pI); | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
if (GetType() == ListBox) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
if (GetType() == ComboBox) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
} | |
if (CPDF_InterForm::m_bUpdateAP) { | |
UpdateAP(NULL); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index) | |
{ | |
ASSERT(GetType() == ComboBox || GetType() == ListBox); | |
if (index < 0 || index >= CountOptions()) { | |
return FALSE; | |
} | |
int iDVIndex = GetDefaultSelectedItem(); | |
if (iDVIndex < 0) { | |
return FALSE; | |
} | |
return (iDVIndex == index); | |
} | |
int CPDF_FormField::GetDefaultSelectedItem() | |
{ | |
ASSERT(GetType() == ComboBox || GetType() == ListBox); | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV"); | |
if (pValue == NULL) { | |
return -1; | |
} | |
CFX_WideString csDV = pValue->GetUnicodeText(); | |
if (csDV.IsEmpty()) { | |
return -1; | |
} | |
int iCount = CountOptions(); | |
for (int i = 0; i < iCount; i ++) { | |
if (csDV == GetOptionValue(i)) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl) | |
{ | |
if (m_Type == PushButton) { | |
return; | |
} | |
if (m_Type == RadioButton || m_Type == CheckBox) { | |
return; | |
} | |
if (!m_pForm->m_bGenerateAP) { | |
return; | |
} | |
for (int i = 0; i < CountControls(); i ++) { | |
CPDF_FormControl* pControl = GetControl(i); | |
FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict); | |
} | |
} | |
int CPDF_FormField::CountOptions() | |
{ | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt"); | |
if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) { | |
return 0; | |
} | |
return ((CPDF_Array*)pValue)->GetCount(); | |
} | |
CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index) | |
{ | |
CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt"); | |
if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) { | |
return CFX_WideString(); | |
} | |
CPDF_Object* pOption = ((CPDF_Array*)pValue)->GetElementValue(index); | |
if (pOption == NULL) { | |
return CFX_WideString(); | |
} | |
if (pOption->GetType() == PDFOBJ_ARRAY) { | |
pOption = ((CPDF_Array*)pOption)->GetElementValue(sub_index); | |
} | |
if (pOption == NULL || pOption->GetType() != PDFOBJ_STRING) { | |
return CFX_WideString(); | |
} | |
return ((CPDF_String*)pOption)->GetUnicodeText(); | |
} | |
CFX_WideString CPDF_FormField::GetOptionLabel(int index) | |
{ | |
return GetOptionText(index, 1); | |
} | |
CFX_WideString CPDF_FormField::GetOptionValue(int index) | |
{ | |
return GetOptionText(index, 0); | |
} | |
int CPDF_FormField::FindOption(CFX_WideString csOptLabel) | |
{ | |
int iCount = CountOptions(); | |
for (int i = 0; i < iCount; i ++) { | |
CFX_WideString csValue = GetOptionValue(i); | |
if (csValue == csOptLabel) { | |
return i; | |
} | |
} | |
return -1; | |
} | |
int CPDF_FormField::FindOptionValue(FX_LPCWSTR csOptValue, int iStartIndex) | |
{ | |
if (iStartIndex < 0) { | |
iStartIndex = 0; | |
} | |
int iCount = CountOptions(); | |
for (; iStartIndex < iCount; iStartIndex ++) { | |
CFX_WideString csValue = GetOptionValue(iStartIndex); | |
if (csValue == csOptValue) { | |
return iStartIndex; | |
} | |
} | |
return -1; | |
} | |
FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify) | |
{ | |
ASSERT(GetType() == CheckBox || GetType() == RadioButton); | |
CPDF_FormControl* pControl = GetControl(iControlIndex); | |
if (pControl == NULL) { | |
return FALSE; | |
} | |
if (!bChecked && pControl->IsChecked() == bChecked) { | |
return FALSE; | |
} | |
CFX_ByteArray statusArray; | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
SaveCheckedFieldStatus(this, statusArray); | |
} | |
CFX_WideString csWExport = pControl->GetExportValue(); | |
CFX_ByteString csBExport = PDF_EncodeText(csWExport); | |
int iCount = CountControls(); | |
FX_BOOL bUnison = PDF_FormField_IsUnison(this); | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pCtrl = GetControl(i); | |
if (bUnison) { | |
CFX_WideString csEValue = pCtrl->GetExportValue(); | |
if (csEValue == csWExport) { | |
if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) { | |
pCtrl->CheckControl(bChecked); | |
} else if (bChecked) { | |
pCtrl->CheckControl(FALSE); | |
} | |
} else if (bChecked) { | |
pCtrl->CheckControl(FALSE); | |
} | |
} else { | |
if (i == iControlIndex) { | |
pCtrl->CheckControl(bChecked); | |
} else if (bChecked) { | |
pCtrl->CheckControl(FALSE); | |
} | |
} | |
} | |
CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt"); | |
if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) { | |
if (bChecked) { | |
m_pDict->SetAtName("V", csBExport); | |
} else { | |
CFX_ByteString csV; | |
CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V"); | |
if (pV != NULL) { | |
csV = pV->GetString(); | |
} | |
if (csV == csBExport) { | |
m_pDict->SetAtName("V", "Off"); | |
} | |
} | |
} else if (bChecked) { | |
CFX_ByteString csIndex; | |
csIndex.Format("%d", iControlIndex); | |
m_pDict->SetAtName("V", csIndex); | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault) | |
{ | |
ASSERT(GetType() == CheckBox || GetType() == RadioButton); | |
CFX_WideString csExport = L"Off"; | |
FX_BOOL bChecked; | |
int iCount = CountControls(); | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pControl = GetControl(i); | |
if (bDefault) { | |
bChecked = pControl->IsDefaultChecked(); | |
} else { | |
bChecked = pControl->IsChecked(); | |
} | |
if (bChecked) { | |
csExport = pControl->GetExportValue(); | |
break; | |
} | |
} | |
return csExport; | |
} | |
FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify) | |
{ | |
ASSERT(GetType() == CheckBox || GetType() == RadioButton); | |
CFX_ByteArray statusArray; | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
SaveCheckedFieldStatus(this, statusArray); | |
} | |
int iCount = CountControls(); | |
for (int i = 0; i < iCount; i ++) { | |
CPDF_FormControl* pControl = GetControl(i); | |
CFX_WideString csExport = pControl->GetExportValue(); | |
if (csExport == value) { | |
if (bDefault) { | |
} else { | |
CheckControl(GetControlIndex(pControl), TRUE); | |
} | |
break; | |
} else { | |
if (bDefault) { | |
} else { | |
CheckControl(GetControlIndex(pControl), FALSE); | |
} | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray); | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
int CPDF_FormField::GetTopVisibleIndex() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI"); | |
if (pObj == NULL) { | |
return 0; | |
} | |
return pObj->GetInteger(); | |
} | |
int CPDF_FormField::CountSelectedOptions() | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pObj == NULL) { | |
return 0; | |
} | |
CPDF_Array* pArray = pObj->GetArray(); | |
if (pArray == NULL) { | |
return 0; | |
} | |
return (int)pArray->GetCount(); | |
} | |
int CPDF_FormField::GetSelectedOptionIndex(int index) | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pObj == NULL) { | |
return -1; | |
} | |
CPDF_Array* pArray = pObj->GetArray(); | |
if (pArray == NULL) { | |
return -1; | |
} | |
int iCount = (int)pArray->GetCount(); | |
if (iCount > 0 && index < iCount) { | |
return pArray->GetInteger(index); | |
} | |
return -1; | |
} | |
FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex) | |
{ | |
CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I"); | |
if (pObj == NULL) { | |
return FALSE; | |
} | |
CPDF_Array* pArray = pObj->GetArray(); | |
if (pArray == NULL) { | |
return FALSE; | |
} | |
int iCount = (int)pArray->GetCount(); | |
for (int i = 0; i < iCount; i ++) { | |
if (pArray->GetInteger(i) == iOptIndex) { | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify) | |
{ | |
CPDF_Array* pArray = m_pDict->GetArray("I"); | |
if (pArray == NULL) { | |
if (!bSelected) { | |
return TRUE; | |
} | |
pArray = CPDF_Array::Create(); | |
if (pArray == NULL) { | |
return FALSE; | |
} | |
m_pDict->SetAt("I", pArray); | |
} | |
FX_BOOL bReturn = FALSE; | |
for (int i = 0; i < (int)pArray->GetCount(); i ++) { | |
int iFind = pArray->GetInteger(i); | |
if (iFind == iOptIndex) { | |
if (bSelected) { | |
return TRUE; | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = 0; | |
CFX_WideString csValue = GetOptionLabel(iOptIndex); | |
if (GetType() == ListBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
} | |
if (GetType() == ComboBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
} | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
pArray->RemoveAt(i); | |
bReturn = TRUE; | |
break; | |
} else if (iFind > iOptIndex) { | |
if (!bSelected) { | |
continue; | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = 0; | |
CFX_WideString csValue = GetOptionLabel(iOptIndex); | |
if (GetType() == ListBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
} | |
if (GetType() == ComboBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
} | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
CPDF_Number* pNum = CPDF_Number::Create(iOptIndex); | |
if (pNum == NULL) { | |
return FALSE; | |
} | |
pArray->InsertAt(i, pNum); | |
bReturn = TRUE; | |
break; | |
} | |
} | |
if (!bReturn) { | |
if (bSelected) { | |
pArray->AddInteger(iOptIndex); | |
} | |
if (pArray->GetCount() == 0) { | |
m_pDict->RemoveAt("I"); | |
} | |
} | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
if (GetType() == ListBox) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
if (GetType() == ComboBox) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify) | |
{ | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
int iRet = 0; | |
CFX_WideString csValue; | |
int iIndex = GetSelectedIndex(0); | |
if (iIndex >= 0) { | |
csValue = GetOptionLabel(iIndex); | |
} | |
if (GetType() == ListBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue); | |
} | |
if (GetType() == ComboBox) { | |
iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue); | |
} | |
if (iRet < 0) { | |
return FALSE; | |
} | |
} | |
m_pDict->RemoveAt("I"); | |
if (bNotify && m_pForm->m_pFormNotify != NULL) { | |
if (GetType() == ListBox) { | |
m_pForm->m_pFormNotify->AfterSelectionChange(this); | |
} | |
if (GetType() == ComboBox) { | |
m_pForm->m_pFormNotify->AfterValueChange(this); | |
} | |
} | |
m_pForm->m_bUpdated = TRUE; | |
return TRUE; | |
} | |
void CPDF_FormField::LoadDA() | |
{ | |
CFX_ByteString DA = FPDF_GetFieldAttr(m_pDict, "DA")->GetString(); | |
if (DA.IsEmpty()) { | |
DA = m_pForm->m_pFormDict->GetString("DA"); | |
} | |
if (DA.IsEmpty()) { | |
return; | |
} | |
CPDF_SimpleParser syntax(DA); | |
syntax.FindTagParam("Tf", 2); | |
CFX_ByteString font_name = syntax.GetWord(); | |
CPDF_Dictionary* pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name); | |
if (pFontDict == NULL) { | |
return; | |
} | |
m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict); | |
m_FontSize = FX_atof(syntax.GetWord()); | |
} |