blob: 4ebf2d3020b1bd410e66d57619e2fb82ce3573b9 [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 {
tsepezb5e8f142016-03-25 15:18:35 -070021 uint32_t dwFlags = pField->GetFieldFlags();
Nico Weber9d8ec5a2015-08-04 13:00:21 -070022 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();
tsepezb5e8f142016-03-25 15:18:35 -070039 uint32_t flags = FPDF_GetFieldAttr(m_pDict, "Ff")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040 ? 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}
tsepezb5e8f142016-03-25 15:18:35 -0700264uint32_t CPDF_FormField::GetFieldFlags() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700265 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:
tsepezbd567552016-03-29 14:51:50 -0700308 pValue = pValue->AsArray()->GetDirectObjectAt(0);
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400309 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
tsepezbd567552016-03-29 14:51:50 -0700450 CPDF_Object* elementValue = pArray->GetDirectObjectAt(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 }
Wei Li05d53f02016-03-29 16:42:53 -0700461 for (int i = 0; i < CountOptions(); i++) {
462 if (sel_value == GetOptionValue(i))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700463 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464 }
465 return -1;
466}
467FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify) {
Lei Zhang96660d62015-12-14 18:27:25 -0800468 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469 int iRet = 0;
470 CFX_WideString csValue;
471 int iIndex = GetSelectedIndex(0);
472 if (iIndex >= 0) {
473 csValue = GetOptionLabel(iIndex);
474 }
475 if (GetType() == ListBox) {
476 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
477 }
478 if (GetType() == ComboBox) {
479 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
480 }
481 if (iRet < 0) {
482 return FALSE;
483 }
484 }
485 m_pDict->RemoveAt("V");
486 m_pDict->RemoveAt("I");
Lei Zhang96660d62015-12-14 18:27:25 -0800487 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488 if (GetType() == ListBox) {
489 m_pForm->m_pFormNotify->AfterSelectionChange(this);
490 }
491 if (GetType() == ComboBox) {
492 m_pForm->m_pFormNotify->AfterValueChange(this);
493 }
494 }
495 if (CPDF_InterForm::m_bUpdateAP) {
496 UpdateAP(NULL);
497 }
498 m_pForm->m_bUpdated = TRUE;
499 return TRUE;
500}
Wei Li05d53f02016-03-29 16:42:53 -0700501
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700502FX_BOOL CPDF_FormField::IsItemSelected(int index) {
503 ASSERT(GetType() == ComboBox || GetType() == ListBox);
504 if (index < 0 || index >= CountOptions()) {
505 return FALSE;
506 }
507 if (IsOptionSelected(index)) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700508 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509 }
510 CFX_WideString opt_value = GetOptionValue(index);
511 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
Lei Zhang412e9082015-12-14 18:34:00 -0800512 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513 pValue = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800514 if (!pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700516 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 }
Dan Sinclair316eb862015-10-21 13:29:23 -0400518
519 if (pValue->IsString())
Dan Sinclair710c9092015-10-21 15:46:10 -0400520 return pValue->GetUnicodeText() == opt_value;
Dan Sinclair316eb862015-10-21 13:29:23 -0400521
Dan Sinclair43ce9032015-10-21 11:07:42 -0400522 if (pValue->IsNumber()) {
Dan Sinclair316eb862015-10-21 13:29:23 -0400523 if (pValue->GetString().IsEmpty())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700524 return FALSE;
Dan Sinclair316eb862015-10-21 13:29:23 -0400525 return (pValue->GetInteger() == index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700526 }
Dan Sinclair316eb862015-10-21 13:29:23 -0400527
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400528 CPDF_Array* pArray = pValue->AsArray();
529 if (!pArray)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700530 return FALSE;
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400531
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700532 int iPos = -1;
533 for (int j = 0; j < CountSelectedOptions(); j++) {
534 if (GetSelectedOptionIndex(j) == index) {
535 iPos = j;
536 break;
537 }
538 }
tsepezb5e8f142016-03-25 15:18:35 -0700539 for (uint32_t i = 0; i < pArray->GetCount(); i++)
tsepezbd567552016-03-29 14:51:50 -0700540 if (pArray->GetDirectObjectAt(i)->GetUnicodeText() == opt_value &&
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700541 (int)i == iPos) {
542 return TRUE;
543 }
544 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700545}
Wei Li05d53f02016-03-29 16:42:53 -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;
Wei Li05d53f02016-03-29 16:42:53 -0700578 for (int i = 0; i < CountOptions(); i++) {
579 if (i != index && IsItemSelected(i)) {
580 opt_value = GetOptionValue(i);
581 pArray->AddString(PDF_EncodeText(opt_value));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700582 }
583 }
Wei Li05d53f02016-03-29 16:42:53 -0700584 if (pArray->GetCount() < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700585 pArray->Release();
Wei Li05d53f02016-03-29 16:42:53 -0700586 else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700587 m_pDict->SetAt("V", pArray);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700588 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700589 } else if (m_Type == ComboBox) {
590 m_pDict->RemoveAt("V");
591 m_pDict->RemoveAt("I");
592 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700593 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700594 } else {
595 if (m_Type == ListBox) {
596 SelectOption(index, TRUE);
597 if (!(m_Flags & FORMLIST_MULTISELECT)) {
598 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
599 } else {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800600 CPDF_Array* pArray = new CPDF_Array;
Wei Li05d53f02016-03-29 16:42:53 -0700601 for (int i = 0; i < CountOptions(); i++) {
602 if (i == index || IsItemSelected(i)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700603 opt_value = GetOptionValue(i);
604 pArray->AddString(PDF_EncodeText(opt_value));
605 }
606 }
607 m_pDict->SetAt("V", pArray);
608 }
609 } else if (m_Type == ComboBox) {
610 m_pDict->SetAtString("V", PDF_EncodeText(opt_value));
Lei Zhang4880d1a2015-12-18 17:05:11 -0800611 CPDF_Array* pI = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 pI->AddInteger(index);
613 m_pDict->SetAt("I", pI);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700614 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700615 }
Lei Zhang96660d62015-12-14 18:27:25 -0800616 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700617 if (GetType() == ListBox) {
618 m_pForm->m_pFormNotify->AfterSelectionChange(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700619 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700620 if (GetType() == ComboBox) {
621 m_pForm->m_pFormNotify->AfterValueChange(this);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700622 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700623 }
624 if (CPDF_InterForm::m_bUpdateAP) {
625 UpdateAP(NULL);
626 }
627 m_pForm->m_bUpdated = TRUE;
628 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700629}
Wei Li05d53f02016-03-29 16:42:53 -0700630
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700631FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index) {
632 ASSERT(GetType() == ComboBox || GetType() == ListBox);
Wei Li05d53f02016-03-29 16:42:53 -0700633 if (index < 0 || index >= CountOptions())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700634 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700635 int iDVIndex = GetDefaultSelectedItem();
Wei Li05d53f02016-03-29 16:42:53 -0700636 return iDVIndex >= 0 && iDVIndex == index;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700637}
Wei Li05d53f02016-03-29 16:42:53 -0700638
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700639int CPDF_FormField::GetDefaultSelectedItem() {
640 ASSERT(GetType() == ComboBox || GetType() == ListBox);
641 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
Wei Li05d53f02016-03-29 16:42:53 -0700642 if (!pValue)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643 return -1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700644 CFX_WideString csDV = pValue->GetUnicodeText();
Wei Li05d53f02016-03-29 16:42:53 -0700645 if (csDV.IsEmpty())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646 return -1;
Wei Li05d53f02016-03-29 16:42:53 -0700647 for (int i = 0; i < CountOptions(); i++) {
648 if (csDV == GetOptionValue(i))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700649 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650 }
651 return -1;
652}
Wei Li05d53f02016-03-29 16:42:53 -0700653
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl) {
Wei Li05d53f02016-03-29 16:42:53 -0700655 if (m_Type == PushButton || m_Type == RadioButton || m_Type == CheckBox)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700656 return;
Wei Li05d53f02016-03-29 16:42:53 -0700657 if (!m_pForm->m_bGenerateAP)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700658 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700659 for (int i = 0; i < CountControls(); i++) {
660 CPDF_FormControl* pControl = GetControl(i);
661 FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
662 }
663}
Wei Li05d53f02016-03-29 16:42:53 -0700664
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700665int CPDF_FormField::CountOptions() {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400666 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
667 return pArray ? pArray->GetCount() : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700668}
Wei Li05d53f02016-03-29 16:42:53 -0700669
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700670CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index) {
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400671 CPDF_Array* pArray = ToArray(FPDF_GetFieldAttr(m_pDict, "Opt"));
672 if (!pArray)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700673 return CFX_WideString();
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400674
tsepezbd567552016-03-29 14:51:50 -0700675 CPDF_Object* pOption = pArray->GetDirectObjectAt(index);
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400676 if (!pOption)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700677 return CFX_WideString();
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400678 if (CPDF_Array* pOptionArray = pOption->AsArray())
tsepezbd567552016-03-29 14:51:50 -0700679 pOption = pOptionArray->GetDirectObjectAt(sub_index);
Dan Sinclair316eb862015-10-21 13:29:23 -0400680
681 CPDF_String* pString = ToString(pOption);
682 return pString ? pString->GetUnicodeText() : CFX_WideString();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683}
684CFX_WideString CPDF_FormField::GetOptionLabel(int index) {
685 return GetOptionText(index, 1);
686}
687CFX_WideString CPDF_FormField::GetOptionValue(int index) {
688 return GetOptionText(index, 0);
689}
Wei Li05d53f02016-03-29 16:42:53 -0700690
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700691int CPDF_FormField::FindOption(CFX_WideString csOptLabel) {
Wei Li05d53f02016-03-29 16:42:53 -0700692 for (int i = 0; i < CountOptions(); i++) {
693 if (GetOptionValue(i) == csOptLabel)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700694 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700695 }
696 return -1;
697}
Wei Li05d53f02016-03-29 16:42:53 -0700698
699int CPDF_FormField::FindOptionValue(const CFX_WideString& csOptValue) {
700 for (int i = 0; i < CountOptions(); i++) {
701 if (GetOptionValue(i) == csOptValue)
702 return i;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700703 }
704 return -1;
705}
Wei Li05d53f02016-03-29 16:42:53 -0700706
Tom Sepez5c4c1932015-11-25 12:15:38 -0800707#ifdef PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700708int CPDF_FormField::InsertOption(CFX_WideString csOptLabel,
709 int index,
710 FX_BOOL bNotify) {
711 if (csOptLabel.IsEmpty())
712 return -1;
713
Lei Zhang4880d1a2015-12-18 17:05:11 -0800714 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700715 int iRet = 0;
716 if (GetType() == ListBox)
717 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csOptLabel);
718 if (GetType() == ComboBox)
719 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csOptLabel);
720 if (iRet < 0)
721 return -1;
722 }
723
724 CFX_ByteString csStr = PDF_EncodeText(csOptLabel, csOptLabel.GetLength());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700725 CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
Lei Zhang4880d1a2015-12-18 17:05:11 -0800726 CPDF_Array* pOpt = ToArray(pValue);
727 if (!pOpt) {
728 pOpt = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700729 m_pDict->SetAt("Opt", pOpt);
Lei Zhang4880d1a2015-12-18 17:05:11 -0800730 }
731
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700732 int iCount = (int)pOpt->GetCount();
733 if (index < 0 || index >= iCount) {
734 pOpt->AddString(csStr);
735 index = iCount;
736 } else {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800737 CPDF_String* pString = new CPDF_String(csStr, FALSE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700738 pOpt->InsertAt(index, pString);
739 }
740
Lei Zhang4880d1a2015-12-18 17:05:11 -0800741 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700742 if (GetType() == ListBox)
743 m_pForm->m_pFormNotify->AfterSelectionChange(this);
744 if (GetType() == ComboBox)
745 m_pForm->m_pFormNotify->AfterValueChange(this);
746 }
747 m_pForm->m_bUpdated = TRUE;
748 return index;
749}
750FX_BOOL CPDF_FormField::ClearOptions(FX_BOOL bNotify) {
Lei Zhang4880d1a2015-12-18 17:05:11 -0800751 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700752 int iRet = 0;
753 CFX_WideString csValue;
754 int iIndex = GetSelectedIndex(0);
755 if (iIndex >= 0)
756 csValue = GetOptionLabel(iIndex);
757 if (GetType() == ListBox)
758 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
759 if (GetType() == ComboBox)
760 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
761 if (iRet < 0)
762 return FALSE;
763 }
764
765 m_pDict->RemoveAt("Opt");
766 m_pDict->RemoveAt("V");
767 m_pDict->RemoveAt("DV");
768 m_pDict->RemoveAt("I");
769 m_pDict->RemoveAt("TI");
770
Lei Zhang4880d1a2015-12-18 17:05:11 -0800771 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700772 if (GetType() == ListBox)
773 m_pForm->m_pFormNotify->AfterSelectionChange(this);
774 if (GetType() == ComboBox)
775 m_pForm->m_pFormNotify->AfterValueChange(this);
776 }
777
778 m_pForm->m_bUpdated = TRUE;
779 return TRUE;
780}
Tom Sepeza2c42ce2015-11-25 15:52:28 -0800781#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700782FX_BOOL CPDF_FormField::CheckControl(int iControlIndex,
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800783 bool bChecked,
784 bool bNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700785 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
786 CPDF_FormControl* pControl = GetControl(iControlIndex);
Lei Zhang412e9082015-12-14 18:34:00 -0800787 if (!pControl) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700788 return FALSE;
789 }
790 if (!bChecked && pControl->IsChecked() == bChecked) {
791 return FALSE;
792 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700793 CFX_WideString csWExport = pControl->GetExportValue();
794 CFX_ByteString csBExport = PDF_EncodeText(csWExport);
795 int iCount = CountControls();
796 FX_BOOL bUnison = PDF_FormField_IsUnison(this);
797 for (int i = 0; i < iCount; i++) {
798 CPDF_FormControl* pCtrl = GetControl(i);
799 if (bUnison) {
800 CFX_WideString csEValue = pCtrl->GetExportValue();
801 if (csEValue == csWExport) {
802 if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
803 pCtrl->CheckControl(bChecked);
804 } else if (bChecked) {
805 pCtrl->CheckControl(FALSE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700806 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700807 } else if (bChecked) {
808 pCtrl->CheckControl(FALSE);
809 }
810 } else {
811 if (i == iControlIndex) {
812 pCtrl->CheckControl(bChecked);
813 } else if (bChecked) {
814 pCtrl->CheckControl(FALSE);
815 }
816 }
817 }
818 CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
Dan Sinclair2b11dc12015-10-22 15:02:06 -0400819 if (!ToArray(pOpt)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700820 if (bChecked) {
821 m_pDict->SetAtName("V", csBExport);
822 } else {
823 CFX_ByteString csV;
824 CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
Lei Zhang96660d62015-12-14 18:27:25 -0800825 if (pV) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700826 csV = pV->GetString();
827 }
828 if (csV == csBExport) {
829 m_pDict->SetAtName("V", "Off");
830 }
831 }
832 } else if (bChecked) {
833 CFX_ByteString csIndex;
834 csIndex.Format("%d", iControlIndex);
835 m_pDict->SetAtName("V", csIndex);
836 }
Lei Zhang96660d62015-12-14 18:27:25 -0800837 if (bNotify && m_pForm->m_pFormNotify) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800838 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700839 }
840 m_pForm->m_bUpdated = TRUE;
841 return TRUE;
842}
843CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault) {
844 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
845 CFX_WideString csExport = L"Off";
846 FX_BOOL bChecked;
847 int iCount = CountControls();
848 for (int i = 0; i < iCount; i++) {
849 CPDF_FormControl* pControl = GetControl(i);
850 if (bDefault) {
851 bChecked = pControl->IsDefaultChecked();
852 } else {
853 bChecked = pControl->IsChecked();
854 }
855 if (bChecked) {
856 csExport = pControl->GetExportValue();
857 break;
858 }
859 }
860 return csExport;
861}
862FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value,
863 FX_BOOL bDefault,
864 FX_BOOL bNotify) {
865 ASSERT(GetType() == CheckBox || GetType() == RadioButton);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700866 int iCount = CountControls();
867 for (int i = 0; i < iCount; i++) {
868 CPDF_FormControl* pControl = GetControl(i);
869 CFX_WideString csExport = pControl->GetExportValue();
870 if (csExport == value) {
871 if (bDefault) {
872 } else {
873 CheckControl(GetControlIndex(pControl), TRUE);
874 }
875 break;
876 } else {
877 if (bDefault) {
878 } else {
879 CheckControl(GetControlIndex(pControl), FALSE);
880 }
881 }
882 }
Lei Zhang96660d62015-12-14 18:27:25 -0800883 if (bNotify && m_pForm->m_pFormNotify) {
Tom Sepezed5d7aa2016-02-02 16:02:03 -0800884 m_pForm->m_pFormNotify->AfterCheckedStatusChange(this);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700885 }
886 m_pForm->m_bUpdated = TRUE;
887 return TRUE;
888}
889int CPDF_FormField::GetTopVisibleIndex() {
890 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
Lei Zhang412e9082015-12-14 18:34:00 -0800891 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700892 return 0;
893 }
894 return pObj->GetInteger();
895}
896int CPDF_FormField::CountSelectedOptions() {
897 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800898 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700899 return 0;
900 }
901 CPDF_Array* pArray = pObj->GetArray();
Lei Zhang412e9082015-12-14 18:34:00 -0800902 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700903 return 0;
904 }
905 return (int)pArray->GetCount();
906}
907int CPDF_FormField::GetSelectedOptionIndex(int index) {
908 CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
Lei Zhang412e9082015-12-14 18:34:00 -0800909 if (!pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700910 return -1;
911 }
912 CPDF_Array* pArray = pObj->GetArray();
Lei Zhang412e9082015-12-14 18:34:00 -0800913 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700914 return -1;
915 }
916 int iCount = (int)pArray->GetCount();
917 if (iCount > 0 && index < iCount) {
Wei Li9b761132016-01-29 15:44:20 -0800918 return pArray->GetIntegerAt(index);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700919 }
920 return -1;
921}
922FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex) {
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 FALSE;
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 FALSE;
930 }
931 int iCount = (int)pArray->GetCount();
932 for (int i = 0; i < iCount; i++) {
Wei Li9b761132016-01-29 15:44:20 -0800933 if (pArray->GetIntegerAt(i) == iOptIndex) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700934 return TRUE;
935 }
936 }
937 return FALSE;
938}
939FX_BOOL CPDF_FormField::SelectOption(int iOptIndex,
940 FX_BOOL bSelected,
941 FX_BOOL bNotify) {
Wei Li9b761132016-01-29 15:44:20 -0800942 CPDF_Array* pArray = m_pDict->GetArrayBy("I");
Lei Zhang412e9082015-12-14 18:34:00 -0800943 if (!pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700944 if (!bSelected) {
945 return TRUE;
946 }
Lei Zhang4880d1a2015-12-18 17:05:11 -0800947 pArray = new CPDF_Array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700948 m_pDict->SetAt("I", pArray);
949 }
950 FX_BOOL bReturn = FALSE;
951 for (int i = 0; i < (int)pArray->GetCount(); i++) {
Wei Li9b761132016-01-29 15:44:20 -0800952 int iFind = pArray->GetIntegerAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700953 if (iFind == iOptIndex) {
954 if (bSelected) {
955 return TRUE;
956 }
Lei Zhang96660d62015-12-14 18:27:25 -0800957 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700958 int iRet = 0;
959 CFX_WideString csValue = GetOptionLabel(iOptIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700960 if (GetType() == ListBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700961 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700962 }
963 if (GetType() == ComboBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700964 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700965 }
966 if (iRet < 0) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700967 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700968 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700969 }
970 pArray->RemoveAt(i);
971 bReturn = TRUE;
972 break;
973 } else if (iFind > iOptIndex) {
974 if (!bSelected) {
975 continue;
976 }
Lei Zhang96660d62015-12-14 18:27:25 -0800977 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700978 int iRet = 0;
979 CFX_WideString csValue = GetOptionLabel(iOptIndex);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700980 if (GetType() == ListBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700981 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700982 }
983 if (GetType() == ComboBox) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700984 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700985 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700986 if (iRet < 0) {
987 return FALSE;
988 }
989 }
Lei Zhang4880d1a2015-12-18 17:05:11 -0800990 CPDF_Number* pNum = new CPDF_Number(iOptIndex);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991 pArray->InsertAt(i, pNum);
992 bReturn = TRUE;
993 break;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700994 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700995 }
996 if (!bReturn) {
997 if (bSelected) {
998 pArray->AddInteger(iOptIndex);
999 }
1000 if (pArray->GetCount() == 0) {
1001 m_pDict->RemoveAt("I");
1002 }
1003 }
Lei Zhang96660d62015-12-14 18:27:25 -08001004 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001005 if (GetType() == ListBox) {
1006 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1007 }
1008 if (GetType() == ComboBox) {
1009 m_pForm->m_pFormNotify->AfterValueChange(this);
1010 }
1011 }
1012 m_pForm->m_bUpdated = TRUE;
1013 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001014}
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001015FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify) {
Lei Zhang96660d62015-12-14 18:27:25 -08001016 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001017 int iRet = 0;
1018 CFX_WideString csValue;
1019 int iIndex = GetSelectedIndex(0);
1020 if (iIndex >= 0) {
1021 csValue = GetOptionLabel(iIndex);
Bo Xu22b31e02014-07-21 10:02:07 -07001022 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001023 if (GetType() == ListBox) {
1024 iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001025 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001026 if (GetType() == ComboBox) {
1027 iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001028 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001029 if (iRet < 0) {
1030 return FALSE;
1031 }
1032 }
1033 m_pDict->RemoveAt("I");
Lei Zhang96660d62015-12-14 18:27:25 -08001034 if (bNotify && m_pForm->m_pFormNotify) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001035 if (GetType() == ListBox) {
1036 m_pForm->m_pFormNotify->AfterSelectionChange(this);
1037 }
1038 if (GetType() == ComboBox) {
1039 m_pForm->m_pFormNotify->AfterValueChange(this);
1040 }
1041 }
1042 m_pForm->m_bUpdated = TRUE;
1043 return TRUE;
1044}
1045void CPDF_FormField::LoadDA() {
1046 CFX_ByteString DA;
1047 if (CPDF_Object* pObj_t = FPDF_GetFieldAttr(m_pDict, "DA")) {
1048 DA = pObj_t->GetString();
1049 }
1050 if (DA.IsEmpty() && m_pForm->m_pFormDict) {
Wei Li9b761132016-01-29 15:44:20 -08001051 DA = m_pForm->m_pFormDict->GetStringBy("DA");
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001052 }
1053 if (DA.IsEmpty()) {
1054 return;
1055 }
1056 CPDF_SimpleParser syntax(DA);
Wei Li970c11e2016-02-16 14:26:22 -08001057 syntax.FindTagParamFromStart("Tf", 2);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001058 CFX_ByteString font_name = syntax.GetWord();
1059 CPDF_Dictionary* pFontDict = NULL;
Wei Li9b761132016-01-29 15:44:20 -08001060 if (m_pForm->m_pFormDict && m_pForm->m_pFormDict->GetDictBy("DR") &&
1061 m_pForm->m_pFormDict->GetDictBy("DR")->GetDictBy("Font"))
1062 pFontDict = m_pForm->m_pFormDict->GetDictBy("DR")
1063 ->GetDictBy("Font")
1064 ->GetDictBy(font_name);
Bo Xu287e11a2014-06-30 09:49:21 -07001065
Lei Zhang412e9082015-12-14 18:34:00 -08001066 if (!pFontDict) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001067 return;
1068 }
1069 m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
1070 m_FontSize = FX_atof(syntax.GetWord());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001071}