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 "core/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 FX_BOOL bUnison = FALSE;
12 if (pField->GetType() == CPDF_FormField::CheckBox) {
13 bUnison = TRUE;
14 } else {
15 FX_DWORD dwFlags = pField->GetFieldFlags();
16 bUnison = ((dwFlags & 0x2000000) != 0);
17 }
18 return bUnison;
19 }
CPDF_FormField(CPDF_InterForm * pForm,CPDF_Dictionary * pDict)20 CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict) {
21 m_pDict = pDict;
22 m_Type = Unknown;
23 m_pForm = pForm;
24 m_pFont = NULL;
25 m_FontSize = 0;
26 SyncFieldFlags();
27 }
~CPDF_FormField()28 CPDF_FormField::~CPDF_FormField() {}
SyncFieldFlags()29 void CPDF_FormField::SyncFieldFlags() {
30 CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT")
31 ? FPDF_GetFieldAttr(m_pDict, "FT")->GetString()
32 : CFX_ByteString();
33 FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")
34 ? FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger()
35 : 0;
36 m_Flags = 0;
37 if (flags & 1) {
38 m_Flags |= FORMFIELD_READONLY;
39 }
40 if (flags & 2) {
41 m_Flags |= FORMFIELD_REQUIRED;
42 }
43 if (flags & 4) {
44 m_Flags |= FORMFIELD_NOEXPORT;
45 }
46 if (type_name == "Btn") {
47 if (flags & 0x8000) {
48 m_Type = RadioButton;
49 if (flags & 0x4000) {
50 m_Flags |= FORMRADIO_NOTOGGLEOFF;
51 }
52 if (flags & 0x2000000) {
53 m_Flags |= FORMRADIO_UNISON;
54 }
55 } else if (flags & 0x10000) {
56 m_Type = PushButton;
57 } else {
58 m_Type = CheckBox;
59 }
60 } else if (type_name == "Tx") {
61 if (flags & 0x100000) {
62 m_Type = File;
63 } else if (flags & 0x2000000) {
64 m_Type = RichText;
65 } else {
66 m_Type = Text;
67 if (flags & 0x1000) {
68 m_Flags |= FORMTEXT_MULTILINE;
69 }
70 if (flags & 0x2000) {
71 m_Flags |= FORMTEXT_PASSWORD;
72 }
73 if (flags & 0x800000) {
74 m_Flags |= FORMTEXT_NOSCROLL;
75 }
76 if (flags & 0x100000) {
77 m_Flags |= FORMTEXT_COMB;
78 }
79 }
80 LoadDA();
81 } else if (type_name == "Ch") {
82 if (flags & 0x20000) {
83 m_Type = ComboBox;
84 if (flags & 0x40000) {
85 m_Flags |= FORMCOMBO_EDIT;
86 }
87 } else {
88 m_Type = ListBox;
89 if (flags & 0x200000) {
90 m_Flags |= FORMLIST_MULTISELECT;
91 }
92 }
93 LoadDA();
94 } else if (type_name == "Sig") {
95 m_Type = Sign;
96 }
97 }
GetFullName()98 CFX_WideString CPDF_FormField::GetFullName() {
99 return ::GetFullName(m_pDict);
100 }
ResetField(FX_BOOL bNotify)101 FX_BOOL CPDF_FormField::ResetField(FX_BOOL bNotify) {
102 switch (m_Type) {
103 case CPDF_FormField::CheckBox:
104 case CPDF_FormField::RadioButton: {
105 CFX_ByteArray statusArray;
106 if (bNotify && m_pForm->m_pFormNotify) {
107 SaveCheckedFieldStatus(this, statusArray);
108 }
109 int iCount = CountControls();
110 if (iCount) {
111 if (PDF_FormField_IsUnison(this)) {
112 for (int i = 0; i < iCount; i++) {
113 CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE);
114 }
115 } else {
116 for (int i = 0; i < iCount; i++) {
117 CPDF_FormControl* pControl = GetControl(i);
118 FX_BOOL bChecked = pControl->IsDefaultChecked();
119 CheckControl(i, bChecked, FALSE);
120 }
121 }
122 }
123 if (bNotify && m_pForm->m_pFormNotify) {
124 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
125 }
126 } break;
127 case CPDF_FormField::ComboBox: {
128 CFX_WideString csValue;
129 ClearSelection();
130 int iIndex = GetDefaultSelectedItem();
131 if (iIndex >= 0) {
132 csValue = GetOptionLabel(iIndex);
133 }
134 if (bNotify && m_pForm->m_pFormNotify) {
135 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
136 if (iRet < 0) {
137 return FALSE;
138 }
139 }
140 SetItemSelection(iIndex, TRUE);
141 if (bNotify && m_pForm->m_pFormNotify) {
142 m_pForm->m_pFormNotify->AfterValueChange(this);
143 }
144 } break;
145 case CPDF_FormField::ListBox: {
146 CFX_WideString csValue;
147 ClearSelection();
148 int iIndex = GetDefaultSelectedItem();
149 if (iIndex >= 0) {
150 csValue = GetOptionLabel(iIndex);
151 }
152 if (bNotify && m_pForm->m_pFormNotify) {
153 int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
154 if (iRet < 0) {
155 return FALSE;
156 }
157 }
158 SetItemSelection(iIndex, TRUE);
159 if (bNotify && m_pForm->m_pFormNotify) {
160 m_pForm->m_pFormNotify->AfterSelectionChange(this);
161 }
162 } break;
163 case CPDF_FormField::Text:
164 case CPDF_FormField::RichText:
165 case CPDF_FormField::File:
166 default: {
167 CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV");
168 CFX_WideString csDValue;
169 if (pDV) {
170 csDValue = pDV->GetUnicodeText();
171 }
172 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
173 CFX_WideString csValue;
174 if (pV) {
175 csValue = pV->GetUnicodeText();
176 }
177 CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV");
178 if (!pRV && (csDValue == csValue)) {
179 return FALSE;
180 }
181 if (bNotify && m_pForm->m_pFormNotify) {
182 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csDValue);
183 if (iRet < 0) {
184 return FALSE;
185 }
186 }
187 if (pDV) {
188 CPDF_Object* pClone = pDV->Clone();
189 if (!pClone) {
190 return FALSE;
191 }
192 m_pDict->SetAt("V", pClone);
193 if (pRV) {
194 CPDF_Object* pCloneR = pDV->Clone();
195 m_pDict->SetAt("RV", pCloneR);
196 }
197 } else {
198 m_pDict->RemoveAt("V");
199 m_pDict->RemoveAt("RV");
200 }
201 if (bNotify && m_pForm->m_pFormNotify) {
202 m_pForm->m_pFormNotify->AfterValueChange(this);
203 }
204 m_pForm->m_bUpdated = TRUE;
205 } break;
206 }
207 return TRUE;
208 }
GetControlIndex(const CPDF_FormControl * pControl)209 int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl) {
210 if (!pControl) {
211 return -1;
212 }
213 for (int i = 0; i < m_ControlList.GetSize(); i++) {
214 if (m_ControlList.GetAt(i) == pControl)
215 return i;
216 }
217 return -1;
218 }
GetFieldType()219 int CPDF_FormField::GetFieldType() {
220 switch (m_Type) {
221 case PushButton:
222 return FIELDTYPE_PUSHBUTTON;
223 case CheckBox:
224 return FIELDTYPE_CHECKBOX;
225 case RadioButton:
226 return FIELDTYPE_RADIOBUTTON;
227 case ComboBox:
228 return FIELDTYPE_COMBOBOX;
229 case ListBox:
230 return FIELDTYPE_LISTBOX;
231 case Text:
232 case RichText:
233 case File:
234 return FIELDTYPE_TEXTFIELD;
235 case Sign:
236 return FIELDTYPE_SIGNATURE;
237 default:
238 break;
239 }
240 return FIELDTYPE_UNKNOWN;
241 }
GetAdditionalAction()242 CPDF_AAction CPDF_FormField::GetAdditionalAction() {
243 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA");
244 if (!pObj) {
245 return NULL;
246 }
247 return pObj->GetDict();
248 }
GetAlternateName()249 CFX_WideString CPDF_FormField::GetAlternateName() {
250 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU");
251 if (!pObj) {
252 return L"";
253 }
254 return pObj->GetUnicodeText();
255 }
GetMappingName()256 CFX_WideString CPDF_FormField::GetMappingName() {
257 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM");
258 if (!pObj) {
259 return L"";
260 }
261 return pObj->GetUnicodeText();
262 }
GetFieldFlags()263 FX_DWORD CPDF_FormField::GetFieldFlags() {
264 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff");
265 if (!pObj) {
266 return 0;
267 }
268 return pObj->GetInteger();
269 }
GetDefaultStyle()270 CFX_ByteString CPDF_FormField::GetDefaultStyle() {
271 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS");
272 if (!pObj) {
273 return "";
274 }
275 return pObj->GetString();
276 }
GetRichTextString()277 CFX_WideString CPDF_FormField::GetRichTextString() {
278 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV");
279 if (!pObj) {
280 return L"";
281 }
282 return pObj->GetUnicodeText();
283 }
GetValue(FX_BOOL bDefault)284 CFX_WideString CPDF_FormField::GetValue(FX_BOOL bDefault) {
285 if (GetType() == CheckBox || GetType() == RadioButton) {
286 return GetCheckValue(bDefault);
287 }
288 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V");
289 if (!pValue) {
290 if (!bDefault) {
291 if (m_Type == RichText) {
292 pValue = FPDF_GetFieldAttr(m_pDict, "V");
293 }
294 if (!pValue && m_Type != Text) {
295 pValue = FPDF_GetFieldAttr(m_pDict, "DV");
296 }
297 }
298 if (!pValue) {
299 return CFX_WideString();
300 }
301 }
302 switch (pValue->GetType()) {
303 case PDFOBJ_STRING:
304 case PDFOBJ_STREAM:
305 return pValue->GetUnicodeText();
306 case PDFOBJ_ARRAY:
307 pValue = pValue->AsArray()->GetElementValue(0);
308 if (pValue)
309 return pValue->GetUnicodeText();
310 break;
311 }
312 return CFX_WideString();
313 }
GetValue()314 CFX_WideString CPDF_FormField::GetValue() {
315 return GetValue(FALSE);
316 }
GetDefaultValue()317 CFX_WideString CPDF_FormField::GetDefaultValue() {
318 return GetValue(TRUE);
319 }
SetValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)320 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value,
321 FX_BOOL bDefault,
322 FX_BOOL bNotify) {
323 switch (m_Type) {
324 case CheckBox:
325 case RadioButton: {
326 SetCheckValue(value, bDefault, bNotify);
327 return TRUE;
328 }
329 case File:
330 case RichText:
331 case Text:
332 case ComboBox: {
333 CFX_WideString csValue = value;
334 if (bNotify && m_pForm->m_pFormNotify) {
335 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
336 if (iRet < 0) {
337 return FALSE;
338 }
339 }
340 int iIndex = FindOptionValue(csValue);
341 if (iIndex < 0) {
342 CFX_ByteString bsEncodeText = PDF_EncodeText(csValue);
343 m_pDict->SetAtString(bDefault ? "DV" : "V", bsEncodeText);
344 if (m_Type == RichText && !bDefault) {
345 m_pDict->SetAtString("RV", bsEncodeText);
346 }
347 m_pDict->RemoveAt("I");
348 } else {
349 m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue));
350 if (bDefault) {
351 } else {
352 ClearSelection();
353 SetItemSelection(iIndex, TRUE);
354 }
355 }
356 if (bNotify && m_pForm->m_pFormNotify) {
357 m_pForm->m_pFormNotify->AfterValueChange(this);
358 }
359 m_pForm->m_bUpdated = TRUE;
360 } break;
361 case ListBox: {
362 int iIndex = FindOptionValue(value);
363 if (iIndex < 0) {
364 return FALSE;
365 }
366 if (bDefault && iIndex == GetDefaultSelectedItem()) {
367 return FALSE;
368 }
369 if (bNotify && m_pForm->m_pFormNotify) {
370 CFX_WideString csValue = value;
371 int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
372 if (iRet < 0) {
373 return FALSE;
374 }
375 }
376 if (bDefault) {
377 } else {
378 ClearSelection();
379 SetItemSelection(iIndex, TRUE);
380 }
381 if (bNotify && m_pForm->m_pFormNotify) {
382 m_pForm->m_pFormNotify->AfterSelectionChange(this);
383 }
384 m_pForm->m_bUpdated = TRUE;
385 break;
386 }
387 default:
388 break;
389 }
390 if (CPDF_InterForm::m_bUpdateAP) {
391 UpdateAP(NULL);
392 }
393 return TRUE;
394 }
SetValue(const CFX_WideString & value,FX_BOOL bNotify)395 FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify) {
396 return SetValue(value, FALSE, bNotify);
397 }
GetMaxLen()398 int CPDF_FormField::GetMaxLen() {
399 if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen"))
400 return pObj->GetInteger();
401
402 for (int i = 0; i < m_ControlList.GetSize(); i++) {
403 CPDF_FormControl* pControl = m_ControlList.GetAt(i);
404 if (!pControl)
405 continue;
406
407 CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict;
408 if (pWidgetDict->KeyExist("MaxLen"))
409 return pWidgetDict->GetInteger("MaxLen");
410 }
411 return 0;
412 }
CountSelectedItems()413 int CPDF_FormField::CountSelectedItems() {
414 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
415 if (!pValue) {
416 pValue = FPDF_GetFieldAttr(m_pDict, "I");
417 if (!pValue)
418 return 0;
419 }
420
421 if (pValue->IsString() || pValue->IsNumber())
422 return pValue->GetString().IsEmpty() ? 0 : 1;
423 if (CPDF_Array* pArray = pValue->AsArray())
424 return pArray->GetCount();
425 return 0;
426 }
GetSelectedIndex(int index)427 int CPDF_FormField::GetSelectedIndex(int index) {
428 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
429 if (!pValue) {
430 pValue = FPDF_GetFieldAttr(m_pDict, "I");
431 if (!pValue)
432 return -1;
433 }
434 if (pValue->IsNumber())
435 return pValue->GetInteger();
436
437 CFX_WideString sel_value;
438 if (pValue->IsString()) {
439 if (index != 0)
440 return -1;
441 sel_value = pValue->GetUnicodeText();
442 } else {
443 CPDF_Array* pArray = pValue->AsArray();
444 if (!pArray || index < 0)
445 return -1;
446
447 CPDF_Object* elementValue = pArray->GetElementValue(index);
448 sel_value =
449 elementValue ? elementValue->GetUnicodeText() : CFX_WideString();
450 }
451 if (index < CountSelectedOptions()) {
452 int iOptIndex = GetSelectedOptionIndex(index);
453 CFX_WideString csOpt = GetOptionValue(iOptIndex);
454 if (csOpt == sel_value) {
455 return iOptIndex;
456 }
457 }
458 int nOpts = CountOptions();
459 for (int i = 0; i < nOpts; i++) {
460 if (sel_value == GetOptionValue(i)) {
461 return i;
462 }
463 }
464 return -1;
465 }
ClearSelection(FX_BOOL bNotify)466 FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify) {
467 if (bNotify && m_pForm->m_pFormNotify) {
468 int iRet = 0;
469 CFX_WideString csValue;
470 int iIndex = GetSelectedIndex(0);
471 if (iIndex >= 0) {
472 csValue = GetOptionLabel(iIndex);
473 }
474 if (GetType() == ListBox) {
475 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
476 }
477 if (GetType() == ComboBox) {
478 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
479 }
480 if (iRet < 0) {
481 return FALSE;
482 }
483 }
484 m_pDict->RemoveAt("V");
485 m_pDict->RemoveAt("I");
486 if (bNotify && m_pForm->m_pFormNotify) {
487 if (GetType() == ListBox) {
488 m_pForm->m_pFormNotify->AfterSelectionChange(this);
489 }
490 if (GetType() == ComboBox) {
491 m_pForm->m_pFormNotify->AfterValueChange(this);
492 }
493 }
494 if (CPDF_InterForm::m_bUpdateAP) {
495 UpdateAP(NULL);
496 }
497 m_pForm->m_bUpdated = TRUE;
498 return TRUE;
499 }
IsItemSelected(int index)500 FX_BOOL CPDF_FormField::IsItemSelected(int index) {
501 ASSERT(GetType() == ComboBox || GetType() == ListBox);
502 if (index < 0 || index >= CountOptions()) {
503 return FALSE;
504 }
505 if (IsOptionSelected(index)) {
506 return TRUE;
507 }
508 CFX_WideString opt_value = GetOptionValue(index);
509 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
510 if (!pValue) {
511 pValue = FPDF_GetFieldAttr(m_pDict, "I");
512 if (!pValue) {
513 return FALSE;
514 }
515 }
516
517 if (pValue->IsString())
518 return pValue->GetUnicodeText() == opt_value;
519
520 if (pValue->IsNumber()) {
521 if (pValue->GetString().IsEmpty())
522 return FALSE;
523 return (pValue->GetInteger() == index);
524 }
525
526 CPDF_Array* pArray = pValue->AsArray();
527 if (!pArray)
528 return FALSE;
529
530 int iPos = -1;
531 for (int j = 0; j < CountSelectedOptions(); j++) {
532 if (GetSelectedOptionIndex(j) == index) {
533 iPos = j;
534 break;
535 }
536 }
537 for (FX_DWORD i = 0; i < pArray->GetCount(); i++)
538 if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value &&
539 (int)i == iPos) {
540 return TRUE;
541 }
542 return FALSE;
543 }
SetItemSelection(int index,FX_BOOL bSelected,FX_BOOL bNotify)544 FX_BOOL CPDF_FormField::SetItemSelection(int index,
545 FX_BOOL bSelected,
546 FX_BOOL bNotify) {
547 ASSERT(GetType() == ComboBox || GetType() == ListBox);
548 if (index < 0 || index >= CountOptions()) {
549 return FALSE;
550 }
551 CFX_WideString opt_value = GetOptionValue(index);
552 if (bNotify && m_pForm->m_pFormNotify) {
553 int iRet = 0;
554 if (GetType() == ListBox) {
555 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
556 }
557 if (GetType() == ComboBox) {
558 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
559 }
560 if (iRet < 0) {
561 return FALSE;
562 }
563 }
564 if (!bSelected) {
565 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
566 if (pValue) {
567 if (m_Type == ListBox) {
568 SelectOption(index, FALSE);
569 if (pValue->IsString()) {
570 if (pValue->GetUnicodeText() == opt_value) {
571 m_pDict->RemoveAt("V");
572 }
573 } else if (pValue->IsArray()) {
574 CPDF_Array* pArray = new CPDF_Array;
575 int iCount = CountOptions();
576 for (int i = 0; i < iCount; i++) {
577 if (i != index) {
578 if (IsItemSelected(i)) {
579 opt_value = GetOptionValue(i);
580 pArray->AddString(PDF_EncodeText(opt_value));
581 }
582 }
583 }
584 if (pArray->GetCount() < 1) {
585 pArray->Release();
586 } else {
587 m_pDict->SetAt("V", pArray);
588 }
589 }
590 } else if (m_Type == ComboBox) {
591 m_pDict->RemoveAt("V");
592 m_pDict->RemoveAt("I");
593 }
594 }
595 } else {
596 if (m_Type == ListBox) {
597 SelectOption(index, TRUE);
598 if (!(m_Flags & FORMLIST_MULTISELECT)) {
599 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
600 } else {
601 CPDF_Array* pArray = new CPDF_Array;
602 int iCount = CountOptions();
603 for (int i = 0; i < iCount; i++) {
604 FX_BOOL bSelected;
605 if (i != index) {
606 bSelected = IsItemSelected(i);
607 } else {
608 bSelected = TRUE;
609 }
610 if (bSelected) {
611 opt_value = GetOptionValue(i);
612 pArray->AddString(PDF_EncodeText(opt_value));
613 }
614 }
615 m_pDict->SetAt("V", pArray);
616 }
617 } else if (m_Type == ComboBox) {
618 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
619 CPDF_Array* pI = new CPDF_Array;
620 pI->AddInteger(index);
621 m_pDict->SetAt("I", pI);
622 }
623 }
624 if (bNotify && m_pForm->m_pFormNotify) {
625 if (GetType() == ListBox) {
626 m_pForm->m_pFormNotify->AfterSelectionChange(this);
627 }
628 if (GetType() == ComboBox) {
629 m_pForm->m_pFormNotify->AfterValueChange(this);
630 }
631 }
632 if (CPDF_InterForm::m_bUpdateAP) {
633 UpdateAP(NULL);
634 }
635 m_pForm->m_bUpdated = TRUE;
636 return TRUE;
637 }
IsItemDefaultSelected(int index)638 FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index) {
639 ASSERT(GetType() == ComboBox || GetType() == ListBox);
640 if (index < 0 || index >= CountOptions()) {
641 return FALSE;
642 }
643 int iDVIndex = GetDefaultSelectedItem();
644 if (iDVIndex < 0) {
645 return FALSE;
646 }
647 return (iDVIndex == index);
648 }
GetDefaultSelectedItem()649 int CPDF_FormField::GetDefaultSelectedItem() {
650 ASSERT(GetType() == ComboBox || GetType() == ListBox);
651 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
652 if (!pValue) {
653 return -1;
654 }
655 CFX_WideString csDV = pValue->GetUnicodeText();
656 if (csDV.IsEmpty()) {
657 return -1;
658 }
659 int iCount = CountOptions();
660 for (int i = 0; i < iCount; i++) {
661 if (csDV == GetOptionValue(i)) {
662 return i;
663 }
664 }
665 return -1;
666 }
UpdateAP(CPDF_FormControl * pControl)667 void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl) {
668 if (m_Type == PushButton) {
669 return;
670 }
671 if (m_Type == RadioButton || m_Type == CheckBox) {
672 return;
673 }
674 if (!m_pForm->m_bGenerateAP) {
675 return;
676 }
677 for (int i = 0; i < CountControls(); i++) {
678 CPDF_FormControl* pControl = GetControl(i);
679 FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
680 }
681 }
CountOptions()682 int CPDF_FormField::CountOptions() {
683 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
684 return pArray ? pArray->GetCount() : 0;
685 }
GetOptionText(int index,int sub_index)686 CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index) {
687 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
688 if (!pArray)
689 return CFX_WideString();
690
691 CPDF_Object* pOption = pArray->GetElementValue(index);
692 if (!pOption)
693 return CFX_WideString();
694 if (CPDF_Array* pOptionArray = pOption->AsArray())
695 pOption = pOptionArray->GetElementValue(sub_index);
696
697 CPDF_String* pString = ToString(pOption);
698 return pString ? pString->GetUnicodeText() : CFX_WideString();
699 }
GetOptionLabel(int index)700 CFX_WideString CPDF_FormField::GetOptionLabel(int index) {
701 return GetOptionText(index, 1);
702 }
GetOptionValue(int index)703 CFX_WideString CPDF_FormField::GetOptionValue(int index) {
704 return GetOptionText(index, 0);
705 }
FindOption(CFX_WideString csOptLabel)706 int CPDF_FormField::FindOption(CFX_WideString csOptLabel) {
707 int iCount = CountOptions();
708 for (int i = 0; i < iCount; i++) {
709 CFX_WideString csValue = GetOptionValue(i);
710 if (csValue == csOptLabel) {
711 return i;
712 }
713 }
714 return -1;
715 }
FindOptionValue(const CFX_WideString & csOptValue,int iStartIndex)716 int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue,
717 int iStartIndex) {
718 if (iStartIndex < 0) {
719 iStartIndex = 0;
720 }
721 int iCount = CountOptions();
722 for (; iStartIndex < iCount; iStartIndex++) {
723 CFX_WideString csValue = GetOptionValue(iStartIndex);
724 if (csValue == csOptValue) {
725 return iStartIndex;
726 }
727 }
728 return -1;
729 }
730 #ifdef PDF_ENABLE_XFA
InsertOption(CFX_WideString csOptLabel,int index,FX_BOOL bNotify)731 int CPDF_FormField::InsertOption(CFX_WideString csOptLabel,
732 int index,
733 FX_BOOL bNotify) {
734 if (csOptLabel.IsEmpty())
735 return -1;
736
737 if (bNotify && m_pForm->m_pFormNotify) {
738 int iRet = 0;
739 if (GetType() == ListBox)
740 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csOptLabel);
741 if (GetType() == ComboBox)
742 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csOptLabel);
743 if (iRet < 0)
744 return -1;
745 }
746
747 CFX_ByteString csStr = PDF_EncodeText(csOptLabel, csOptLabel.GetLength());
748 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
749 CPDF_Array* pOpt = ToArray(pValue);
750 if (!pOpt) {
751 pOpt = new CPDF_Array;
752 m_pDict->SetAt("Opt", pOpt);
753 }
754
755 int iCount = (int)pOpt->GetCount();
756 if (index < 0 || index >= iCount) {
757 pOpt->AddString(csStr);
758 index = iCount;
759 } else {
760 CPDF_String* pString = new CPDF_String(csStr, FALSE);
761 pOpt->InsertAt(index, pString);
762 }
763
764 if (bNotify && m_pForm->m_pFormNotify) {
765 if (GetType() == ListBox)
766 m_pForm->m_pFormNotify->AfterSelectionChange(this);
767 if (GetType() == ComboBox)
768 m_pForm->m_pFormNotify->AfterValueChange(this);
769 }
770 m_pForm->m_bUpdated = TRUE;
771 return index;
772 }
ClearOptions(FX_BOOL bNotify)773 FX_BOOL CPDF_FormField::ClearOptions(FX_BOOL bNotify) {
774 if (bNotify && m_pForm->m_pFormNotify) {
775 int iRet = 0;
776 CFX_WideString csValue;
777 int iIndex = GetSelectedIndex(0);
778 if (iIndex >= 0)
779 csValue = GetOptionLabel(iIndex);
780 if (GetType() == ListBox)
781 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
782 if (GetType() == ComboBox)
783 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
784 if (iRet < 0)
785 return FALSE;
786 }
787
788 m_pDict->RemoveAt("Opt");
789 m_pDict->RemoveAt("V");
790 m_pDict->RemoveAt("DV");
791 m_pDict->RemoveAt("I");
792 m_pDict->RemoveAt("TI");
793
794 if (bNotify && m_pForm->m_pFormNotify) {
795 if (GetType() == ListBox)
796 m_pForm->m_pFormNotify->AfterSelectionChange(this);
797 if (GetType() == ComboBox)
798 m_pForm->m_pFormNotify->AfterValueChange(this);
799 }
800
801 m_pForm->m_bUpdated = TRUE;
802 return TRUE;
803 }
804 #endif // PDF_ENABLE_XFA
CheckControl(int iControlIndex,FX_BOOL bChecked,FX_BOOL bNotify)805 FX_BOOL CPDF_FormField::CheckControl(int iControlIndex,
806 FX_BOOL bChecked,
807 FX_BOOL bNotify) {
808 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
809 CPDF_FormControl* pControl = GetControl(iControlIndex);
810 if (!pControl) {
811 return FALSE;
812 }
813 if (!bChecked && pControl->IsChecked() == bChecked) {
814 return FALSE;
815 }
816 CFX_ByteArray statusArray;
817 if (bNotify && m_pForm->m_pFormNotify) {
818 SaveCheckedFieldStatus(this, statusArray);
819 }
820 CFX_WideString csWExport = pControl->GetExportValue();
821 CFX_ByteString csBExport = PDF_EncodeText(csWExport);
822 int iCount = CountControls();
823 FX_BOOL bUnison = PDF_FormField_IsUnison(this);
824 for (int i = 0; i < iCount; i++) {
825 CPDF_FormControl* pCtrl = GetControl(i);
826 if (bUnison) {
827 CFX_WideString csEValue = pCtrl->GetExportValue();
828 if (csEValue == csWExport) {
829 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
830 pCtrl->CheckControl(bChecked);
831 } else if (bChecked) {
832 pCtrl->CheckControl(FALSE);
833 }
834 } else if (bChecked) {
835 pCtrl->CheckControl(FALSE);
836 }
837 } else {
838 if (i == iControlIndex) {
839 pCtrl->CheckControl(bChecked);
840 } else if (bChecked) {
841 pCtrl->CheckControl(FALSE);
842 }
843 }
844 }
845 CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
846 if (!ToArray(pOpt)) {
847 if (bChecked) {
848 m_pDict->SetAtName("V", csBExport);
849 } else {
850 CFX_ByteString csV;
851 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
852 if (pV) {
853 csV = pV->GetString();
854 }
855 if (csV == csBExport) {
856 m_pDict->SetAtName("V", "Off");
857 }
858 }
859 } else if (bChecked) {
860 CFX_ByteString csIndex;
861 csIndex.Format("%d", iControlIndex);
862 m_pDict->SetAtName("V", csIndex);
863 }
864 if (bNotify && m_pForm->m_pFormNotify) {
865 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
866 }
867 m_pForm->m_bUpdated = TRUE;
868 return TRUE;
869 }
GetCheckValue(FX_BOOL bDefault)870 CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault) {
871 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
872 CFX_WideString csExport = L"Off";
873 FX_BOOL bChecked;
874 int iCount = CountControls();
875 for (int i = 0; i < iCount; i++) {
876 CPDF_FormControl* pControl = GetControl(i);
877 if (bDefault) {
878 bChecked = pControl->IsDefaultChecked();
879 } else {
880 bChecked = pControl->IsChecked();
881 }
882 if (bChecked) {
883 csExport = pControl->GetExportValue();
884 break;
885 }
886 }
887 return csExport;
888 }
SetCheckValue(const CFX_WideString & value,FX_BOOL bDefault,FX_BOOL bNotify)889 FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value,
890 FX_BOOL bDefault,
891 FX_BOOL bNotify) {
892 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
893 CFX_ByteArray statusArray;
894 if (bNotify && m_pForm->m_pFormNotify) {
895 SaveCheckedFieldStatus(this, statusArray);
896 }
897 int iCount = CountControls();
898 for (int i = 0; i < iCount; i++) {
899 CPDF_FormControl* pControl = GetControl(i);
900 CFX_WideString csExport = pControl->GetExportValue();
901 if (csExport == value) {
902 if (bDefault) {
903 } else {
904 CheckControl(GetControlIndex(pControl), TRUE);
905 }
906 break;
907 } else {
908 if (bDefault) {
909 } else {
910 CheckControl(GetControlIndex(pControl), FALSE);
911 }
912 }
913 }
914 if (bNotify && m_pForm->m_pFormNotify) {
915 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
916 }
917 m_pForm->m_bUpdated = TRUE;
918 return TRUE;
919 }
GetTopVisibleIndex()920 int CPDF_FormField::GetTopVisibleIndex() {
921 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
922 if (!pObj) {
923 return 0;
924 }
925 return pObj->GetInteger();
926 }
CountSelectedOptions()927 int CPDF_FormField::CountSelectedOptions() {
928 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
929 if (!pObj) {
930 return 0;
931 }
932 CPDF_Array* pArray = pObj->GetArray();
933 if (!pArray) {
934 return 0;
935 }
936 return (int)pArray->GetCount();
937 }
GetSelectedOptionIndex(int index)938 int CPDF_FormField::GetSelectedOptionIndex(int index) {
939 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
940 if (!pObj) {
941 return -1;
942 }
943 CPDF_Array* pArray = pObj->GetArray();
944 if (!pArray) {
945 return -1;
946 }
947 int iCount = (int)pArray->GetCount();
948 if (iCount > 0 && index < iCount) {
949 return pArray->GetInteger(index);
950 }
951 return -1;
952 }
IsOptionSelected(int iOptIndex)953 FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex) {
954 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
955 if (!pObj) {
956 return FALSE;
957 }
958 CPDF_Array* pArray = pObj->GetArray();
959 if (!pArray) {
960 return FALSE;
961 }
962 int iCount = (int)pArray->GetCount();
963 for (int i = 0; i < iCount; i++) {
964 if (pArray->GetInteger(i) == iOptIndex) {
965 return TRUE;
966 }
967 }
968 return FALSE;
969 }
SelectOption(int iOptIndex,FX_BOOL bSelected,FX_BOOL bNotify)970 FX_BOOL CPDF_FormField::SelectOption(int iOptIndex,
971 FX_BOOL bSelected,
972 FX_BOOL bNotify) {
973 CPDF_Array* pArray = m_pDict->GetArray("I");
974 if (!pArray) {
975 if (!bSelected) {
976 return TRUE;
977 }
978 pArray = new CPDF_Array;
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) {
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) {
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 = new CPDF_Number(iOptIndex);
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) {
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 if (bNotify && m_pForm->m_pFormNotify) {
1048 int iRet = 0;
1049 CFX_WideString csValue;
1050 int iIndex = GetSelectedIndex(0);
1051 if (iIndex >= 0) {
1052 csValue = GetOptionLabel(iIndex);
1053 }
1054 if (GetType() == ListBox) {
1055 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
1056 }
1057 if (GetType() == ComboBox) {
1058 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
1059 }
1060 if (iRet < 0) {
1061 return FALSE;
1062 }
1063 }
1064 m_pDict->RemoveAt("I");
1065 if (bNotify && m_pForm->m_pFormNotify) {
1066 if (GetType() == ListBox) {
1067 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1068 }
1069 if (GetType() == ComboBox) {
1070 m_pForm->m_pFormNotify->AfterValueChange(this);
1071 }
1072 }
1073 m_pForm->m_bUpdated = TRUE;
1074 return TRUE;
1075 }
LoadDA()1076 void CPDF_FormField::LoadDA() {
1077 CFX_ByteString DA;
1078 if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
1079 DA = pObj_t->GetString();
1080 }
1081 if (DA.IsEmpty() && m_pForm->m_pFormDict) {
1082 DA = m_pForm->m_pFormDict->GetString("DA");
1083 }
1084 if (DA.IsEmpty()) {
1085 return;
1086 }
1087 CPDF_SimpleParser syntax(DA);
1088 syntax.FindTagParam("Tf", 2);
1089 CFX_ByteString font_name = syntax.GetWord();
1090 CPDF_Dictionary* pFontDict = NULL;
1091 if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDict("DR") &&
1092 m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font"))
1093 pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(
1094 font_name);
1095
1096 if (!pFontDict) {
1097 return;
1098 }
1099 m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1100 m_FontSize = FX_atof(syntax.GetWord());
1101 }
1102