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