Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
[pdfium.git] / core / src / fpdfdoc / doc_formfield.cpp
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") ? 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, opt_value.GetLength()));
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, opt_value.GetLength()));
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(FX_LPCWSTR 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 int CPDF_FormField::InsertOption(CFX_WideString csOptLabel, int index, FX_BOOL bNotify)\r
801 {\r
802     if (csOptLabel.IsEmpty()) return -1;\r
803 \r
804     if (bNotify && m_pForm->m_pFormNotify != NULL)\r
805     {\r
806         int iRet = 0;\r
807         if (GetType() == ListBox) iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csOptLabel);\r
808         if (GetType() == ComboBox) iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csOptLabel);\r
809         if (iRet < 0) return -1;\r
810     }\r
811 \r
812     CFX_ByteString csStr = PDF_EncodeText(csOptLabel, csOptLabel.GetLength());\r
813     CPDF_Array* pOpt = NULL;\r
814     CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");\r
815     if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY)\r
816     {\r
817         pOpt = CPDF_Array::Create();\r
818         if (pOpt == NULL) return -1;\r
819         m_pDict->SetAt("Opt", pOpt);\r
820     }\r
821     else\r
822         pOpt = (CPDF_Array*)pValue;\r
823     int iCount = (int)pOpt->GetCount();\r
824     if (index < 0 || index >= iCount)\r
825     {\r
826         pOpt->AddString(csStr);\r
827         index = iCount;\r
828     }\r
829     else {\r
830         CPDF_String* pString = CPDF_String::Create(csStr);\r
831         if (pString == NULL) return -1;\r
832         pOpt->InsertAt(index, pString);\r
833     }\r
834 \r
835     if (bNotify && m_pForm->m_pFormNotify != NULL)\r
836     {\r
837         if (GetType() == ListBox) m_pForm->m_pFormNotify->AfterSelectionChange(this);\r
838         if (GetType() == ComboBox) m_pForm->m_pFormNotify->AfterValueChange(this);\r
839     }\r
840     m_pForm->m_bUpdated = TRUE;\r
841     return index;\r
842 }
843 FX_BOOL CPDF_FormField::ClearOptions(FX_BOOL bNotify)\r
844 {\r
845     if (bNotify && m_pForm->m_pFormNotify != NULL)\r
846     {\r
847         int iRet = 0;\r
848         CFX_WideString csValue;\r
849         int iIndex = GetSelectedIndex(0);\r
850         if (iIndex >= 0) csValue = GetOptionLabel(iIndex);\r
851         if (GetType() == ListBox) iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);\r
852         if (GetType() == ComboBox) iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);\r
853         if (iRet < 0) return FALSE;\r
854     }\r
855 \r
856     m_pDict->RemoveAt("Opt");\r
857     m_pDict->RemoveAt("V");\r
858     m_pDict->RemoveAt("DV");\r
859     m_pDict->RemoveAt("I");\r
860     m_pDict->RemoveAt("TI");\r
861 \r
862     if (bNotify && m_pForm->m_pFormNotify != NULL)\r
863     {\r
864         if (GetType() == ListBox) m_pForm->m_pFormNotify->AfterSelectionChange(this);\r
865         if (GetType() == ComboBox) m_pForm->m_pFormNotify->AfterValueChange(this);\r
866     }\r
867 \r
868     m_pForm->m_bUpdated = TRUE;\r
869     return TRUE;\r
870 }
871 FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify)
872 {
873     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
874     CPDF_FormControl* pControl = GetControl(iControlIndex);
875     if (pControl == NULL) {
876         return FALSE;
877     }
878     if (!bChecked && pControl->IsChecked() == bChecked) {
879         return FALSE;
880     }
881     CFX_ByteArray statusArray;
882     if (bNotify && m_pForm->m_pFormNotify != NULL) {
883         SaveCheckedFieldStatus(this, statusArray);
884     }
885     CFX_WideString csWExport =  pControl->GetExportValue();
886     CFX_ByteString csBExport = PDF_EncodeText(csWExport);
887     int iCount = CountControls();
888     FX_BOOL bUnison = PDF_FormField_IsUnison(this);
889     for (int i = 0; i < iCount; i ++) {
890         CPDF_FormControl* pCtrl = GetControl(i);
891         if (bUnison) {
892             CFX_WideString csEValue = pCtrl->GetExportValue();
893             if (csEValue == csWExport) {
894                 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
895                     pCtrl->CheckControl(bChecked);
896                 } else if (bChecked) {
897                     pCtrl->CheckControl(FALSE);
898                 }
899             } else if (bChecked) {
900                 pCtrl->CheckControl(FALSE);
901             }
902         } else {
903             if (i == iControlIndex) {
904                 pCtrl->CheckControl(bChecked);
905             } else if (bChecked) {
906                 pCtrl->CheckControl(FALSE);
907             }
908         }
909     }
910     CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
911     if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) {
912         if (bChecked) {
913             m_pDict->SetAtName("V", csBExport);
914         } else {
915             CFX_ByteString csV;
916             CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
917             if (pV != NULL) {
918                 csV = pV->GetString();
919             }
920             if (csV == csBExport) {
921                 m_pDict->SetAtName("V", "Off");
922             }
923         }
924     } else if (bChecked) {
925         CFX_ByteString csIndex;
926         csIndex.Format("%d", iControlIndex);
927         m_pDict->SetAtName("V", csIndex);
928     }
929     if (bNotify && m_pForm->m_pFormNotify != NULL) {
930         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
931     }
932     m_pForm->m_bUpdated = TRUE;
933     return TRUE;
934 }
935 CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault)
936 {
937     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
938     CFX_WideString csExport = L"Off";
939     FX_BOOL bChecked;
940     int iCount = CountControls();
941     for (int i = 0; i < iCount; i ++) {
942         CPDF_FormControl* pControl = GetControl(i);
943         if (bDefault) {
944             bChecked = pControl->IsDefaultChecked();
945         } else {
946             bChecked = pControl->IsChecked();
947         }
948         if (bChecked) {
949             csExport = pControl->GetExportValue();
950             break;
951         }
952     }
953     return csExport;
954 }
955 FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
956 {
957     ASSERT(GetType() == CheckBox || GetType() == RadioButton);
958     CFX_ByteArray statusArray;
959     if (bNotify && m_pForm->m_pFormNotify != NULL) {
960         SaveCheckedFieldStatus(this, statusArray);
961     }
962     int iCount = CountControls();
963     for (int i = 0; i < iCount; i ++) {
964         CPDF_FormControl* pControl = GetControl(i);
965         CFX_WideString csExport = pControl->GetExportValue();
966         if (csExport == value) {
967             if (bDefault) {
968             } else {
969                 CheckControl(GetControlIndex(pControl), TRUE);
970             }
971             break;
972         } else {
973             if (bDefault) {
974             } else {
975                 CheckControl(GetControlIndex(pControl), FALSE);
976             }
977         }
978     }
979     if (bNotify && m_pForm->m_pFormNotify != NULL) {
980         m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
981     }
982     m_pForm->m_bUpdated = TRUE;
983     return TRUE;
984 }
985 int CPDF_FormField::GetTopVisibleIndex()
986 {
987     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
988     if (pObj == NULL) {
989         return 0;
990     }
991     return pObj->GetInteger();
992 }
993 int CPDF_FormField::CountSelectedOptions()
994 {
995     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
996     if (pObj == NULL) {
997         return 0;
998     }
999     CPDF_Array* pArray = pObj->GetArray();
1000     if (pArray == NULL) {
1001         return 0;
1002     }
1003     return (int)pArray->GetCount();
1004 }
1005 int CPDF_FormField::GetSelectedOptionIndex(int index)
1006 {
1007     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
1008     if (pObj == NULL) {
1009         return -1;
1010     }
1011     CPDF_Array* pArray = pObj->GetArray();
1012     if (pArray == NULL) {
1013         return -1;
1014     }
1015     int iCount = (int)pArray->GetCount();
1016     if (iCount > 0 && index < iCount) {
1017         return pArray->GetInteger(index);
1018     }
1019     return -1;
1020 }
1021 FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex)
1022 {
1023     CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
1024     if (pObj == NULL) {
1025         return FALSE;
1026     }
1027     CPDF_Array* pArray = pObj->GetArray();
1028     if (pArray == NULL) {
1029         return FALSE;
1030     }
1031     int iCount = (int)pArray->GetCount();
1032     for (int i = 0; i < iCount; i ++) {
1033         if (pArray->GetInteger(i) == iOptIndex) {
1034             return TRUE;
1035         }
1036     }
1037     return FALSE;
1038 }
1039 FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify)
1040 {
1041     CPDF_Array* pArray = m_pDict->GetArray("I");
1042     if (pArray == NULL) {
1043         if (!bSelected) {
1044             return TRUE;
1045         }
1046         pArray = CPDF_Array::Create();
1047         if (pArray == NULL) {
1048             return FALSE;
1049         }
1050         m_pDict->SetAt("I", pArray);
1051     }
1052     FX_BOOL bReturn = FALSE;
1053     for (int i = 0; i < (int)pArray->GetCount(); i ++) {
1054         int iFind = pArray->GetInteger(i);
1055         if (iFind == iOptIndex) {
1056             if (bSelected) {
1057                 return TRUE;
1058             }
1059             if (bNotify && m_pForm->m_pFormNotify != NULL) {
1060                 int iRet = 0;
1061                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
1062                 if (GetType() == ListBox) {
1063                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1064                 }
1065                 if (GetType() == ComboBox) {
1066                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1067                 }
1068                 if (iRet < 0) {
1069                     return FALSE;
1070                 }
1071             }
1072             pArray->RemoveAt(i);
1073             bReturn = TRUE;
1074             break;
1075         } else if (iFind > iOptIndex) {
1076             if (!bSelected) {
1077                 continue;
1078             }
1079             if (bNotify && m_pForm->m_pFormNotify != NULL) {
1080                 int iRet = 0;
1081                 CFX_WideString csValue = GetOptionLabel(iOptIndex);
1082                 if (GetType() == ListBox) {
1083                     iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1084                 }
1085                 if (GetType() == ComboBox) {
1086                     iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1087                 }
1088                 if (iRet < 0) {
1089                     return FALSE;
1090                 }
1091             }
1092             CPDF_Number* pNum = CPDF_Number::Create(iOptIndex);
1093             if (pNum == NULL) {
1094                 return FALSE;
1095             }
1096             pArray->InsertAt(i, pNum);
1097             bReturn = TRUE;
1098             break;
1099         }
1100     }
1101     if (!bReturn) {
1102         if (bSelected) {
1103             pArray->AddInteger(iOptIndex);
1104         }
1105         if (pArray->GetCount() == 0) {
1106             m_pDict->RemoveAt("I");
1107         }
1108     }
1109     if (bNotify && m_pForm->m_pFormNotify != NULL) {
1110         if (GetType() == ListBox) {
1111             m_pForm->m_pFormNotify->AfterSelectionChange(this);
1112         }
1113         if (GetType() == ComboBox) {
1114             m_pForm->m_pFormNotify->AfterValueChange(this);
1115         }
1116     }
1117     m_pForm->m_bUpdated = TRUE;
1118     return TRUE;
1119 }
1120 FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify)
1121 {
1122     if (bNotify && m_pForm->m_pFormNotify != NULL) {
1123         int iRet = 0;
1124         CFX_WideString csValue;
1125         int iIndex = GetSelectedIndex(0);
1126         if (iIndex >= 0) {
1127             csValue = GetOptionLabel(iIndex);
1128         }
1129         if (GetType() == ListBox) {
1130             iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1131         }
1132         if (GetType() == ComboBox) {
1133             iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1134         }
1135         if (iRet < 0) {
1136             return FALSE;
1137         }
1138     }
1139     m_pDict->RemoveAt("I");
1140     if (bNotify && m_pForm->m_pFormNotify != NULL) {
1141         if (GetType() == ListBox) {
1142             m_pForm->m_pFormNotify->AfterSelectionChange(this);
1143         }
1144         if (GetType() == ComboBox) {
1145             m_pForm->m_pFormNotify->AfterValueChange(this);
1146         }
1147     }
1148     m_pForm->m_bUpdated = TRUE;
1149     return TRUE;
1150 }
1151 void CPDF_FormField::LoadDA()
1152 {
1153     CFX_ByteString DA;
1154     if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
1155         DA = pObj_t->GetString();
1156     }
1157     if (DA.IsEmpty() && m_pForm->m_pFormDict) {
1158         DA = m_pForm->m_pFormDict->GetString("DA");
1159     }
1160     if (DA.IsEmpty()) {
1161         return;
1162     }
1163     CPDF_SimpleParser syntax(DA);
1164     syntax.FindTagParam("Tf", 2);
1165     CFX_ByteString font_name = syntax.GetWord();
1166     CPDF_Dictionary* pFontDict = NULL;
1167     if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDict("DR") &&
1168         m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font") )
1169     pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
1170
1171     if (pFontDict == NULL) {
1172         return;
1173     }
1174     m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1175     m_FontSize = FX_atof(syntax.GetWord());
1176 }