Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(653)

Side by Side Diff: core/fpdfdoc/doc_formfield.cpp

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

Powered by Google App Engine
This is Rietveld 408576698