blob: 6c3afad1ee12e5cc81ab31c28d5c8cfaab7a7537 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairaa403d32016-03-15 14:57:22 -04007#include "core/fpdfapi/fpdf_parser/include/cfdf_document.h"
8#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
9#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
10#include "core/fpdfapi/fpdf_parser/include/cpdf_number.h"
11#include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h"
12#include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
Dan Sinclair764ec512016-03-14 13:35:12 -040013#include "core/fpdfdoc/doc_utils.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080014#include "core/include/fpdfdoc/fpdf_doc.h"
Tom Sepezeff208f2015-05-08 13:45:01 -070015
Nico Weber9d8ec5a2015-08-04 13:00:21 -070016FX_BOOL PDF_FormField_IsUnison(CPDF_FormField* pField) {
17 FX_BOOL bUnison = FALSE;
18 if (pField->GetType() == CPDF_FormField::CheckBox) {
19 bUnison = TRUE;
20 } else {
21 FX_DWORD dwFlags = pField->GetFieldFlags();
22 bUnison = ((dwFlags & 0x2000000) != 0);
23 }
24 return bUnison;
25}
26CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict) {
27 m_pDict = pDict;
28 m_Type = Unknown;
29 m_pForm = pForm;
30 m_pFont = NULL;
31 m_FontSize = 0;
32 SyncFieldFlags();
33}
34CPDF_FormField::~CPDF_FormField() {}
35void CPDF_FormField::SyncFieldFlags() {
36 CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT")
37 ? FPDF_GetFieldAttr(m_pDict, "FT")->GetString()
38 : CFX_ByteString();
39 FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")
40 ? FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger()
41 : 0;
42 m_Flags = 0;
43 if (flags & 1) {
44 m_Flags |= FORMFIELD_READONLY;
45 }
46 if (flags & 2) {
47 m_Flags |= FORMFIELD_REQUIRED;
48 }
49 if (flags & 4) {
50 m_Flags |= FORMFIELD_NOEXPORT;
51 }
52 if (type_name == "Btn") {
53 if (flags & 0x8000) {
54 m_Type = RadioButton;
55 if (flags & 0x4000) {
56 m_Flags |= FORMRADIO_NOTOGGLEOFF;
57 }
58 if (flags & 0x2000000) {
59 m_Flags |= FORMRADIO_UNISON;
60 }
61 } else if (flags & 0x10000) {
62 m_Type = PushButton;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070063 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064 m_Type = CheckBox;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070065 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070066 } else if (type_name == "Tx") {
67 if (flags & 0x100000) {
68 m_Type = File;
69 } else if (flags & 0x2000000) {
70 m_Type = RichText;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070071 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072 m_Type = Text;
73 if (flags & 0x1000) {
74 m_Flags |= FORMTEXT_MULTILINE;
75 }
76 if (flags & 0x2000) {
77 m_Flags |= FORMTEXT_PASSWORD;
78 }
79 if (flags & 0x800000) {
80 m_Flags |= FORMTEXT_NOSCROLL;
81 }
82 if (flags & 0x100000) {
83 m_Flags |= FORMTEXT_COMB;
84 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070085 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 LoadDA();
87 } else if (type_name == "Ch") {
88 if (flags & 0x20000) {
89 m_Type = ComboBox;
90 if (flags & 0x40000) {
91 m_Flags |= FORMCOMBO_EDIT;
92 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070093 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094 m_Type = ListBox;
95 if (flags & 0x200000) {
96 m_Flags |= FORMLIST_MULTISELECT;
97 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070098 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099 LoadDA();
100 } else if (type_name == "Sig") {
101 m_Type = Sign;
102 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700103}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104CFX_WideString CPDF_FormField::GetFullName() {
105 return ::GetFullName(m_pDict);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700107FX_BOOL CPDF_FormField::ResetField(FX_BOOL bNotify) {
108 switch (m_Type) {
109 case CPDF_FormField::CheckBox:
110 case CPDF_FormField::RadioButton: {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111 int iCount = CountControls();
112 if (iCount) {
Wei Li97da9762016-03-11 17:00:48 -0800113 // TODO(weili): Check whether anything special needs to be done for
114 // unison field. Otherwise, merge these branches.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700115 if (PDF_FormField_IsUnison(this)) {
116 for (int i = 0; i < iCount; i++) {
117 CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE);
118 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700119 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700120 for (int i = 0; i < iCount; i++) {
Wei Li97da9762016-03-11 17:00:48 -0800121 CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700123 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 }
Lei Zhang96660d62015-12-14 18:27:25 -0800125 if (bNotify && m_pForm->m_pFormNotify) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800126 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700127 }
128 } break;
129 case CPDF_FormField::ComboBox: {
130 CFX_WideString csValue;
131 ClearSelection();
132 int iIndex = GetDefaultSelectedItem();
133 if (iIndex >= 0) {
134 csValue = GetOptionLabel(iIndex);
135 }
Lei Zhang96660d62015-12-14 18:27:25 -0800136 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
138 if (iRet < 0) {
139 return FALSE;
140 }
141 }
142 SetItemSelection(iIndex, TRUE);
Lei Zhang96660d62015-12-14 18:27:25 -0800143 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144 m_pForm->m_pFormNotify->AfterValueChange(this);
145 }
146 } break;
147 case CPDF_FormField::ListBox: {
148 CFX_WideString csValue;
149 ClearSelection();
150 int iIndex = GetDefaultSelectedItem();
151 if (iIndex >= 0) {
152 csValue = GetOptionLabel(iIndex);
153 }
Lei Zhang96660d62015-12-14 18:27:25 -0800154 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
156 if (iRet < 0) {
157 return FALSE;
158 }
159 }
160 SetItemSelection(iIndex, TRUE);
Lei Zhang96660d62015-12-14 18:27:25 -0800161 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 m_pForm->m_pFormNotify->AfterSelectionChange(this);
163 }
164 } break;
165 case CPDF_FormField::Text:
166 case CPDF_FormField::RichText:
167 case CPDF_FormField::File:
168 default: {
169 CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV");
170 CFX_WideString csDValue;
Lei Zhang96660d62015-12-14 18:27:25 -0800171 if (pDV) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 csDValue = pDV->GetUnicodeText();
173 }
174 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
175 CFX_WideString csValue;
Lei Zhang96660d62015-12-14 18:27:25 -0800176 if (pV) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 csValue = pV->GetUnicodeText();
178 }
179 CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV");
180 if (!pRV && (csDValue == csValue)) {
181 return FALSE;
182 }
Lei Zhang96660d62015-12-14 18:27:25 -0800183 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700184 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csDValue);
185 if (iRet < 0) {
186 return FALSE;
187 }
188 }
Lei Zhang412e9082015-12-14 18:34:00 -0800189 if (pDV) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700190 CPDF_Object* pClone = pDV->Clone();
Lei Zhang412e9082015-12-14 18:34:00 -0800191 if (!pClone) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700192 return FALSE;
193 }
194 m_pDict->SetAt("V", pClone);
195 if (pRV) {
196 CPDF_Object* pCloneR = pDV->Clone();
197 m_pDict->SetAt("RV", pCloneR);
198 }
Lei Zhang412e9082015-12-14 18:34:00 -0800199 } else {
200 m_pDict->RemoveAt("V");
201 m_pDict->RemoveAt("RV");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202 }
Lei Zhang96660d62015-12-14 18:27:25 -0800203 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700204 m_pForm->m_pFormNotify->AfterValueChange(this);
205 }
206 m_pForm->m_bUpdated = TRUE;
207 } break;
208 }
209 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700211int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl) {
Tom Sepezbd573f12015-12-09 16:39:40 -0800212 if (!pControl) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700213 return -1;
214 }
Tom Sepezbd573f12015-12-09 16:39:40 -0800215 for (int i = 0; i < m_ControlList.GetSize(); i++) {
216 if (m_ControlList.GetAt(i) == pControl)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700218 }
219 return -1;
220}
221int CPDF_FormField::GetFieldType() {
222 switch (m_Type) {
223 case PushButton:
224 return FIELDTYPE_PUSHBUTTON;
225 case CheckBox:
226 return FIELDTYPE_CHECKBOX;
227 case RadioButton:
228 return FIELDTYPE_RADIOBUTTON;
229 case ComboBox:
230 return FIELDTYPE_COMBOBOX;
231 case ListBox:
232 return FIELDTYPE_LISTBOX;
233 case Text:
234 case RichText:
235 case File:
236 return FIELDTYPE_TEXTFIELD;
237 case Sign:
238 return FIELDTYPE_SIGNATURE;
239 default:
240 break;
241 }
242 return FIELDTYPE_UNKNOWN;
243}
Wei Li0fc6b252016-03-01 16:29:41 -0800244
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245CPDF_AAction CPDF_FormField::GetAdditionalAction() {
246 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA");
Wei Li0fc6b252016-03-01 16:29:41 -0800247 return CPDF_AAction(pObj ? pObj->GetDict() : nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248}
Wei Li0fc6b252016-03-01 16:29:41 -0800249
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700250CFX_WideString CPDF_FormField::GetAlternateName() {
251 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU");
Lei Zhang412e9082015-12-14 18:34:00 -0800252 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700253 return L"";
254 }
255 return pObj->GetUnicodeText();
256}
257CFX_WideString CPDF_FormField::GetMappingName() {
258 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM");
Lei Zhang412e9082015-12-14 18:34:00 -0800259 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700260 return L"";
261 }
262 return pObj->GetUnicodeText();
263}
264FX_DWORD CPDF_FormField::GetFieldFlags() {
265 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff");
Lei Zhang412e9082015-12-14 18:34:00 -0800266 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700267 return 0;
268 }
269 return pObj->GetInteger();
270}
271CFX_ByteString CPDF_FormField::GetDefaultStyle() {
272 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS");
Lei Zhang412e9082015-12-14 18:34:00 -0800273 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700274 return "";
275 }
276 return pObj->GetString();
277}
278CFX_WideString CPDF_FormField::GetRichTextString() {
279 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV");
Lei Zhang412e9082015-12-14 18:34:00 -0800280 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700281 return L"";
282 }
283 return pObj->GetUnicodeText();
284}
285CFX_WideString CPDF_FormField::GetValue(FX_BOOL bDefault) {
286 if (GetType() == CheckBox || GetType() == RadioButton) {
287 return GetCheckValue(bDefault);
288 }
289 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V");
Lei Zhang412e9082015-12-14 18:34:00 -0800290 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700291 if (!bDefault) {
292 if (m_Type == RichText) {
293 pValue = FPDF_GetFieldAttr(m_pDict, "V");
294 }
Lei Zhang412e9082015-12-14 18:34:00 -0800295 if (!pValue && m_Type != Text) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700296 pValue = FPDF_GetFieldAttr(m_pDict, "DV");
297 }
298 }
Lei Zhang412e9082015-12-14 18:34:00 -0800299 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 return CFX_WideString();
301 }
302 }
303 switch (pValue->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800304 case CPDF_Object::STRING:
305 case CPDF_Object::STREAM:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306 return pValue->GetUnicodeText();
Tom Sepez8e5cd192016-01-26 13:20:26 -0800307 case CPDF_Object::ARRAY:
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400308 pValue = pValue->AsArray()->GetElementValue(0);
309 if (pValue)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310 return pValue->GetUnicodeText();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700311 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800312 default:
313 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700314 }
315 return CFX_WideString();
316}
317CFX_WideString CPDF_FormField::GetValue() {
318 return GetValue(FALSE);
319}
320CFX_WideString CPDF_FormField::GetDefaultValue() {
321 return GetValue(TRUE);
322}
323FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value,
324 FX_BOOL bDefault,
325 FX_BOOL bNotify) {
326 switch (m_Type) {
327 case CheckBox:
328 case RadioButton: {
329 SetCheckValue(value, bDefault, bNotify);
330 return TRUE;
331 }
332 case File:
333 case RichText:
334 case Text:
335 case ComboBox: {
336 CFX_WideString csValue = value;
Lei Zhang96660d62015-12-14 18:27:25 -0800337 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700338 int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
339 if (iRet < 0) {
340 return FALSE;
341 }
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 }
350 m_pDict->RemoveAt("I");
351 } else {
352 m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700353 if (bDefault) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700354 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700355 ClearSelection();
356 SetItemSelection(iIndex, TRUE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700357 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700358 }
Lei Zhang96660d62015-12-14 18:27:25 -0800359 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 m_pForm->m_pFormNotify->AfterValueChange(this);
361 }
362 m_pForm->m_bUpdated = TRUE;
363 } break;
364 case ListBox: {
365 int iIndex = FindOptionValue(value);
366 if (iIndex < 0) {
367 return FALSE;
368 }
369 if (bDefault && iIndex == GetDefaultSelectedItem()) {
370 return FALSE;
371 }
Lei Zhang96660d62015-12-14 18:27:25 -0800372 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700373 CFX_WideString csValue = value;
374 int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
375 if (iRet < 0) {
376 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700377 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700378 }
379 if (bDefault) {
380 } else {
381 ClearSelection();
382 SetItemSelection(iIndex, TRUE);
383 }
Lei Zhang96660d62015-12-14 18:27:25 -0800384 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700385 m_pForm->m_pFormNotify->AfterSelectionChange(this);
386 }
387 m_pForm->m_bUpdated = TRUE;
388 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700389 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700390 default:
391 break;
392 }
393 if (CPDF_InterForm::m_bUpdateAP) {
394 UpdateAP(NULL);
395 }
396 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700397}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700398FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify) {
399 return SetValue(value, FALSE, bNotify);
400}
401int CPDF_FormField::GetMaxLen() {
Tom Sepezbd573f12015-12-09 16:39:40 -0800402 if (CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen"))
403 return pObj->GetInteger();
404
405 for (int i = 0; i < m_ControlList.GetSize(); i++) {
406 CPDF_FormControl* pControl = m_ControlList.GetAt(i);
407 if (!pControl)
408 continue;
409
410 CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict;
411 if (pWidgetDict->KeyExist("MaxLen"))
Wei Li9b761132016-01-29 15:44:20 -0800412 return pWidgetDict->GetIntegerBy("MaxLen");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700413 }
Tom Sepezbd573f12015-12-09 16:39:40 -0800414 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700415}
416int CPDF_FormField::CountSelectedItems() {
417 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400418 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700419 pValue = FPDF_GetFieldAttr(m_pDict, "I");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400420 if (!pValue)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700422 }
Dan Sinclair316eb862015-10-21 13:29:23 -0400423
424 if (pValue->IsString() || pValue->IsNumber())
425 return pValue->GetString().IsEmpty() ? 0 : 1;
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400426 if (CPDF_Array* pArray = pValue->AsArray())
427 return pArray->GetCount();
428 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429}
430int CPDF_FormField::GetSelectedIndex(int index) {
431 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400432 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700433 pValue = FPDF_GetFieldAttr(m_pDict, "I");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400434 if (!pValue)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700435 return -1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 }
Dan Sinclair43ce9032015-10-21 11:07:42 -0400437 if (pValue->IsNumber())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700438 return pValue->GetInteger();
Dan Sinclair43ce9032015-10-21 11:07:42 -0400439
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 CFX_WideString sel_value;
Dan Sinclair316eb862015-10-21 13:29:23 -0400441 if (pValue->IsString()) {
442 if (index != 0)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700443 return -1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444 sel_value = pValue->GetUnicodeText();
445 } else {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400446 CPDF_Array* pArray = pValue->AsArray();
447 if (!pArray || index < 0)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 return -1;
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400449
450 CPDF_Object* elementValue = pArray->GetElementValue(index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451 sel_value =
452 elementValue ? elementValue->GetUnicodeText() : CFX_WideString();
453 }
454 if (index < CountSelectedOptions()) {
455 int iOptIndex = GetSelectedOptionIndex(index);
456 CFX_WideString csOpt = GetOptionValue(iOptIndex);
457 if (csOpt == sel_value) {
458 return iOptIndex;
459 }
460 }
461 int nOpts = CountOptions();
462 for (int i = 0; i < nOpts; i++) {
463 if (sel_value == GetOptionValue(i)) {
464 return i;
465 }
466 }
467 return -1;
468}
469FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify) {
Lei Zhang96660d62015-12-14 18:27:25 -0800470 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700471 int iRet = 0;
472 CFX_WideString csValue;
473 int iIndex = GetSelectedIndex(0);
474 if (iIndex >= 0) {
475 csValue = GetOptionLabel(iIndex);
476 }
477 if (GetType() == ListBox) {
478 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
479 }
480 if (GetType() == ComboBox) {
481 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
482 }
483 if (iRet < 0) {
484 return FALSE;
485 }
486 }
487 m_pDict->RemoveAt("V");
488 m_pDict->RemoveAt("I");
Lei Zhang96660d62015-12-14 18:27:25 -0800489 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 if (GetType() == ListBox) {
491 m_pForm->m_pFormNotify->AfterSelectionChange(this);
492 }
493 if (GetType() == ComboBox) {
494 m_pForm->m_pFormNotify->AfterValueChange(this);
495 }
496 }
497 if (CPDF_InterForm::m_bUpdateAP) {
498 UpdateAP(NULL);
499 }
500 m_pForm->m_bUpdated = TRUE;
501 return TRUE;
502}
503FX_BOOL CPDF_FormField::IsItemSelected(int index) {
504 ASSERT(GetType() == ComboBox || GetType() == ListBox);
505 if (index < 0 || index >= CountOptions()) {
506 return FALSE;
507 }
508 if (IsOptionSelected(index)) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700509 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700510 }
511 CFX_WideString opt_value = GetOptionValue(index);
512 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
Lei Zhang412e9082015-12-14 18:34:00 -0800513 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 pValue = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800515 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700516 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700517 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700518 }
Dan Sinclair316eb862015-10-21 13:29:23 -0400519
520 if (pValue->IsString())
Dan Sinclair710c9092015-10-21 15:46:10 -0400521 return pValue->GetUnicodeText() == opt_value;
Dan Sinclair316eb862015-10-21 13:29:23 -0400522
Dan Sinclair43ce9032015-10-21 11:07:42 -0400523 if (pValue->IsNumber()) {
Dan Sinclair316eb862015-10-21 13:29:23 -0400524 if (pValue->GetString().IsEmpty())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525 return FALSE;
Dan Sinclair316eb862015-10-21 13:29:23 -0400526 return (pValue->GetInteger() == index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 }
Dan Sinclair316eb862015-10-21 13:29:23 -0400528
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400529 CPDF_Array* pArray = pValue->AsArray();
530 if (!pArray)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 return FALSE;
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400532
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700533 int iPos = -1;
534 for (int j = 0; j < CountSelectedOptions(); j++) {
535 if (GetSelectedOptionIndex(j) == index) {
536 iPos = j;
537 break;
538 }
539 }
540 for (FX_DWORD i = 0; i < pArray->GetCount(); i++)
541 if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value &&
542 (int)i == iPos) {
543 return TRUE;
544 }
545 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700546}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700547FX_BOOL CPDF_FormField::SetItemSelection(int index,
548 FX_BOOL bSelected,
549 FX_BOOL bNotify) {
550 ASSERT(GetType() == ComboBox || GetType() == ListBox);
551 if (index < 0 || index >= CountOptions()) {
552 return FALSE;
553 }
554 CFX_WideString opt_value = GetOptionValue(index);
Lei Zhang96660d62015-12-14 18:27:25 -0800555 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700556 int iRet = 0;
557 if (GetType() == ListBox) {
558 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
559 }
560 if (GetType() == ComboBox) {
561 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
562 }
563 if (iRet < 0) {
564 return FALSE;
565 }
566 }
567 if (!bSelected) {
568 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
Lei Zhang96660d62015-12-14 18:27:25 -0800569 if (pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700570 if (m_Type == ListBox) {
571 SelectOption(index, FALSE);
Dan Sinclair316eb862015-10-21 13:29:23 -0400572 if (pValue->IsString()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573 if (pValue->GetUnicodeText() == opt_value) {
574 m_pDict->RemoveAt("V");
575 }
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400576 } else if (pValue->IsArray()) {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800577 CPDF_Array* pArray = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 int iCount = CountOptions();
579 for (int i = 0; i < iCount; i++) {
580 if (i != index) {
581 if (IsItemSelected(i)) {
582 opt_value = GetOptionValue(i);
583 pArray->AddString(PDF_EncodeText(opt_value));
584 }
585 }
586 }
587 if (pArray->GetCount() < 1) {
588 pArray->Release();
589 } else {
590 m_pDict->SetAt("V", pArray);
591 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700592 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700593 } else if (m_Type == ComboBox) {
594 m_pDict->RemoveAt("V");
595 m_pDict->RemoveAt("I");
596 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700597 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700598 } else {
599 if (m_Type == ListBox) {
600 SelectOption(index, TRUE);
601 if (!(m_Flags & FORMLIST_MULTISELECT)) {
602 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
603 } else {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800604 CPDF_Array* pArray = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700605 int iCount = CountOptions();
606 for (int i = 0; i < iCount; i++) {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800607 FX_BOOL bSelected;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700608 if (i != index) {
609 bSelected = IsItemSelected(i);
610 } else {
611 bSelected = TRUE;
612 }
613 if (bSelected) {
614 opt_value = GetOptionValue(i);
615 pArray->AddString(PDF_EncodeText(opt_value));
616 }
617 }
618 m_pDict->SetAt("V", pArray);
619 }
620 } else if (m_Type == ComboBox) {
621 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
Lei Zhang4880d1a2015-12-18 17:05:11 -0800622 CPDF_Array* pI = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700623 pI->AddInteger(index);
624 m_pDict->SetAt("I", pI);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700625 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700626 }
Lei Zhang96660d62015-12-14 18:27:25 -0800627 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700628 if (GetType() == ListBox) {
629 m_pForm->m_pFormNotify->AfterSelectionChange(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700630 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700631 if (GetType() == ComboBox) {
632 m_pForm->m_pFormNotify->AfterValueChange(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700633 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700634 }
635 if (CPDF_InterForm::m_bUpdateAP) {
636 UpdateAP(NULL);
637 }
638 m_pForm->m_bUpdated = TRUE;
639 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700640}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700641FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index) {
642 ASSERT(GetType() == ComboBox || GetType() == ListBox);
643 if (index < 0 || index >= CountOptions()) {
644 return FALSE;
645 }
646 int iDVIndex = GetDefaultSelectedItem();
647 if (iDVIndex < 0) {
648 return FALSE;
649 }
650 return (iDVIndex == index);
651}
652int CPDF_FormField::GetDefaultSelectedItem() {
653 ASSERT(GetType() == ComboBox || GetType() == ListBox);
654 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
Lei Zhang412e9082015-12-14 18:34:00 -0800655 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700656 return -1;
657 }
658 CFX_WideString csDV = pValue->GetUnicodeText();
659 if (csDV.IsEmpty()) {
660 return -1;
661 }
662 int iCount = CountOptions();
663 for (int i = 0; i < iCount; i++) {
664 if (csDV == GetOptionValue(i)) {
665 return i;
666 }
667 }
668 return -1;
669}
670void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl) {
671 if (m_Type == PushButton) {
672 return;
673 }
674 if (m_Type == RadioButton || m_Type == CheckBox) {
675 return;
676 }
677 if (!m_pForm->m_bGenerateAP) {
678 return;
679 }
680 for (int i = 0; i < CountControls(); i++) {
681 CPDF_FormControl* pControl = GetControl(i);
682 FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
683 }
684}
685int CPDF_FormField::CountOptions() {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400686 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
687 return pArray ? pArray->GetCount() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688}
689CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index) {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400690 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
691 if (!pArray)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700692 return CFX_WideString();
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400693
694 CPDF_Object* pOption = pArray->GetElementValue(index);
695 if (!pOption)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700696 return CFX_WideString();
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400697 if (CPDF_Array* pOptionArray = pOption->AsArray())
698 pOption = pOptionArray->GetElementValue(sub_index);
Dan Sinclair316eb862015-10-21 13:29:23 -0400699
700 CPDF_String* pString = ToString(pOption);
701 return pString ? pString->GetUnicodeText() : CFX_WideString();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700702}
703CFX_WideString CPDF_FormField::GetOptionLabel(int index) {
704 return GetOptionText(index, 1);
705}
706CFX_WideString CPDF_FormField::GetOptionValue(int index) {
707 return GetOptionText(index, 0);
708}
709int CPDF_FormField::FindOption(CFX_WideString csOptLabel) {
710 int iCount = CountOptions();
711 for (int i = 0; i < iCount; i++) {
712 CFX_WideString csValue = GetOptionValue(i);
713 if (csValue == csOptLabel) {
714 return i;
715 }
716 }
717 return -1;
718}
719int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue,
720 int iStartIndex) {
721 if (iStartIndex < 0) {
722 iStartIndex = 0;
723 }
724 int iCount = CountOptions();
725 for (; iStartIndex < iCount; iStartIndex++) {
726 CFX_WideString csValue = GetOptionValue(iStartIndex);
727 if (csValue == csOptValue) {
728 return iStartIndex;
729 }
730 }
731 return -1;
732}
Tom Sepez5c4c1932015-11-25 12:15:38 -0800733#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700734int CPDF_FormField::InsertOption(CFX_WideString csOptLabel,
735 int index,
736 FX_BOOL bNotify) {
737 if (csOptLabel.IsEmpty())
738 return -1;
739
Lei Zhang4880d1a2015-12-18 17:05:11 -0800740 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700741 int iRet = 0;
742 if (GetType() == ListBox)
743 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csOptLabel);
744 if (GetType() == ComboBox)
745 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csOptLabel);
746 if (iRet < 0)
747 return -1;
748 }
749
750 CFX_ByteString csStr = PDF_EncodeText(csOptLabel, csOptLabel.GetLength());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700751 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
Lei Zhang4880d1a2015-12-18 17:05:11 -0800752 CPDF_Array* pOpt = ToArray(pValue);
753 if (!pOpt) {
754 pOpt = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700755 m_pDict->SetAt("Opt", pOpt);
Lei Zhang4880d1a2015-12-18 17:05:11 -0800756 }
757
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700758 int iCount = (int)pOpt->GetCount();
759 if (index < 0 || index >= iCount) {
760 pOpt->AddString(csStr);
761 index = iCount;
762 } else {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800763 CPDF_String* pString = new CPDF_String(csStr, FALSE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700764 pOpt->InsertAt(index, pString);
765 }
766
Lei Zhang4880d1a2015-12-18 17:05:11 -0800767 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700768 if (GetType() == ListBox)
769 m_pForm->m_pFormNotify->AfterSelectionChange(this);
770 if (GetType() == ComboBox)
771 m_pForm->m_pFormNotify->AfterValueChange(this);
772 }
773 m_pForm->m_bUpdated = TRUE;
774 return index;
775}
776FX_BOOL CPDF_FormField::ClearOptions(FX_BOOL bNotify) {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800777 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700778 int iRet = 0;
779 CFX_WideString csValue;
780 int iIndex = GetSelectedIndex(0);
781 if (iIndex >= 0)
782 csValue = GetOptionLabel(iIndex);
783 if (GetType() == ListBox)
784 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
785 if (GetType() == ComboBox)
786 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
787 if (iRet < 0)
788 return FALSE;
789 }
790
791 m_pDict->RemoveAt("Opt");
792 m_pDict->RemoveAt("V");
793 m_pDict->RemoveAt("DV");
794 m_pDict->RemoveAt("I");
795 m_pDict->RemoveAt("TI");
796
Lei Zhang4880d1a2015-12-18 17:05:11 -0800797 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700798 if (GetType() == ListBox)
799 m_pForm->m_pFormNotify->AfterSelectionChange(this);
800 if (GetType() == ComboBox)
801 m_pForm->m_pFormNotify->AfterValueChange(this);
802 }
803
804 m_pForm->m_bUpdated = TRUE;
805 return TRUE;
806}
Tom Sepeza2c42ce2015-11-25 15:52:28 -0800807#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700808FX_BOOL CPDF_FormField::CheckControl(int iControlIndex,
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800809 bool bChecked,
810 bool bNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700811 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
812 CPDF_FormControl* pControl = GetControl(iControlIndex);
Lei Zhang412e9082015-12-14 18:34:00 -0800813 if (!pControl) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700814 return FALSE;
815 }
816 if (!bChecked && pControl->IsChecked() == bChecked) {
817 return FALSE;
818 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700819 CFX_WideString csWExport = pControl->GetExportValue();
820 CFX_ByteString csBExport = PDF_EncodeText(csWExport);
821 int iCount = CountControls();
822 FX_BOOL bUnison = PDF_FormField_IsUnison(this);
823 for (int i = 0; i < iCount; i++) {
824 CPDF_FormControl* pCtrl = GetControl(i);
825 if (bUnison) {
826 CFX_WideString csEValue = pCtrl->GetExportValue();
827 if (csEValue == csWExport) {
828 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
829 pCtrl->CheckControl(bChecked);
830 } else if (bChecked) {
831 pCtrl->CheckControl(FALSE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700832 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700833 } else if (bChecked) {
834 pCtrl->CheckControl(FALSE);
835 }
836 } else {
837 if (i == iControlIndex) {
838 pCtrl->CheckControl(bChecked);
839 } else if (bChecked) {
840 pCtrl->CheckControl(FALSE);
841 }
842 }
843 }
844 CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400845 if (!ToArray(pOpt)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700846 if (bChecked) {
847 m_pDict->SetAtName("V", csBExport);
848 } else {
849 CFX_ByteString csV;
850 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
Lei Zhang96660d62015-12-14 18:27:25 -0800851 if (pV) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700852 csV = pV->GetString();
853 }
854 if (csV == csBExport) {
855 m_pDict->SetAtName("V", "Off");
856 }
857 }
858 } else if (bChecked) {
859 CFX_ByteString csIndex;
860 csIndex.Format("%d", iControlIndex);
861 m_pDict->SetAtName("V", csIndex);
862 }
Lei Zhang96660d62015-12-14 18:27:25 -0800863 if (bNotify && m_pForm->m_pFormNotify) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800864 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700865 }
866 m_pForm->m_bUpdated = TRUE;
867 return TRUE;
868}
869CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault) {
870 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
871 CFX_WideString csExport = L"Off";
872 FX_BOOL bChecked;
873 int iCount = CountControls();
874 for (int i = 0; i < iCount; i++) {
875 CPDF_FormControl* pControl = GetControl(i);
876 if (bDefault) {
877 bChecked = pControl->IsDefaultChecked();
878 } else {
879 bChecked = pControl->IsChecked();
880 }
881 if (bChecked) {
882 csExport = pControl->GetExportValue();
883 break;
884 }
885 }
886 return csExport;
887}
888FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value,
889 FX_BOOL bDefault,
890 FX_BOOL bNotify) {
891 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700892 int iCount = CountControls();
893 for (int i = 0; i < iCount; i++) {
894 CPDF_FormControl* pControl = GetControl(i);
895 CFX_WideString csExport = pControl->GetExportValue();
896 if (csExport == value) {
897 if (bDefault) {
898 } else {
899 CheckControl(GetControlIndex(pControl), TRUE);
900 }
901 break;
902 } else {
903 if (bDefault) {
904 } else {
905 CheckControl(GetControlIndex(pControl), FALSE);
906 }
907 }
908 }
Lei Zhang96660d62015-12-14 18:27:25 -0800909 if (bNotify && m_pForm->m_pFormNotify) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800910 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700911 }
912 m_pForm->m_bUpdated = TRUE;
913 return TRUE;
914}
915int CPDF_FormField::GetTopVisibleIndex() {
916 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
Lei Zhang412e9082015-12-14 18:34:00 -0800917 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700918 return 0;
919 }
920 return pObj->GetInteger();
921}
922int CPDF_FormField::CountSelectedOptions() {
923 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800924 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700925 return 0;
926 }
927 CPDF_Array* pArray = pObj->GetArray();
Lei Zhang412e9082015-12-14 18:34:00 -0800928 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700929 return 0;
930 }
931 return (int)pArray->GetCount();
932}
933int CPDF_FormField::GetSelectedOptionIndex(int index) {
934 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800935 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700936 return -1;
937 }
938 CPDF_Array* pArray = pObj->GetArray();
Lei Zhang412e9082015-12-14 18:34:00 -0800939 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700940 return -1;
941 }
942 int iCount = (int)pArray->GetCount();
943 if (iCount > 0 && index < iCount) {
Wei Li9b761132016-01-29 15:44:20 -0800944 return pArray->GetIntegerAt(index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700945 }
946 return -1;
947}
948FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex) {
949 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800950 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700951 return FALSE;
952 }
953 CPDF_Array* pArray = pObj->GetArray();
Lei Zhang412e9082015-12-14 18:34:00 -0800954 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700955 return FALSE;
956 }
957 int iCount = (int)pArray->GetCount();
958 for (int i = 0; i < iCount; i++) {
Wei Li9b761132016-01-29 15:44:20 -0800959 if (pArray->GetIntegerAt(i) == iOptIndex) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700960 return TRUE;
961 }
962 }
963 return FALSE;
964}
965FX_BOOL CPDF_FormField::SelectOption(int iOptIndex,
966 FX_BOOL bSelected,
967 FX_BOOL bNotify) {
Wei Li9b761132016-01-29 15:44:20 -0800968 CPDF_Array* pArray = m_pDict->GetArrayBy("I");
Lei Zhang412e9082015-12-14 18:34:00 -0800969 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700970 if (!bSelected) {
971 return TRUE;
972 }
Lei Zhang4880d1a2015-12-18 17:05:11 -0800973 pArray = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700974 m_pDict->SetAt("I", pArray);
975 }
976 FX_BOOL bReturn = FALSE;
977 for (int i = 0; i < (int)pArray->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -0800978 int iFind = pArray->GetIntegerAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700979 if (iFind == iOptIndex) {
980 if (bSelected) {
981 return TRUE;
982 }
Lei Zhang96660d62015-12-14 18:27:25 -0800983 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700984 int iRet = 0;
985 CFX_WideString csValue = GetOptionLabel(iOptIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700986 if (GetType() == ListBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700987 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700988 }
989 if (GetType() == ComboBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700990 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700991 }
992 if (iRet < 0) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700993 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700994 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700995 }
996 pArray->RemoveAt(i);
997 bReturn = TRUE;
998 break;
999 } else if (iFind > iOptIndex) {
1000 if (!bSelected) {
1001 continue;
1002 }
Lei Zhang96660d62015-12-14 18:27:25 -08001003 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001004 int iRet = 0;
1005 CFX_WideString csValue = GetOptionLabel(iOptIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001006 if (GetType() == ListBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001007 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001008 }
1009 if (GetType() == ComboBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001010 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001011 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001012 if (iRet < 0) {
1013 return FALSE;
1014 }
1015 }
Lei Zhang4880d1a2015-12-18 17:05:11 -08001016 CPDF_Number* pNum = new CPDF_Number(iOptIndex);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001017 pArray->InsertAt(i, pNum);
1018 bReturn = TRUE;
1019 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001020 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001021 }
1022 if (!bReturn) {
1023 if (bSelected) {
1024 pArray->AddInteger(iOptIndex);
1025 }
1026 if (pArray->GetCount() == 0) {
1027 m_pDict->RemoveAt("I");
1028 }
1029 }
Lei Zhang96660d62015-12-14 18:27:25 -08001030 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001031 if (GetType() == ListBox) {
1032 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1033 }
1034 if (GetType() == ComboBox) {
1035 m_pForm->m_pFormNotify->AfterValueChange(this);
1036 }
1037 }
1038 m_pForm->m_bUpdated = TRUE;
1039 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001040}
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001041FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify) {
Lei Zhang96660d62015-12-14 18:27:25 -08001042 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001043 int iRet = 0;
1044 CFX_WideString csValue;
1045 int iIndex = GetSelectedIndex(0);
1046 if (iIndex >= 0) {
1047 csValue = GetOptionLabel(iIndex);
Bo Xu22b31e02014-07-21 10:02:07 -07001048 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001049 if (GetType() == ListBox) {
1050 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001051 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001052 if (GetType() == ComboBox) {
1053 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001054 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001055 if (iRet < 0) {
1056 return FALSE;
1057 }
1058 }
1059 m_pDict->RemoveAt("I");
Lei Zhang96660d62015-12-14 18:27:25 -08001060 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001061 if (GetType() == ListBox) {
1062 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1063 }
1064 if (GetType() == ComboBox) {
1065 m_pForm->m_pFormNotify->AfterValueChange(this);
1066 }
1067 }
1068 m_pForm->m_bUpdated = TRUE;
1069 return TRUE;
1070}
1071void CPDF_FormField::LoadDA() {
1072 CFX_ByteString DA;
1073 if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
1074 DA = pObj_t->GetString();
1075 }
1076 if (DA.IsEmpty() && m_pForm->m_pFormDict) {
Wei Li9b761132016-01-29 15:44:20 -08001077 DA = m_pForm->m_pFormDict->GetStringBy("DA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001078 }
1079 if (DA.IsEmpty()) {
1080 return;
1081 }
1082 CPDF_SimpleParser syntax(DA);
Wei Li970c11e2016-02-16 14:26:22 -08001083 syntax.FindTagParamFromStart("Tf", 2);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001084 CFX_ByteString font_name = syntax.GetWord();
1085 CPDF_Dictionary* pFontDict = NULL;
Wei Li9b761132016-01-29 15:44:20 -08001086 if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDictBy("DR") &&
1087 m_pForm->m_pFormDict->GetDictBy("DR")->GetDictBy("Font"))
1088 pFontDict = m_pForm->m_pFormDict->GetDictBy("DR")
1089 ->GetDictBy("Font")
1090 ->GetDictBy(font_name);
Bo Xu287e11a2014-06-30 09:49:21 -07001091
Lei Zhang412e9082015-12-14 18:34:00 -08001092 if (!pFontDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001093 return;
1094 }
1095 m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1096 m_FontSize = FX_atof(syntax.GetWord());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001097}