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 #include "doc_utils.h"
      9 
     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") ? FPDF_GetFieldAttr(m_pDict, "FT")->GetString() : CFX_ByteString();
     36     FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")? FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger() : 0;
     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             if (pValue) {
    328                 return pValue->GetUnicodeText();
    329             }
    330             break;
    331     }
    332     return CFX_WideString();
    333 }
    334 CFX_WideString CPDF_FormField::GetValue()
    335 {
    336     return GetValue(FALSE);
    337 }
    338 CFX_WideString CPDF_FormField::GetDefaultValue()
    339 {
    340     return GetValue(TRUE);
    341 }
    342 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
    343 {
    344     switch (m_Type) {
    345         case CheckBox:
    346         case RadioButton: {
    347                 SetCheckValue(value, bDefault, bNotify);
    348                 return TRUE;
    349             }
    350         case File:
    351         case RichText:
    352         case Text:
    353         case ComboBox: {
    354                 CFX_WideString csValue = value;
    355                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    356                     int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    357                     if (iRet < 0) {
    358                         return FALSE;
    359                     }
    360                 }
    361                 int iIndex = FindOptionValue(csValue);
    362                 if (iIndex < 0) {
    363                     CFX_ByteString bsEncodeText = PDF_EncodeText(csValue);
    364                     m_pDict->SetAtString(bDefault ? "DV" : "V", bsEncodeText);
    365                     if (m_Type == RichText && !bDefault) {
    366                         m_pDict->SetAtString("RV", bsEncodeText);
    367                     }
    368                     m_pDict->RemoveAt("I");
    369                 } else {
    370                     m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue));
    371                     if (bDefault) {
    372                     } else {
    373                         ClearSelection();
    374                         SetItemSelection(iIndex, TRUE);
    375                     }
    376                 }
    377                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    378                     m_pForm->m_pFormNotify->AfterValueChange(this);
    379                 }
    380                 m_pForm->m_bUpdated = TRUE;
    381             }
    382             break;
    383         case ListBox: {
    384                 int iIndex = FindOptionValue(value);
    385                 if (iIndex < 0) {
    386                     return FALSE;
    387                 }
    388                 if (bDefault && iIndex == GetDefaultSelectedItem()) {
    389                     return FALSE;
    390                 }
    391                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    392                     CFX_WideString csValue = value;
    393                     int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    394                     if (iRet < 0) {
    395                         return FALSE;
    396                     }
    397                 }
    398                 if (bDefault) {
    399                 } else {
    400                     ClearSelection();
    401                     SetItemSelection(iIndex, TRUE);
    402                 }
    403                 if (bNotify && m_pForm->m_pFormNotify != NULL) {
    404                     m_pForm->m_pFormNotify->AfterSelectionChange(this);
    405                 }
    406                 m_pForm->m_bUpdated = TRUE;
    407                 break;
    408             }
    409         default:
    410             break;
    411     }
    412     if (CPDF_InterForm::m_bUpdateAP) {
    413         UpdateAP(NULL);
    414     }
    415     return TRUE;
    416 }
    417 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify)
    418 {
    419     return SetValue(value, FALSE, bNotify);
    420 }
    421 int CPDF_FormField::GetMaxLen()
    422 {
    423     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen");
    424     if (pObj == NULL) {
    425         int iCount = m_ControlList.GetSize();
    426         for (int i = 0; i < iCount; i ++) {
    427             CPDF_FormControl* pControl = (CPDF_FormControl*)m_ControlList.GetAt(i);
    428             if (pControl == NULL) {
    429                 continue;
    430             }
    431             CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict;
    432             if (pWidgetDict->KeyExist("MaxLen")) {
    433                 return pWidgetDict->GetInteger("MaxLen");
    434             }
    435         }
    436         return 0;
    437     }
    438     return pObj->GetInteger();
    439 }
    440 int CPDF_FormField::CountSelectedItems()
    441 {
    442     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    443     if (pValue == NULL) {
    444         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    445         if (pValue == NULL) {
    446             return 0;
    447         }
    448     }
    449     if (pValue->GetType() == PDFOBJ_STRING) {
    450         if (pValue->GetString().IsEmpty()) {
    451             return 0;
    452         }
    453         return 1;
    454     }
    455     if (pValue->GetType() == PDFOBJ_NUMBER) {
    456         if (pValue->GetString().IsEmpty()) {
    457             return 0;
    458         }
    459         return 1;
    460     }
    461     if (pValue->GetType() != PDFOBJ_ARRAY) {
    462         return 0;
    463     }
    464     return ((CPDF_Array*)pValue)->GetCount();
    465 }
    466 int CPDF_FormField::GetSelectedIndex(int index)
    467 {
    468     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    469     if (pValue == NULL) {
    470         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    471         if (pValue == NULL) {
    472             return -1;
    473         }
    474     }
    475     CFX_WideString sel_value;
    476     if (pValue->GetType() == PDFOBJ_STRING) {
    477         if (index != 0) {
    478             return -1;
    479         }
    480         sel_value = pValue->GetUnicodeText();
    481     } else if (pValue->GetType() == PDFOBJ_NUMBER) {
    482         return pValue->GetInteger();
    483     } else {
    484         if (pValue->GetType() != PDFOBJ_ARRAY) {
    485             return -1;
    486         }
    487         if (index < 0) {
    488             return -1;
    489         }
    490         CPDF_Object* elementValue = ((CPDF_Array*)pValue)->GetElementValue(index);
    491         sel_value = elementValue ? elementValue->GetUnicodeText() : CFX_WideString();
    492     }
    493     if (index < CountSelectedOptions()) {
    494         int iOptIndex = GetSelectedOptionIndex(index);
    495         CFX_WideString csOpt = GetOptionValue(iOptIndex);
    496         if (csOpt == sel_value) {
    497             return iOptIndex;
    498         }
    499     }
    500     int nOpts = CountOptions();
    501     for (int i = 0; i < nOpts; i ++) {
    502         if (sel_value == GetOptionValue(i)) {
    503             return i;
    504         }
    505     }
    506     return -1;
    507 }
    508 FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify)
    509 {
    510     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    511         int iRet = 0;
    512         CFX_WideString csValue;
    513         int iIndex = GetSelectedIndex(0);
    514         if (iIndex >= 0) {
    515             csValue = GetOptionLabel(iIndex);
    516         }
    517         if (GetType() == ListBox) {
    518             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    519         }
    520         if (GetType() == ComboBox) {
    521             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    522         }
    523         if (iRet < 0) {
    524             return FALSE;
    525         }
    526     }
    527     m_pDict->RemoveAt("V");
    528     m_pDict->RemoveAt("I");
    529     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    530         if (GetType() == ListBox) {
    531             m_pForm->m_pFormNotify->AfterSelectionChange(this);
    532         }
    533         if (GetType() == ComboBox) {
    534             m_pForm->m_pFormNotify->AfterValueChange(this);
    535         }
    536     }
    537     if (CPDF_InterForm::m_bUpdateAP) {
    538         UpdateAP(NULL);
    539     }
    540     m_pForm->m_bUpdated = TRUE;
    541     return TRUE;
    542 }
    543 FX_BOOL CPDF_FormField::IsItemSelected(int index)
    544 {
    545     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    546     if (index < 0 || index >= CountOptions()) {
    547         return FALSE;
    548     }
    549     if (IsOptionSelected(index)) {
    550         return TRUE;
    551     }
    552     CFX_WideString opt_value = GetOptionValue(index);
    553     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    554     if (pValue == NULL) {
    555         pValue = FPDF_GetFieldAttr(m_pDict, "I");
    556         if (pValue == NULL) {
    557             return FALSE;
    558         }
    559     }
    560     if (pValue->GetType() == PDFOBJ_STRING) {
    561         if (pValue->GetUnicodeText() == opt_value) {
    562             return TRUE;
    563         }
    564         return FALSE;
    565     }
    566     if (pValue->GetType() == PDFOBJ_NUMBER) {
    567         if (pValue->GetString().IsEmpty()) {
    568             return FALSE;
    569         }
    570         if (pValue->GetInteger() == index) {
    571             return TRUE;
    572         }
    573         return FALSE;
    574     }
    575     if (pValue->GetType() != PDFOBJ_ARRAY) {
    576         return FALSE;
    577     }
    578     CPDF_Array* pArray = (CPDF_Array*)pValue;
    579     int iPos = -1;
    580     for (int j = 0; j < CountSelectedOptions(); j ++) {
    581         if (GetSelectedOptionIndex(j) == index) {
    582             iPos = j;
    583             break;
    584         }
    585     }
    586     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++)
    587         if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value && (int)i == iPos) {
    588             return TRUE;
    589         }
    590     return FALSE;
    591 }
    592 FX_BOOL CPDF_FormField::SetItemSelection(int index, FX_BOOL bSelected, FX_BOOL bNotify)
    593 {
    594     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    595     if (index < 0 || index >= CountOptions()) {
    596         return FALSE;
    597     }
    598     CFX_WideString opt_value = GetOptionValue(index);
    599     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    600         int iRet = 0;
    601         if (GetType() == ListBox) {
    602             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
    603         }
    604         if (GetType() == ComboBox) {
    605             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
    606         }
    607         if (iRet < 0) {
    608             return FALSE;
    609         }
    610     }
    611     if (!bSelected) {
    612         CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
    613         if (pValue != NULL) {
    614             if (m_Type == ListBox) {
    615                 SelectOption(index, FALSE);
    616                 if (pValue->GetType() == PDFOBJ_STRING) {
    617                     if (pValue->GetUnicodeText() == opt_value) {
    618                         m_pDict->RemoveAt("V");
    619                     }
    620                 } else if (pValue->GetType() == PDFOBJ_ARRAY) {
    621                     CPDF_Array* pArray = CPDF_Array::Create();
    622                     if (pArray == NULL) {
    623                         return FALSE;
    624                     }
    625                     int iCount = CountOptions();
    626                     for (int i = 0; i < iCount; i ++) {
    627                         if (i != index) {
    628                             if (IsItemSelected(i)) {
    629                                 opt_value = GetOptionValue(i);
    630                                 pArray->AddString(PDF_EncodeText(opt_value));
    631                             }
    632                         }
    633                     }
    634                     if (pArray->GetCount() < 1) {
    635                         pArray->Release();
    636                     } else {
    637                         m_pDict->SetAt("V", pArray);
    638                     }
    639                 }
    640             } else if (m_Type == ComboBox) {
    641                 m_pDict->RemoveAt("V");
    642                 m_pDict->RemoveAt("I");
    643             }
    644         }
    645     } else {
    646         if (m_Type == ListBox) {
    647             SelectOption(index, TRUE);
    648             if (!(m_Flags & FORMLIST_MULTISELECT)) {
    649                 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
    650             } else {
    651                 CPDF_Array* pArray = CPDF_Array::Create();
    652                 if (pArray == NULL) {
    653                     return FALSE;
    654                 }
    655                 FX_BOOL bSelected;
    656                 int iCount = CountOptions();
    657                 for (int i = 0; i < iCount; i ++) {
    658                     if (i != index) {
    659                         bSelected = IsItemSelected(i);
    660                     } else {
    661                         bSelected = TRUE;
    662                     }
    663                     if (bSelected) {
    664                         opt_value = GetOptionValue(i);
    665                         pArray->AddString(PDF_EncodeText(opt_value));
    666                     }
    667                 }
    668                 m_pDict->SetAt("V", pArray);
    669             }
    670         } else if (m_Type == ComboBox) {
    671             m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
    672             CPDF_Array* pI = CPDF_Array::Create();
    673             if (pI == NULL) {
    674                 return FALSE;
    675             }
    676             pI->AddInteger(index);
    677             m_pDict->SetAt("I", pI);
    678         }
    679     }
    680     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    681         if (GetType() == ListBox) {
    682             m_pForm->m_pFormNotify->AfterSelectionChange(this);
    683         }
    684         if (GetType() == ComboBox) {
    685             m_pForm->m_pFormNotify->AfterValueChange(this);
    686         }
    687     }
    688     if (CPDF_InterForm::m_bUpdateAP) {
    689         UpdateAP(NULL);
    690     }
    691     m_pForm->m_bUpdated = TRUE;
    692     return TRUE;
    693 }
    694 FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index)
    695 {
    696     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    697     if (index < 0 || index >= CountOptions()) {
    698         return FALSE;
    699     }
    700     int iDVIndex = GetDefaultSelectedItem();
    701     if (iDVIndex < 0) {
    702         return FALSE;
    703     }
    704     return (iDVIndex == index);
    705 }
    706 int CPDF_FormField::GetDefaultSelectedItem()
    707 {
    708     ASSERT(GetType() == ComboBox || GetType() == ListBox);
    709     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
    710     if (pValue == NULL) {
    711         return -1;
    712     }
    713     CFX_WideString csDV = pValue->GetUnicodeText();
    714     if (csDV.IsEmpty()) {
    715         return -1;
    716     }
    717     int iCount = CountOptions();
    718     for (int i = 0; i < iCount; i ++) {
    719         if (csDV == GetOptionValue(i)) {
    720             return i;
    721         }
    722     }
    723     return -1;
    724 }
    725 void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl)
    726 {
    727     if (m_Type == PushButton) {
    728         return;
    729     }
    730     if (m_Type == RadioButton || m_Type == CheckBox) {
    731         return;
    732     }
    733     if (!m_pForm->m_bGenerateAP) {
    734         return;
    735     }
    736     for (int i = 0; i < CountControls(); i ++) {
    737         CPDF_FormControl* pControl = GetControl(i);
    738         FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
    739     }
    740 }
    741 int CPDF_FormField::CountOptions()
    742 {
    743     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
    744     if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
    745         return 0;
    746     }
    747     return ((CPDF_Array*)pValue)->GetCount();
    748 }
    749 CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index)
    750 {
    751     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
    752     if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
    753         return CFX_WideString();
    754     }
    755     CPDF_Object* pOption = ((CPDF_Array*)pValue)->GetElementValue(index);
    756     if (pOption == NULL) {
    757         return CFX_WideString();
    758     }
    759     if (pOption->GetType() == PDFOBJ_ARRAY) {
    760         pOption = ((CPDF_Array*)pOption)->GetElementValue(sub_index);
    761     }
    762     if (pOption == NULL || pOption->GetType() != PDFOBJ_STRING) {
    763         return CFX_WideString();
    764     }
    765     return ((CPDF_String*)pOption)->GetUnicodeText();
    766 }
    767 CFX_WideString CPDF_FormField::GetOptionLabel(int index)
    768 {
    769     return GetOptionText(index, 1);
    770 }
    771 CFX_WideString CPDF_FormField::GetOptionValue(int index)
    772 {
    773     return GetOptionText(index, 0);
    774 }
    775 int CPDF_FormField::FindOption(CFX_WideString csOptLabel)
    776 {
    777     int iCount = CountOptions();
    778     for (int i = 0; i < iCount; i ++) {
    779         CFX_WideString csValue = GetOptionValue(i);
    780         if (csValue == csOptLabel) {
    781             return i;
    782         }
    783     }
    784     return -1;
    785 }
    786 int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue, int iStartIndex)
    787 {
    788     if (iStartIndex < 0) {
    789         iStartIndex = 0;
    790     }
    791     int iCount = CountOptions();
    792     for (; iStartIndex < iCount; iStartIndex ++) {
    793         CFX_WideString csValue = GetOptionValue(iStartIndex);
    794         if (csValue == csOptValue) {
    795             return iStartIndex;
    796         }
    797     }
    798     return -1;
    799 }
    800 FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify)
    801 {
    802     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    803     CPDF_FormControl* pControl = GetControl(iControlIndex);
    804     if (pControl == NULL) {
    805         return FALSE;
    806     }
    807     if (!bChecked && pControl->IsChecked() == bChecked) {
    808         return FALSE;
    809     }
    810     CFX_ByteArray statusArray;
    811     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    812         SaveCheckedFieldStatus(this, statusArray);
    813     }
    814     CFX_WideString csWExport = pControl->GetExportValue();
    815     CFX_ByteString csBExport = PDF_EncodeText(csWExport);
    816     int iCount = CountControls();
    817     FX_BOOL bUnison = PDF_FormField_IsUnison(this);
    818     for (int i = 0; i < iCount; i ++) {
    819         CPDF_FormControl* pCtrl = GetControl(i);
    820         if (bUnison) {
    821             CFX_WideString csEValue = pCtrl->GetExportValue();
    822             if (csEValue == csWExport) {
    823                 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
    824                     pCtrl->CheckControl(bChecked);
    825                 } else if (bChecked) {
    826                     pCtrl->CheckControl(FALSE);
    827                 }
    828             } else if (bChecked) {
    829                 pCtrl->CheckControl(FALSE);
    830             }
    831         } else {
    832             if (i == iControlIndex) {
    833                 pCtrl->CheckControl(bChecked);
    834             } else if (bChecked) {
    835                 pCtrl->CheckControl(FALSE);
    836             }
    837         }
    838     }
    839     CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
    840     if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) {
    841         if (bChecked) {
    842             m_pDict->SetAtName("V", csBExport);
    843         } else {
    844             CFX_ByteString csV;
    845             CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
    846             if (pV != NULL) {
    847                 csV = pV->GetString();
    848             }
    849             if (csV == csBExport) {
    850                 m_pDict->SetAtName("V", "Off");
    851             }
    852         }
    853     } else if (bChecked) {
    854         CFX_ByteString csIndex;
    855         csIndex.Format("%d", iControlIndex);
    856         m_pDict->SetAtName("V", csIndex);
    857     }
    858     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    859         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
    860     }
    861     m_pForm->m_bUpdated = TRUE;
    862     return TRUE;
    863 }
    864 CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault)
    865 {
    866     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    867     CFX_WideString csExport = L"Off";
    868     FX_BOOL bChecked;
    869     int iCount = CountControls();
    870     for (int i = 0; i < iCount; i ++) {
    871         CPDF_FormControl* pControl = GetControl(i);
    872         if (bDefault) {
    873             bChecked = pControl->IsDefaultChecked();
    874         } else {
    875             bChecked = pControl->IsChecked();
    876         }
    877         if (bChecked) {
    878             csExport = pControl->GetExportValue();
    879             break;
    880         }
    881     }
    882     return csExport;
    883 }
    884 FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
    885 {
    886     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
    887     CFX_ByteArray statusArray;
    888     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    889         SaveCheckedFieldStatus(this, statusArray);
    890     }
    891     int iCount = CountControls();
    892     for (int i = 0; i < iCount; i ++) {
    893         CPDF_FormControl* pControl = GetControl(i);
    894         CFX_WideString csExport = pControl->GetExportValue();
    895         if (csExport == value) {
    896             if (bDefault) {
    897             } else {
    898                 CheckControl(GetControlIndex(pControl), TRUE);
    899             }
    900             break;
    901         } else {
    902             if (bDefault) {
    903             } else {
    904                 CheckControl(GetControlIndex(pControl), FALSE);
    905             }
    906         }
    907     }
    908     if (bNotify && m_pForm->m_pFormNotify != NULL) {
    909         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
    910     }
    911     m_pForm->m_bUpdated = TRUE;
    912     return TRUE;
    913 }
    914 int CPDF_FormField::GetTopVisibleIndex()
    915 {
    916     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
    917     if (pObj == NULL) {
    918         return 0;
    919     }
    920     return pObj->GetInteger();
    921 }
    922 int CPDF_FormField::CountSelectedOptions()
    923 {
    924     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    925     if (pObj == NULL) {
    926         return 0;
    927     }
    928     CPDF_Array* pArray = pObj->GetArray();
    929     if (pArray == NULL) {
    930         return 0;
    931     }
    932     return (int)pArray->GetCount();
    933 }
    934 int CPDF_FormField::GetSelectedOptionIndex(int index)
    935 {
    936     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    937     if (pObj == NULL) {
    938         return -1;
    939     }
    940     CPDF_Array* pArray = pObj->GetArray();
    941     if (pArray == NULL) {
    942         return -1;
    943     }
    944     int iCount = (int)pArray->GetCount();
    945     if (iCount > 0 && index < iCount) {
    946         return pArray->GetInteger(index);
    947     }
    948     return -1;
    949 }
    950 FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex)
    951 {
    952     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
    953     if (pObj == NULL) {
    954         return FALSE;
    955     }
    956     CPDF_Array* pArray = pObj->GetArray();
    957     if (pArray == NULL) {
    958         return FALSE;
    959     }
    960     int iCount = (int)pArray->GetCount();
    961     for (int i = 0; i < iCount; i ++) {
    962         if (pArray->GetInteger(i) == iOptIndex) {
    963             return TRUE;
    964         }
    965     }
    966     return FALSE;
    967 }
    968 FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify)
    969 {
    970     CPDF_Array* pArray = m_pDict->GetArray("I");
    971     if (pArray == NULL) {
    972         if (!bSelected) {
    973             return TRUE;
    974         }
    975         pArray = CPDF_Array::Create();
    976         if (pArray == NULL) {
    977             return FALSE;
    978         }
    979         m_pDict->SetAt("I", pArray);
    980     }
    981     FX_BOOL bReturn = FALSE;
    982     for (int i = 0; i < (int)pArray->GetCount(); i ++) {
    983         int iFind = pArray->GetInteger(i);
    984         if (iFind == iOptIndex) {
    985             if (bSelected) {
    986                 return TRUE;
    987             }
    988             if (bNotify && m_pForm->m_pFormNotify != NULL) {
    989                 int iRet = 0;
    990                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
    991                 if (GetType() == ListBox) {
    992                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
    993                 }
    994                 if (GetType() == ComboBox) {
    995                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
    996                 }
    997                 if (iRet < 0) {
    998                     return FALSE;
    999                 }
   1000             }
   1001             pArray->RemoveAt(i);
   1002             bReturn = TRUE;
   1003             break;
   1004         } else if (iFind > iOptIndex) {
   1005             if (!bSelected) {
   1006                 continue;
   1007             }
   1008             if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1009                 int iRet = 0;
   1010                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
   1011                 if (GetType() == ListBox) {
   1012                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
   1013                 }
   1014                 if (GetType() == ComboBox) {
   1015                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
   1016                 }
   1017                 if (iRet < 0) {
   1018                     return FALSE;
   1019                 }
   1020             }
   1021             CPDF_Number* pNum = CPDF_Number::Create(iOptIndex);
   1022             if (pNum == NULL) {
   1023                 return FALSE;
   1024             }
   1025             pArray->InsertAt(i, pNum);
   1026             bReturn = TRUE;
   1027             break;
   1028         }
   1029     }
   1030     if (!bReturn) {
   1031         if (bSelected) {
   1032             pArray->AddInteger(iOptIndex);
   1033         }
   1034         if (pArray->GetCount() == 0) {
   1035             m_pDict->RemoveAt("I");
   1036         }
   1037     }
   1038     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1039         if (GetType() == ListBox) {
   1040             m_pForm->m_pFormNotify->AfterSelectionChange(this);
   1041         }
   1042         if (GetType() == ComboBox) {
   1043             m_pForm->m_pFormNotify->AfterValueChange(this);
   1044         }
   1045     }
   1046     m_pForm->m_bUpdated = TRUE;
   1047     return TRUE;
   1048 }
   1049 FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify)
   1050 {
   1051     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1052         int iRet = 0;
   1053         CFX_WideString csValue;
   1054         int iIndex = GetSelectedIndex(0);
   1055         if (iIndex >= 0) {
   1056             csValue = GetOptionLabel(iIndex);
   1057         }
   1058         if (GetType() == ListBox) {
   1059             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
   1060         }
   1061         if (GetType() == ComboBox) {
   1062             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
   1063         }
   1064         if (iRet < 0) {
   1065             return FALSE;
   1066         }
   1067     }
   1068     m_pDict->RemoveAt("I");
   1069     if (bNotify && m_pForm->m_pFormNotify != NULL) {
   1070         if (GetType() == ListBox) {
   1071             m_pForm->m_pFormNotify->AfterSelectionChange(this);
   1072         }
   1073         if (GetType() == ComboBox) {
   1074             m_pForm->m_pFormNotify->AfterValueChange(this);
   1075         }
   1076     }
   1077     m_pForm->m_bUpdated = TRUE;
   1078     return TRUE;
   1079 }
   1080 void CPDF_FormField::LoadDA()
   1081 {
   1082     CFX_ByteString DA;
   1083     if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
   1084         DA = pObj_t->GetString();
   1085     }
   1086     if (DA.IsEmpty() && m_pForm->m_pFormDict) {
   1087         DA = m_pForm->m_pFormDict->GetString("DA");
   1088     }
   1089     if (DA.IsEmpty()) {
   1090         return;
   1091     }
   1092     CPDF_SimpleParser syntax(DA);
   1093     syntax.FindTagParam("Tf", 2);
   1094     CFX_ByteString font_name = syntax.GetWord();
   1095     CPDF_Dictionary* pFontDict = NULL;
   1096     if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDict("DR") &&
   1097         m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font") )
   1098     pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
   1099 
   1100     if (pFontDict == NULL) {
   1101         return;
   1102     }
   1103     m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
   1104     m_FontSize = FX_atof(syntax.GetWord());
   1105 }
   1106