1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/fpdfdoc/fpdf_doc.h"
8 #include "doc_utils.h"
9
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") ? 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 }
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 if (pValue) {
328 return pValue->GetUnicodeText();
329 }
330 break;
331 }
332 return CFX_WideString();
333 }
GetValue()334 CFX_WideString CPDF_FormField::GetValue()
335 {
336 return GetValue(FALSE);
337 }
GetDefaultValue()338 CFX_WideString CPDF_FormField::GetDefaultValue()
339 {
340 return GetValue(TRUE);
341 }
SetValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)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 }
SetValue(const CFX_WideString & value,FX_BOOL bNotify)417 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify)
418 {
419 return SetValue(value, FALSE, bNotify);
420 }
GetMaxLen()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 }
CountSelectedItems()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 }
GetSelectedIndex(int index)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 }
ClearSelection(FX_BOOL bNotify)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 }
IsItemSelected(int index)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 }
SetItemSelection(int index,FX_BOOL bSelected,FX_BOOL bNotify)592 FX_BOOL CPDF_FormField::SetItemSelection(int index, FX_BOOL bSelected, FX_BOOL bNotify)
593 {
594 ASSERT(GetType() == ComboBox || GetType() == ListBox);
595 if (index < 0 || index >= CountOptions()) {
596 return FALSE;
597 }
598 CFX_WideString opt_value = GetOptionValue(index);
599 if (bNotify && m_pForm->m_pFormNotify != NULL) {
600 int iRet = 0;
601 if (GetType() == ListBox) {
602 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
603 }
604 if (GetType() == ComboBox) {
605 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
606 }
607 if (iRet < 0) {
608 return FALSE;
609 }
610 }
611 if (!bSelected) {
612 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
613 if (pValue != NULL) {
614 if (m_Type == ListBox) {
615 SelectOption(index, FALSE);
616 if (pValue->GetType() == PDFOBJ_STRING) {
617 if (pValue->GetUnicodeText() == opt_value) {
618 m_pDict->RemoveAt("V");
619 }
620 } else if (pValue->GetType() == PDFOBJ_ARRAY) {
621 CPDF_Array* pArray = CPDF_Array::Create();
622 if (pArray == NULL) {
623 return FALSE;
624 }
625 int iCount = CountOptions();
626 for (int i = 0; i < iCount; i ++) {
627 if (i != index) {
628 if (IsItemSelected(i)) {
629 opt_value = GetOptionValue(i);
630 pArray->AddString(PDF_EncodeText(opt_value));
631 }
632 }
633 }
634 if (pArray->GetCount() < 1) {
635 pArray->Release();
636 } else {
637 m_pDict->SetAt("V", pArray);
638 }
639 }
640 } else if (m_Type == ComboBox) {
641 m_pDict->RemoveAt("V");
642 m_pDict->RemoveAt("I");
643 }
644 }
645 } else {
646 if (m_Type == ListBox) {
647 SelectOption(index, TRUE);
648 if (!(m_Flags & FORMLIST_MULTISELECT)) {
649 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
650 } else {
651 CPDF_Array* pArray = CPDF_Array::Create();
652 if (pArray == NULL) {
653 return FALSE;
654 }
655 FX_BOOL bSelected;
656 int iCount = CountOptions();
657 for (int i = 0; i < iCount; i ++) {
658 if (i != index) {
659 bSelected = IsItemSelected(i);
660 } else {
661 bSelected = TRUE;
662 }
663 if (bSelected) {
664 opt_value = GetOptionValue(i);
665 pArray->AddString(PDF_EncodeText(opt_value));
666 }
667 }
668 m_pDict->SetAt("V", pArray);
669 }
670 } else if (m_Type == ComboBox) {
671 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
672 CPDF_Array* pI = CPDF_Array::Create();
673 if (pI == NULL) {
674 return FALSE;
675 }
676 pI->AddInteger(index);
677 m_pDict->SetAt("I", pI);
678 }
679 }
680 if (bNotify && m_pForm->m_pFormNotify != NULL) {
681 if (GetType() == ListBox) {
682 m_pForm->m_pFormNotify->AfterSelectionChange(this);
683 }
684 if (GetType() == ComboBox) {
685 m_pForm->m_pFormNotify->AfterValueChange(this);
686 }
687 }
688 if (CPDF_InterForm::m_bUpdateAP) {
689 UpdateAP(NULL);
690 }
691 m_pForm->m_bUpdated = TRUE;
692 return TRUE;
693 }
IsItemDefaultSelected(int index)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 }
GetDefaultSelectedItem()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 }
UpdateAP(CPDF_FormControl * pControl)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 }
CountOptions()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 }
GetOptionText(int index,int sub_index)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 }
GetOptionLabel(int index)767 CFX_WideString CPDF_FormField::GetOptionLabel(int index)
768 {
769 return GetOptionText(index, 1);
770 }
GetOptionValue(int index)771 CFX_WideString CPDF_FormField::GetOptionValue(int index)
772 {
773 return GetOptionText(index, 0);
774 }
FindOption(CFX_WideString csOptLabel)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 }
FindOptionValue(const CFX_WideString & csOptValue,int iStartIndex)786 int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue, int iStartIndex)
787 {
788 if (iStartIndex < 0) {
789 iStartIndex = 0;
790 }
791 int iCount = CountOptions();
792 for (; iStartIndex < iCount; iStartIndex ++) {
793 CFX_WideString csValue = GetOptionValue(iStartIndex);
794 if (csValue == csOptValue) {
795 return iStartIndex;
796 }
797 }
798 return -1;
799 }
CheckControl(int iControlIndex,FX_BOOL bChecked,FX_BOOL bNotify)800 FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify)
801 {
802 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
803 CPDF_FormControl* pControl = GetControl(iControlIndex);
804 if (pControl == NULL) {
805 return FALSE;
806 }
807 if (!bChecked && pControl->IsChecked() == bChecked) {
808 return FALSE;
809 }
810 CFX_ByteArray statusArray;
811 if (bNotify && m_pForm->m_pFormNotify != NULL) {
812 SaveCheckedFieldStatus(this, statusArray);
813 }
814 CFX_WideString csWExport = pControl->GetExportValue();
815 CFX_ByteString csBExport = PDF_EncodeText(csWExport);
816 int iCount = CountControls();
817 FX_BOOL bUnison = PDF_FormField_IsUnison(this);
818 for (int i = 0; i < iCount; i ++) {
819 CPDF_FormControl* pCtrl = GetControl(i);
820 if (bUnison) {
821 CFX_WideString csEValue = pCtrl->GetExportValue();
822 if (csEValue == csWExport) {
823 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
824 pCtrl->CheckControl(bChecked);
825 } else if (bChecked) {
826 pCtrl->CheckControl(FALSE);
827 }
828 } else if (bChecked) {
829 pCtrl->CheckControl(FALSE);
830 }
831 } else {
832 if (i == iControlIndex) {
833 pCtrl->CheckControl(bChecked);
834 } else if (bChecked) {
835 pCtrl->CheckControl(FALSE);
836 }
837 }
838 }
839 CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
840 if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) {
841 if (bChecked) {
842 m_pDict->SetAtName("V", csBExport);
843 } else {
844 CFX_ByteString csV;
845 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
846 if (pV != NULL) {
847 csV = pV->GetString();
848 }
849 if (csV == csBExport) {
850 m_pDict->SetAtName("V", "Off");
851 }
852 }
853 } else if (bChecked) {
854 CFX_ByteString csIndex;
855 csIndex.Format("%d", iControlIndex);
856 m_pDict->SetAtName("V", csIndex);
857 }
858 if (bNotify && m_pForm->m_pFormNotify != NULL) {
859 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
860 }
861 m_pForm->m_bUpdated = TRUE;
862 return TRUE;
863 }
GetCheckValue(FX_BOOL bDefault)864 CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault)
865 {
866 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
867 CFX_WideString csExport = L"Off";
868 FX_BOOL bChecked;
869 int iCount = CountControls();
870 for (int i = 0; i < iCount; i ++) {
871 CPDF_FormControl* pControl = GetControl(i);
872 if (bDefault) {
873 bChecked = pControl->IsDefaultChecked();
874 } else {
875 bChecked = pControl->IsChecked();
876 }
877 if (bChecked) {
878 csExport = pControl->GetExportValue();
879 break;
880 }
881 }
882 return csExport;
883 }
SetCheckValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)884 FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
885 {
886 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
887 CFX_ByteArray statusArray;
888 if (bNotify && m_pForm->m_pFormNotify != NULL) {
889 SaveCheckedFieldStatus(this, statusArray);
890 }
891 int iCount = CountControls();
892 for (int i = 0; i < iCount; i ++) {
893 CPDF_FormControl* pControl = GetControl(i);
894 CFX_WideString csExport = pControl->GetExportValue();
895 if (csExport == value) {
896 if (bDefault) {
897 } else {
898 CheckControl(GetControlIndex(pControl), TRUE);
899 }
900 break;
901 } else {
902 if (bDefault) {
903 } else {
904 CheckControl(GetControlIndex(pControl), FALSE);
905 }
906 }
907 }
908 if (bNotify && m_pForm->m_pFormNotify != NULL) {
909 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
910 }
911 m_pForm->m_bUpdated = TRUE;
912 return TRUE;
913 }
GetTopVisibleIndex()914 int CPDF_FormField::GetTopVisibleIndex()
915 {
916 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
917 if (pObj == NULL) {
918 return 0;
919 }
920 return pObj->GetInteger();
921 }
CountSelectedOptions()922 int CPDF_FormField::CountSelectedOptions()
923 {
924 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
925 if (pObj == NULL) {
926 return 0;
927 }
928 CPDF_Array* pArray = pObj->GetArray();
929 if (pArray == NULL) {
930 return 0;
931 }
932 return (int)pArray->GetCount();
933 }
GetSelectedOptionIndex(int index)934 int CPDF_FormField::GetSelectedOptionIndex(int index)
935 {
936 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
937 if (pObj == NULL) {
938 return -1;
939 }
940 CPDF_Array* pArray = pObj->GetArray();
941 if (pArray == NULL) {
942 return -1;
943 }
944 int iCount = (int)pArray->GetCount();
945 if (iCount > 0 && index < iCount) {
946 return pArray->GetInteger(index);
947 }
948 return -1;
949 }
IsOptionSelected(int iOptIndex)950 FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex)
951 {
952 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
953 if (pObj == NULL) {
954 return FALSE;
955 }
956 CPDF_Array* pArray = pObj->GetArray();
957 if (pArray == NULL) {
958 return FALSE;
959 }
960 int iCount = (int)pArray->GetCount();
961 for (int i = 0; i < iCount; i ++) {
962 if (pArray->GetInteger(i) == iOptIndex) {
963 return TRUE;
964 }
965 }
966 return FALSE;
967 }
SelectOption(int iOptIndex,FX_BOOL bSelected,FX_BOOL bNotify)968 FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify)
969 {
970 CPDF_Array* pArray = m_pDict->GetArray("I");
971 if (pArray == NULL) {
972 if (!bSelected) {
973 return TRUE;
974 }
975 pArray = CPDF_Array::Create();
976 if (pArray == NULL) {
977 return FALSE;
978 }
979 m_pDict->SetAt("I", pArray);
980 }
981 FX_BOOL bReturn = FALSE;
982 for (int i = 0; i < (int)pArray->GetCount(); i ++) {
983 int iFind = pArray->GetInteger(i);
984 if (iFind == iOptIndex) {
985 if (bSelected) {
986 return TRUE;
987 }
988 if (bNotify && m_pForm->m_pFormNotify != NULL) {
989 int iRet = 0;
990 CFX_WideString csValue = GetOptionLabel(iOptIndex);
991 if (GetType() == ListBox) {
992 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
993 }
994 if (GetType() == ComboBox) {
995 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
996 }
997 if (iRet < 0) {
998 return FALSE;
999 }
1000 }
1001 pArray->RemoveAt(i);
1002 bReturn = TRUE;
1003 break;
1004 } else if (iFind > iOptIndex) {
1005 if (!bSelected) {
1006 continue;
1007 }
1008 if (bNotify && m_pForm->m_pFormNotify != NULL) {
1009 int iRet = 0;
1010 CFX_WideString csValue = GetOptionLabel(iOptIndex);
1011 if (GetType() == ListBox) {
1012 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1013 }
1014 if (GetType() == ComboBox) {
1015 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1016 }
1017 if (iRet < 0) {
1018 return FALSE;
1019 }
1020 }
1021 CPDF_Number* pNum = CPDF_Number::Create(iOptIndex);
1022 if (pNum == NULL) {
1023 return FALSE;
1024 }
1025 pArray->InsertAt(i, pNum);
1026 bReturn = TRUE;
1027 break;
1028 }
1029 }
1030 if (!bReturn) {
1031 if (bSelected) {
1032 pArray->AddInteger(iOptIndex);
1033 }
1034 if (pArray->GetCount() == 0) {
1035 m_pDict->RemoveAt("I");
1036 }
1037 }
1038 if (bNotify && m_pForm->m_pFormNotify != NULL) {
1039 if (GetType() == ListBox) {
1040 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1041 }
1042 if (GetType() == ComboBox) {
1043 m_pForm->m_pFormNotify->AfterValueChange(this);
1044 }
1045 }
1046 m_pForm->m_bUpdated = TRUE;
1047 return TRUE;
1048 }
ClearSelectedOptions(FX_BOOL bNotify)1049 FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify)
1050 {
1051 if (bNotify && m_pForm->m_pFormNotify != NULL) {
1052 int iRet = 0;
1053 CFX_WideString csValue;
1054 int iIndex = GetSelectedIndex(0);
1055 if (iIndex >= 0) {
1056 csValue = GetOptionLabel(iIndex);
1057 }
1058 if (GetType() == ListBox) {
1059 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1060 }
1061 if (GetType() == ComboBox) {
1062 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1063 }
1064 if (iRet < 0) {
1065 return FALSE;
1066 }
1067 }
1068 m_pDict->RemoveAt("I");
1069 if (bNotify && m_pForm->m_pFormNotify != NULL) {
1070 if (GetType() == ListBox) {
1071 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1072 }
1073 if (GetType() == ComboBox) {
1074 m_pForm->m_pFormNotify->AfterValueChange(this);
1075 }
1076 }
1077 m_pForm->m_bUpdated = TRUE;
1078 return TRUE;
1079 }
LoadDA()1080 void CPDF_FormField::LoadDA()
1081 {
1082 CFX_ByteString DA;
1083 if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
1084 DA = pObj_t->GetString();
1085 }
1086 if (DA.IsEmpty() && m_pForm->m_pFormDict) {
1087 DA = m_pForm->m_pFormDict->GetString("DA");
1088 }
1089 if (DA.IsEmpty()) {
1090 return;
1091 }
1092 CPDF_SimpleParser syntax(DA);
1093 syntax.FindTagParam("Tf", 2);
1094 CFX_ByteString font_name = syntax.GetWord();
1095 CPDF_Dictionary* pFontDict = NULL;
1096 if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDict("DR") &&
1097 m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font") )
1098 pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
1099
1100 if (pFontDict == NULL) {
1101 return;
1102 }
1103 m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1104 m_FontSize = FX_atof(syntax.GetWord());
1105 }
1106