Home | History | Annotate | Download | only in fpdfdoc
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../include/fpdfdoc/fpdf_doc.h"
      8 CFX_WideString		GetFullName(CPDF_Dictionary* pFieldDict);
      9 void				SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
     10 FX_BOOL PDF_FormField_IsUnison(CPDF_FormField *pField)
     11 {
     12     FX_BOOL bUnison = FALSE;
     13     if (pField->GetType() == CPDF_FormField::CheckBox) {
     14         bUnison = TRUE;
     15     } else {
     16         FX_DWORD dwFlags = pField->GetFieldFlags();
     17         bUnison = ((dwFlags & 0x2000000) != 0);
     18     }
     19     return bUnison;
     20 }
     21 CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict)
     22 {
     23     m_pDict = pDict;
     24     m_Type = Unknown;
     25     m_pForm = pForm;
     26     m_pFont = NULL;
     27     m_FontSize = 0;
     28     SyncFieldFlags();
     29 }
     30 CPDF_FormField::~CPDF_FormField()
     31 {
     32 }
     33 void CPDF_FormField::SyncFieldFlags()
     34 {
     35     CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT")->GetString();
     36     FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger();
     37     m_Flags = 0;
     38     if (flags & 1) {
     39         m_Flags |= FORMFIELD_READONLY;
     40     }
     41     if (flags & 2) {
     42         m_Flags |= FORMFIELD_REQUIRED;
     43     }
     44     if (flags & 4) {
     45         m_Flags |= FORMFIELD_NOEXPORT;
     46     }
     47     if (type_name == "Btn") {
     48         if (flags & 0x8000) {
     49             m_Type = RadioButton;
     50             if (flags & 0x4000) {
     51                 m_Flags |= FORMRADIO_NOTOGGLEOFF;
     52             }
     53             if (flags & 0x2000000) {
     54                 m_Flags |= FORMRADIO_UNISON;
     55             }
     56         } else if (flags & 0x10000) {
     57             m_Type = PushButton;
     58         } else {
     59             m_Type = CheckBox;
     60         }
     61     } else if (type_name == "Tx") {
     62         if (flags & 0x100000) {
     63             m_Type = File;
     64         } else if (flags & 0x2000000) {
     65             m_Type = RichText;
     66         } else {
     67             m_Type = Text;
     68             if (flags & 0x1000) {
     69                 m_Flags |= FORMTEXT_MULTILINE;
     70             }
     71             if (flags & 0x2000) {
     72                 m_Flags |= FORMTEXT_PASSWORD;
     73             }
     74             if (flags & 0x800000) {
     75                 m_Flags |= FORMTEXT_NOSCROLL;
     76             }
     77             if (flags & 0x100000) {
     78                 m_Flags |= FORMTEXT_COMB;
     79             }
     80         }
     81         LoadDA();
     82     } else if (type_name == "Ch") {
     83         if (flags & 0x20000) {
     84             m_Type = ComboBox;
     85             if (flags & 0x40000) {
     86                 m_Flags |= FORMCOMBO_EDIT;
     87             }
     88         } else {
     89             m_Type = ListBox;
     90             if (flags & 0x200000) {
     91                 m_Flags |= FORMLIST_MULTISELECT;
     92             }
     93         }
     94         LoadDA();
     95     } else if (type_name == "Sig") {
     96         m_Type = Sign;
     97     }
     98 }
     99 CFX_WideString CPDF_FormField::GetFullName()
    100 {
    101     return ::GetFullName(m_pDict);
    102 }
    103 FX_BOOL CPDF_FormField::ResetField(FX_BOOL bNotify)
    104 {
    105     switch (m_Type) {
    106         case CPDF_FormField::CheckBox:
    107         case CPDF_FormField::RadioButton: {
    108                 CFX_ByteArray statusArray;
    109                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    110                     SaveCheckedFieldStatus(this, statusArray);
    111                 }
    112                 int iCount = CountControls();
    113                 if (iCount) {
    114                     if (PDF_FormField_IsUnison(this)) {
    115                         for(int i = 0; i < iCount; i++) {
    116                             CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE);
    117                         }
    118                     } else {
    119                         for (int i = 0; i < iCount; i ++) {
    120                             CPDF_FormControl* pControl = GetControl(i);
    121                             FX_BOOL bChecked = pControl->IsDefaultChecked();
    122                             CheckControl(i, bChecked, FALSE);
    123                         }
    124                     }
    125                 }
    126                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    127                     m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
    128                 }
    129             }
    130             break;
    131         case CPDF_FormField::ComboBox: {
    132                 CFX_WideString csValue;
    133                 ClearSelection();
    134                 int iIndex = GetDefaultSelectedItem();
    135                 if (iIndex >= 0) {
    136                     csValue = GetOptionLabel(iIndex);
    137                 }
    138                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    139                     int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    140                     if (iRet < 0) {
    141                         return FALSE;
    142                     }
    143                 }
    144                 SetItemSelection(iIndex, TRUE);
    145                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    146                     m_pForm->m_pFormNotify->AfterValueChange(this);
    147                 }
    148             }
    149             break;
    150         case CPDF_FormField::ListBox: {
    151                 CFX_WideString csValue;
    152                 ClearSelection();
    153                 int iIndex = GetDefaultSelectedItem();
    154                 if (iIndex >= 0) {
    155                     csValue = GetOptionLabel(iIndex);
    156                 }
    157                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    158                     int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    159                     if (iRet < 0) {
    160                         return FALSE;
    161                     }
    162                 }
    163                 SetItemSelection(iIndex, TRUE);
    164                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    165                     m_pForm->m_pFormNotify->AfterSelectionChange(this);
    166                 }
    167             }
    168             break;
    169         case CPDF_FormField::Text:
    170         case CPDF_FormField::RichText:
    171         case CPDF_FormField::File:
    172         default: {
    173                 CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV");
    174                 CFX_WideString csDValue;
    175                 if (pDV != NULL) {
    176                     csDValue = pDV->GetUnicodeText();
    177                 }
    178                 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
    179                 CFX_WideString csValue;
    180                 if (pV != NULL) {
    181                     csValue = pV->GetUnicodeText();
    182                 }
    183                 CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV");
    184                 if (!pRV && (csDValue == csValue)) {
    185                     return FALSE;
    186                 }
    187                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    188                     int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csDValue);
    189                     if (iRet < 0) {
    190                         return FALSE;
    191                     }
    192                 }
    193                 if (pDV == NULL) {
    194                     m_pDict->RemoveAt("V");
    195                     m_pDict->RemoveAt("RV");
    196                 } else {
    197                     CPDF_Object* pClone = pDV->Clone();
    198                     if (pClone == NULL) {
    199                         return FALSE;
    200                     }
    201                     m_pDict->SetAt("V", pClone);
    202                     if(pRV) {
    203                         CPDF_Object* pCloneR = pDV->Clone();
    204                         m_pDict->SetAt("RV", pCloneR);
    205                     }
    206                 }
    207                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    208                     m_pForm->m_pFormNotify->AfterValueChange(this);
    209                 }
    210                 m_pForm->m_bUpdated = TRUE;
    211             }
    212             break;
    213     }
    214     return TRUE;
    215 }
    216 int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl)
    217 {
    218     if (pControl == NULL) {
    219         return -1;
    220     }
    221     int iCount = m_ControlList.GetSize();
    222     for (int i = 0; i < iCount; i ++) {
    223         CPDF_FormControl* pFind = (CPDF_FormControl*)m_ControlList.GetAt(i);
    224         if (pFind == pControl) {
    225             return i;
    226         }
    227     }
    228     return -1;
    229 }
    230 int CPDF_FormField::GetFieldType()
    231 {
    232     switch (m_Type) {
    233         case PushButton:
    234             return FIELDTYPE_PUSHBUTTON;
    235         case CheckBox:
    236             return FIELDTYPE_CHECKBOX;
    237         case RadioButton:
    238             return FIELDTYPE_RADIOBUTTON;
    239         case ComboBox:
    240             return FIELDTYPE_COMBOBOX;
    241         case ListBox:
    242             return FIELDTYPE_LISTBOX;
    243         case Text:
    244         case RichText:
    245         case File:
    246             return FIELDTYPE_TEXTFIELD;
    247         case Sign:
    248             return FIELDTYPE_SIGNATURE;
    249         default:
    250             break;
    251     }
    252     return FIELDTYPE_UNKNOWN;
    253 }
    254 CPDF_AAction CPDF_FormField::GetAdditionalAction()
    255 {
    256     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA");
    257     if (pObj == NULL) {
    258         return NULL;
    259     }
    260     return pObj->GetDict();
    261 }
    262 CFX_WideString CPDF_FormField::GetAlternateName()
    263 {
    264     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU");
    265     if (pObj == NULL) {
    266         return L"";
    267     }
    268     return pObj->GetUnicodeText();
    269 }
    270 CFX_WideString CPDF_FormField::GetMappingName()
    271 {
    272     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM");
    273     if (pObj == NULL) {
    274         return L"";
    275     }
    276     return pObj->GetUnicodeText();
    277 }
    278 FX_DWORD CPDF_FormField::GetFieldFlags()
    279 {
    280     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff");
    281     if (pObj == NULL) {
    282         return 0;
    283     }
    284     return pObj->GetInteger();
    285 }
    286 CFX_ByteString CPDF_FormField::GetDefaultStyle()
    287 {
    288     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS");
    289     if (pObj == NULL) {
    290         return "";
    291     }
    292     return pObj->GetString();
    293 }
    294 CFX_WideString CPDF_FormField::GetRichTextString()
    295 {
    296     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV");
    297     if (pObj == NULL) {
    298         return L"";
    299     }
    300     return pObj->GetUnicodeText();
    301 }
    302 CFX_WideString CPDF_FormField::GetValue(FX_BOOL bDefault)
    303 {
    304     if (GetType() == CheckBox || GetType() == RadioButton) {
    305         return GetCheckValue(bDefault);
    306     }
    307     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V");
    308     if (pValue == NULL) {
    309         if (!bDefault) {
    310             if (m_Type == RichText) {
    311                 pValue = FPDF_GetFieldAttr(m_pDict, "V");
    312             }
    313             if (pValue == NULL && m_Type != Text) {
    314                 pValue = FPDF_GetFieldAttr(m_pDict, "DV");
    315             }
    316         }
    317         if (pValue == NULL) {
    318             return CFX_WideString();
    319         }
    320     }
    321     switch (pValue->GetType()) {
    322         case PDFOBJ_STRING:
    323         case PDFOBJ_STREAM:
    324             return pValue->GetUnicodeText();
    325         case PDFOBJ_ARRAY:
    326             pValue = ((CPDF_Array*)pValue)->GetElementValue(0);
    327             return pValue->GetUnicodeText();
    328             break;
    329     }
    330     return CFX_WideString();
    331 }
    332 CFX_WideString CPDF_FormField::GetValue()
    333 {
    334     return GetValue(FALSE);
    335 }
    336 CFX_WideString CPDF_FormField::GetDefaultValue()
    337 {
    338     return GetValue(TRUE);
    339 }
    340 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
    341 {
    342     switch (m_Type) {
    343         case CheckBox:
    344         case RadioButton: {
    345                 SetCheckValue(value, bDefault, bNotify);
    346                 return TRUE;
    347             }
    348         case File:
    349         case RichText:
    350         case Text:
    351         case ComboBox: {
    352                 CFX_WideString csValue = value;
    353                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    354                     int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    355                     if (iRet < 0) {
    356                         return FALSE;
    357                     }
    358                 }
    359                 int iIndex = FindOptionValue(csValue);
    360                 if (iIndex < 0) {
    361                     CFX_ByteString bsEncodeText = PDF_EncodeText(csValue);
    362                     m_pDict->SetAtString(bDefault ? "DV" : "V", bsEncodeText);
    363                     if (m_Type == RichText && !bDefault) {
    364                         m_pDict->SetAtString("RV", bsEncodeText);
    365                     }
    366                     m_pDict->RemoveAt("I");
    367                 } else {
    368                     m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue));
    369                     if (bDefault) {
    370                     } else {
    371                         ClearSelection();
    372                         SetItemSelection(iIndex, TRUE);
    373                     }
    374                 }
    375                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    376                     m_pForm->m_pFormNotify->AfterValueChange(this);
    377                 }
    378                 m_pForm->m_bUpdated = TRUE;
    379             }
    380             break;
    381         case ListBox: {
    382                 int iIndex = FindOptionValue(value);
    383                 if (iIndex < 0) {
    384                     return FALSE;
    385                 }
    386                 if (bDefault && iIndex == GetDefaultSelectedItem()) {
    387                     return FALSE;
    388                 }
    389                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    390                     CFX_WideString csValue = value;
    391                     int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    392                     if (iRet < 0) {
    393                         return FALSE;
    394                     }
    395                 }
    396                 if (bDefault) {
    397                 } else {
    398                     ClearSelection();
    399                     SetItemSelection(iIndex, TRUE);
    400                 }
    401                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    402                     m_pForm->m_pFormNotify->AfterSelectionChange(this);
    403                 }
    404                 m_pForm->m_bUpdated = TRUE;
    405                 break;
    406             }
    407         default:
    408             break;
    409     }
    410     if (CPDF_InterForm::m_bUpdateAP) {
    411         UpdateAP(NULL);
    412     }
    413     return TRUE;
    414 }
    415 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify)
    416 {
    417     return SetValue(value, FALSE, bNotify);
    418 }
    419 int CPDF_FormField::GetMaxLen()
    420 {
    421     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen");
    422     if (pObj == NULL) {
    423         int iCount = m_ControlList.GetSize();
    424         for (int i = 0; i < iCount; i ++) {
    425             CPDF_FormControl* pControl = (CPDF_FormControl*)m_ControlList.GetAt(i);
    426             if (pControl == NULL) {
    427                 continue;
    428             }
    429             CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict;
    430             if (pWidgetDict->KeyExist("MaxLen")) {
    431                 return pWidgetDict->GetInteger("MaxLen");
    432             }
    433         }
    434         return 0;
    435     }
    436     return pObj->GetInteger();
    437 }
    438 int CPDF_FormField::CountSelectedItems()
    439 {
    440     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    441     if (pValue == NULL) {
    442         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    443         if (pValue == NULL) {
    444             return 0;
    445         }
    446     }
    447     if (pValue->GetType() == PDFOBJ_STRING) {
    448         if (pValue->GetString().IsEmpty()) {
    449             return 0;
    450         }
    451         return 1;
    452     }
    453     if (pValue->GetType() == PDFOBJ_NUMBER) {
    454         if (pValue->GetString().IsEmpty()) {
    455             return 0;
    456         }
    457         return 1;
    458     }
    459     if (pValue->GetType() != PDFOBJ_ARRAY) {
    460         return 0;
    461     }
    462     return ((CPDF_Array*)pValue)->GetCount();
    463 }
    464 int CPDF_FormField::GetSelectedIndex(int index)
    465 {
    466     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    467     if (pValue == NULL) {
    468         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    469         if (pValue == NULL) {
    470             return -1;
    471         }
    472     }
    473     CFX_WideString sel_value;
    474     if (pValue->GetType() == PDFOBJ_STRING) {
    475         if (index != 0) {
    476             return -1;
    477         }
    478         sel_value = pValue->GetUnicodeText();
    479     } else if (pValue->GetType() == PDFOBJ_NUMBER) {
    480         return pValue->GetInteger();
    481     } else {
    482         if (pValue->GetType() != PDFOBJ_ARRAY) {
    483             return -1;
    484         }
    485         if (index < 0) {
    486             return -1;
    487         }
    488         sel_value = ((CPDF_Array*)pValue)->GetElementValue(index)->GetUnicodeText();
    489     }
    490     if (index < CountSelectedOptions()) {
    491         int iOptIndex = GetSelectedOptionIndex(index);
    492         CFX_WideString csOpt = GetOptionValue(iOptIndex);
    493         if (csOpt == sel_value) {
    494             return iOptIndex;
    495         }
    496     }
    497     int nOpts = CountOptions();
    498     for (int i = 0; i < nOpts; i ++) {
    499         if (sel_value == GetOptionValue(i)) {
    500             return i;
    501         }
    502     }
    503     return -1;
    504 }
    505 FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify)
    506 {
    507     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    508         int iRet = 0;
    509         CFX_WideString csValue;
    510         int iIndex = GetSelectedIndex(0);
    511         if (iIndex >= 0) {
    512             csValue = GetOptionLabel(iIndex);
    513         }
    514         if (GetType() == ListBox) {
    515             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    516         }
    517         if (GetType() == ComboBox) {
    518             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    519         }
    520         if (iRet < 0) {
    521             return FALSE;
    522         }
    523     }
    524     m_pDict->RemoveAt("V");
    525     m_pDict->RemoveAt("I");
    526     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    527         if (GetType() == ListBox) {
    528             m_pForm->m_pFormNotify->AfterSelectionChange(this);
    529         }
    530         if (GetType() == ComboBox) {
    531             m_pForm->m_pFormNotify->AfterValueChange(this);
    532         }
    533     }
    534     if (CPDF_InterForm::m_bUpdateAP) {
    535         UpdateAP(NULL);
    536     }
    537     m_pForm->m_bUpdated = TRUE;
    538     return TRUE;
    539 }
    540 FX_BOOL CPDF_FormField::IsItemSelected(int index)
    541 {
    542     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    543     if (index < 0 || index >= CountOptions()) {
    544         return FALSE;
    545     }
    546     if (IsOptionSelected(index)) {
    547         return TRUE;
    548     }
    549     CFX_WideString opt_value = GetOptionValue(index);
    550     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    551     if (pValue == NULL) {
    552         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    553         if (pValue == NULL) {
    554             return FALSE;
    555         }
    556     }
    557     if (pValue->GetType() == PDFOBJ_STRING) {
    558         if (pValue->GetUnicodeText() == opt_value) {
    559             return TRUE;
    560         }
    561         return FALSE;
    562     }
    563     if (pValue->GetType() == PDFOBJ_NUMBER) {
    564         if (pValue->GetString().IsEmpty()) {
    565             return FALSE;
    566         }
    567         if (pValue->GetInteger() == index) {
    568             return TRUE;
    569         }
    570         return FALSE;
    571     }
    572     if (pValue->GetType() != PDFOBJ_ARRAY) {
    573         return FALSE;
    574     }
    575     CPDF_Array* pArray = (CPDF_Array*)pValue;
    576     int iPos = -1;
    577     for (int j = 0; j < CountSelectedOptions(); j ++) {
    578         if (GetSelectedOptionIndex(j) == index) {
    579             iPos = j;
    580             break;
    581         }
    582     }
    583     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++)
    584         if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value && (int)i == iPos) {
    585             return TRUE;
    586         }
    587     return FALSE;
    588 }
    589 FX_BOOL CPDF_FormField::SetItemSelection(int index, FX_BOOL bSelected, FX_BOOL bNotify)
    590 {
    591     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    592     if (index < 0 || index >= CountOptions()) {
    593         return FALSE;
    594     }
    595     CFX_WideString opt_value = GetOptionValue(index);
    596     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    597         int iRet = 0;
    598         if (GetType() == ListBox) {
    599             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
    600         }
    601         if (GetType() == ComboBox) {
    602             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
    603         }
    604         if (iRet < 0) {
    605             return FALSE;
    606         }
    607     }
    608     if (!bSelected) {
    609         CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    610         if (pValue != NULL) {
    611             if (m_Type == ListBox) {
    612                 SelectOption(index, FALSE);
    613                 if (pValue->GetType() == PDFOBJ_STRING) {
    614                     if (pValue->GetUnicodeText() == opt_value) {
    615                         m_pDict->RemoveAt("V");
    616                     }
    617                 } else if (pValue->GetType() == PDFOBJ_ARRAY) {
    618                     CPDF_Array* pArray = CPDF_Array::Create();
    619                     if (pArray == NULL) {
    620                         return FALSE;
    621                     }
    622                     int iCount = CountOptions();
    623                     for (int i = 0; i < iCount; i ++) {
    624                         if (i != index) {
    625                             if (IsItemSelected(i)) {
    626                                 opt_value = GetOptionValue(i);
    627                                 pArray->AddString(PDF_EncodeText(opt_value));
    628                             }
    629                         }
    630                     }
    631                     if (pArray->GetCount() < 1) {
    632                         pArray->Release();
    633                     } else {
    634                         m_pDict->SetAt("V", pArray);
    635                     }
    636                 }
    637             } else if (m_Type == ComboBox) {
    638                 m_pDict->RemoveAt("V");
    639                 m_pDict->RemoveAt("I");
    640             }
    641         }
    642     } else {
    643         if (m_Type == ListBox) {
    644             SelectOption(index, TRUE);
    645             if (!(m_Flags & FORMLIST_MULTISELECT)) {
    646                 m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength()));
    647             } else {
    648                 CPDF_Array* pArray = CPDF_Array::Create();
    649                 if (pArray == NULL) {
    650                     return FALSE;
    651                 }
    652                 FX_BOOL bSelected;
    653                 int iCount = CountOptions();
    654                 for (int i = 0; i < iCount; i ++) {
    655                     if (i != index) {
    656                         bSelected = IsItemSelected(i);
    657                     } else {
    658                         bSelected = TRUE;
    659                     }
    660                     if (bSelected) {
    661                         opt_value = GetOptionValue(i);
    662                         pArray->AddString(PDF_EncodeText(opt_value));
    663                     }
    664                 }
    665                 m_pDict->SetAt("V", pArray);
    666             }
    667         } else if (m_Type == ComboBox) {
    668             m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength()));
    669             CPDF_Array* pI = CPDF_Array::Create();
    670             if (pI == NULL) {
    671                 return FALSE;
    672             }
    673             pI->AddInteger(index);
    674             m_pDict->SetAt("I", pI);
    675         }
    676     }
    677     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    678         if (GetType() == ListBox) {
    679             m_pForm->m_pFormNotify->AfterSelectionChange(this);
    680         }
    681         if (GetType() == ComboBox) {
    682             m_pForm->m_pFormNotify->AfterValueChange(this);
    683         }
    684     }
    685     if (CPDF_InterForm::m_bUpdateAP) {
    686         UpdateAP(NULL);
    687     }
    688     m_pForm->m_bUpdated = TRUE;
    689     return TRUE;
    690 }
    691 FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index)
    692 {
    693     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    694     if (index < 0 || index >= CountOptions()) {
    695         return FALSE;
    696     }
    697     int iDVIndex = GetDefaultSelectedItem();
    698     if (iDVIndex < 0) {
    699         return FALSE;
    700     }
    701     return (iDVIndex == index);
    702 }
    703 int CPDF_FormField::GetDefaultSelectedItem()
    704 {
    705     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    706     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
    707     if (pValue == NULL) {
    708         return -1;
    709     }
    710     CFX_WideString csDV = pValue->GetUnicodeText();
    711     if (csDV.IsEmpty()) {
    712         return -1;
    713     }
    714     int iCount = CountOptions();
    715     for (int i = 0; i < iCount; i ++) {
    716         if (csDV == GetOptionValue(i)) {
    717             return i;
    718         }
    719     }
    720     return -1;
    721 }
    722 void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl)
    723 {
    724     if (m_Type == PushButton) {
    725         return;
    726     }
    727     if (m_Type == RadioButton || m_Type == CheckBox) {
    728         return;
    729     }
    730     if (!m_pForm->m_bGenerateAP) {
    731         return;
    732     }
    733     for (int i = 0; i < CountControls(); i ++) {
    734         CPDF_FormControl* pControl = GetControl(i);
    735         FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
    736     }
    737 }
    738 int CPDF_FormField::CountOptions()
    739 {
    740     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
    741     if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
    742         return 0;
    743     }
    744     return ((CPDF_Array*)pValue)->GetCount();
    745 }
    746 CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index)
    747 {
    748     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
    749     if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
    750         return CFX_WideString();
    751     }
    752     CPDF_Object* pOption = ((CPDF_Array*)pValue)->GetElementValue(index);
    753     if (pOption == NULL) {
    754         return CFX_WideString();
    755     }
    756     if (pOption->GetType() == PDFOBJ_ARRAY) {
    757         pOption = ((CPDF_Array*)pOption)->GetElementValue(sub_index);
    758     }
    759     if (pOption == NULL || pOption->GetType() != PDFOBJ_STRING) {
    760         return CFX_WideString();
    761     }
    762     return ((CPDF_String*)pOption)->GetUnicodeText();
    763 }
    764 CFX_WideString CPDF_FormField::GetOptionLabel(int index)
    765 {
    766     return GetOptionText(index, 1);
    767 }
    768 CFX_WideString CPDF_FormField::GetOptionValue(int index)
    769 {
    770     return GetOptionText(index, 0);
    771 }
    772 int CPDF_FormField::FindOption(CFX_WideString csOptLabel)
    773 {
    774     int iCount = CountOptions();
    775     for (int i = 0; i < iCount; i ++) {
    776         CFX_WideString csValue = GetOptionValue(i);
    777         if (csValue == csOptLabel) {
    778             return i;
    779         }
    780     }
    781     return -1;
    782 }
    783 int CPDF_FormField::FindOptionValue(FX_LPCWSTR csOptValue, int iStartIndex)
    784 {
    785     if (iStartIndex < 0) {
    786         iStartIndex = 0;
    787     }
    788     int iCount = CountOptions();
    789     for (; iStartIndex < iCount; iStartIndex ++) {
    790         CFX_WideString csValue = GetOptionValue(iStartIndex);
    791         if (csValue == csOptValue) {
    792             return iStartIndex;
    793         }
    794     }
    795     return -1;
    796 }
    797 FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify)
    798 {
    799     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    800     CPDF_FormControl* pControl = GetControl(iControlIndex);
    801     if (pControl == NULL) {
    802         return FALSE;
    803     }
    804     if (!bChecked && pControl->IsChecked() == bChecked) {
    805         return FALSE;
    806     }
    807     CFX_ByteArray statusArray;
    808     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    809         SaveCheckedFieldStatus(this, statusArray);
    810     }
    811     CFX_WideString csWExport =  pControl->GetExportValue();
    812     CFX_ByteString csBExport = PDF_EncodeText(csWExport);
    813     int iCount = CountControls();
    814     FX_BOOL bUnison = PDF_FormField_IsUnison(this);
    815     for (int i = 0; i < iCount; i ++) {
    816         CPDF_FormControl* pCtrl = GetControl(i);
    817         if (bUnison) {
    818             CFX_WideString csEValue = pCtrl->GetExportValue();
    819             if (csEValue == csWExport) {
    820                 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
    821                     pCtrl->CheckControl(bChecked);
    822                 } else if (bChecked) {
    823                     pCtrl->CheckControl(FALSE);
    824                 }
    825             } else if (bChecked) {
    826                 pCtrl->CheckControl(FALSE);
    827             }
    828         } else {
    829             if (i == iControlIndex) {
    830                 pCtrl->CheckControl(bChecked);
    831             } else if (bChecked) {
    832                 pCtrl->CheckControl(FALSE);
    833             }
    834         }
    835     }
    836     CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
    837     if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) {
    838         if (bChecked) {
    839             m_pDict->SetAtName("V", csBExport);
    840         } else {
    841             CFX_ByteString csV;
    842             CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
    843             if (pV != NULL) {
    844                 csV = pV->GetString();
    845             }
    846             if (csV == csBExport) {
    847                 m_pDict->SetAtName("V", "Off");
    848             }
    849         }
    850     } else if (bChecked) {
    851         CFX_ByteString csIndex;
    852         csIndex.Format("%d", iControlIndex);
    853         m_pDict->SetAtName("V", csIndex);
    854     }
    855     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    856         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
    857     }
    858     m_pForm->m_bUpdated = TRUE;
    859     return TRUE;
    860 }
    861 CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault)
    862 {
    863     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    864     CFX_WideString csExport = L"Off";
    865     FX_BOOL bChecked;
    866     int iCount = CountControls();
    867     for (int i = 0; i < iCount; i ++) {
    868         CPDF_FormControl* pControl = GetControl(i);
    869         if (bDefault) {
    870             bChecked = pControl->IsDefaultChecked();
    871         } else {
    872             bChecked = pControl->IsChecked();
    873         }
    874         if (bChecked) {
    875             csExport = pControl->GetExportValue();
    876             break;
    877         }
    878     }
    879     return csExport;
    880 }
    881 FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
    882 {
    883     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    884     CFX_ByteArray statusArray;
    885     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    886         SaveCheckedFieldStatus(this, statusArray);
    887     }
    888     int iCount = CountControls();
    889     for (int i = 0; i < iCount; i ++) {
    890         CPDF_FormControl* pControl = GetControl(i);
    891         CFX_WideString csExport = pControl->GetExportValue();
    892         if (csExport == value) {
    893             if (bDefault) {
    894             } else {
    895                 CheckControl(GetControlIndex(pControl), TRUE);
    896             }
    897             break;
    898         } else {
    899             if (bDefault) {
    900             } else {
    901                 CheckControl(GetControlIndex(pControl), FALSE);
    902             }
    903         }
    904     }
    905     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    906         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
    907     }
    908     m_pForm->m_bUpdated = TRUE;
    909     return TRUE;
    910 }
    911 int CPDF_FormField::GetTopVisibleIndex()
    912 {
    913     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
    914     if (pObj == NULL) {
    915         return 0;
    916     }
    917     return pObj->GetInteger();
    918 }
    919 int CPDF_FormField::CountSelectedOptions()
    920 {
    921     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    922     if (pObj == NULL) {
    923         return 0;
    924     }
    925     CPDF_Array* pArray = pObj->GetArray();
    926     if (pArray == NULL) {
    927         return 0;
    928     }
    929     return (int)pArray->GetCount();
    930 }
    931 int CPDF_FormField::GetSelectedOptionIndex(int index)
    932 {
    933     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    934     if (pObj == NULL) {
    935         return -1;
    936     }
    937     CPDF_Array* pArray = pObj->GetArray();
    938     if (pArray == NULL) {
    939         return -1;
    940     }
    941     int iCount = (int)pArray->GetCount();
    942     if (iCount > 0 && index < iCount) {
    943         return pArray->GetInteger(index);
    944     }
    945     return -1;
    946 }
    947 FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex)
    948 {
    949     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    950     if (pObj == NULL) {
    951         return FALSE;
    952     }
    953     CPDF_Array* pArray = pObj->GetArray();
    954     if (pArray == NULL) {
    955         return FALSE;
    956     }
    957     int iCount = (int)pArray->GetCount();
    958     for (int i = 0; i < iCount; i ++) {
    959         if (pArray->GetInteger(i) == iOptIndex) {
    960             return TRUE;
    961         }
    962     }
    963     return FALSE;
    964 }
    965 FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify)
    966 {
    967     CPDF_Array* pArray = m_pDict->GetArray("I");
    968     if (pArray == NULL) {
    969         if (!bSelected) {
    970             return TRUE;
    971         }
    972         pArray = CPDF_Array::Create();
    973         if (pArray == NULL) {
    974             return FALSE;
    975         }
    976         m_pDict->SetAt("I", pArray);
    977     }
    978     FX_BOOL bReturn = FALSE;
    979     for (int i = 0; i < (int)pArray->GetCount(); i ++) {
    980         int iFind = pArray->GetInteger(i);
    981         if (iFind == iOptIndex) {
    982             if (bSelected) {
    983                 return TRUE;
    984             }
    985             if (bNotify && m_pForm->m_pFormNotify != NULL) {
    986                 int iRet = 0;
    987                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
    988                 if (GetType() == ListBox) {
    989                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    990                 }
    991                 if (GetType() == ComboBox) {
    992                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    993                 }
    994                 if (iRet < 0) {
    995                     return FALSE;
    996                 }
    997             }
    998             pArray->RemoveAt(i);
    999             bReturn = TRUE;
   1000             break;
   1001         } else if (iFind > iOptIndex) {
   1002             if (!bSelected) {
   1003                 continue;
   1004             }
   1005             if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1006                 int iRet = 0;
   1007                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
   1008                 if (GetType() == ListBox) {
   1009                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
   1010                 }
   1011                 if (GetType() == ComboBox) {
   1012                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
   1013                 }
   1014                 if (iRet < 0) {
   1015                     return FALSE;
   1016                 }
   1017             }
   1018             CPDF_Number* pNum = CPDF_Number::Create(iOptIndex);
   1019             if (pNum == NULL) {
   1020                 return FALSE;
   1021             }
   1022             pArray->InsertAt(i, pNum);
   1023             bReturn = TRUE;
   1024             break;
   1025         }
   1026     }
   1027     if (!bReturn) {
   1028         if (bSelected) {
   1029             pArray->AddInteger(iOptIndex);
   1030         }
   1031         if (pArray->GetCount() == 0) {
   1032             m_pDict->RemoveAt("I");
   1033         }
   1034     }
   1035     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1036         if (GetType() == ListBox) {
   1037             m_pForm->m_pFormNotify->AfterSelectionChange(this);
   1038         }
   1039         if (GetType() == ComboBox) {
   1040             m_pForm->m_pFormNotify->AfterValueChange(this);
   1041         }
   1042     }
   1043     m_pForm->m_bUpdated = TRUE;
   1044     return TRUE;
   1045 }
   1046 FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify)
   1047 {
   1048     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1049         int iRet = 0;
   1050         CFX_WideString csValue;
   1051         int iIndex = GetSelectedIndex(0);
   1052         if (iIndex >= 0) {
   1053             csValue = GetOptionLabel(iIndex);
   1054         }
   1055         if (GetType() == ListBox) {
   1056             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
   1057         }
   1058         if (GetType() == ComboBox) {
   1059             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
   1060         }
   1061         if (iRet < 0) {
   1062             return FALSE;
   1063         }
   1064     }
   1065     m_pDict->RemoveAt("I");
   1066     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1067         if (GetType() == ListBox) {
   1068             m_pForm->m_pFormNotify->AfterSelectionChange(this);
   1069         }
   1070         if (GetType() == ComboBox) {
   1071             m_pForm->m_pFormNotify->AfterValueChange(this);
   1072         }
   1073     }
   1074     m_pForm->m_bUpdated = TRUE;
   1075     return TRUE;
   1076 }
   1077 void CPDF_FormField::LoadDA()
   1078 {
   1079     CFX_ByteString DA = FPDF_GetFieldAttr(m_pDict, "DA")->GetString();
   1080     if (DA.IsEmpty()) {
   1081         DA = m_pForm->m_pFormDict->GetString("DA");
   1082     }
   1083     if (DA.IsEmpty()) {
   1084         return;
   1085     }
   1086     CPDF_SimpleParser syntax(DA);
   1087     syntax.FindTagParam("Tf", 2);
   1088     CFX_ByteString font_name = syntax.GetWord();
   1089     CPDF_Dictionary* pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
   1090     if (pFontDict == NULL) {
   1091         return;
   1092     }
   1093     m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
   1094     m_FontSize = FX_atof(syntax.GetWord());
   1095 }
   1096