Fix warnings in android build, fix font rendering issue, fix issue 357588: wrong...
[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")->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 }