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);
PDF_FormField_IsUnison(CPDF_FormField * pField)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 }
CPDF_FormField(CPDF_InterForm * pForm,CPDF_Dictionary * pDict)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 }
~CPDF_FormField()30 CPDF_FormField::~CPDF_FormField()
31 {
32 }
SyncFieldFlags()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 }
GetFullName()99 CFX_WideString CPDF_FormField::GetFullName()
100 {
101 return ::GetFullName(m_pDict);
102 }
ResetField(FX_BOOL bNotify)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 }
GetControlIndex(const CPDF_FormControl * pControl)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 }
GetFieldType()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 }
GetAdditionalAction()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 }
GetAlternateName()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 }
GetMappingName()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 }
GetFieldFlags()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 }
GetDefaultStyle()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 }
GetRichTextString()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 }
GetValue(FX_BOOL bDefault)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 }
GetValue()332 CFX_WideString CPDF_FormField::GetValue()
333 {
334 return GetValue(FALSE);
335 }
GetDefaultValue()336 CFX_WideString CPDF_FormField::GetDefaultValue()
337 {
338 return GetValue(TRUE);
339 }
SetValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)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 }
SetValue(const CFX_WideString & value,FX_BOOL bNotify)415 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify)
416 {
417 return SetValue(value, FALSE, bNotify);
418 }
GetMaxLen()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 }
CountSelectedItems()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 }
GetSelectedIndex(int index)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 }
ClearSelection(FX_BOOL bNotify)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 }
IsItemSelected(int index)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 }
SetItemSelection(int index,FX_BOOL bSelected,FX_BOOL bNotify)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 }
IsItemDefaultSelected(int index)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 }
GetDefaultSelectedItem()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 }
UpdateAP(CPDF_FormControl * pControl)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 }
CountOptions()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 }
GetOptionText(int index,int sub_index)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 }
GetOptionLabel(int index)764 CFX_WideString CPDF_FormField::GetOptionLabel(int index)
765 {
766 return GetOptionText(index, 1);
767 }
GetOptionValue(int index)768 CFX_WideString CPDF_FormField::GetOptionValue(int index)
769 {
770 return GetOptionText(index, 0);
771 }
FindOption(CFX_WideString csOptLabel)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 }
FindOptionValue(FX_LPCWSTR csOptValue,int iStartIndex)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 }
CheckControl(int iControlIndex,FX_BOOL bChecked,FX_BOOL bNotify)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 }
GetCheckValue(FX_BOOL bDefault)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 }
SetCheckValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)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 }
GetTopVisibleIndex()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 }
CountSelectedOptions()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 }
GetSelectedOptionIndex(int index)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 }
IsOptionSelected(int iOptIndex)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 }
SelectOption(int iOptIndex,FX_BOOL bSelected,FX_BOOL bNotify)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 }
ClearSelectedOptions(FX_BOOL bNotify)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 }
LoadDA()1077 void CPDF_FormField::LoadDA()
1078 {
1079 CFX_ByteString DA = FPDF_GetFieldAttr(m_pDict, "DA")->GetString();
1080 if (DA.IsEmpty()) {
1081 DA = m_pForm->m_pFormDict->GetString("DA");
1082 }
1083 if (DA.IsEmpty()) {
1084 return;
1085 }
1086 CPDF_SimpleParser syntax(DA);
1087 syntax.FindTagParam("Tf", 2);
1088 CFX_ByteString font_name = syntax.GetWord();
1089 CPDF_Dictionary* pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
1090 if (pFontDict == NULL) {
1091 return;
1092 }
1093 m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1094 m_FontSize = FX_atof(syntax.GetWord());
1095 }
1096