1// Copyright 2016 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 "fpdfsdk/cpdfsdk_interform.h" 8 9#include <algorithm> 10#include <memory> 11#include <sstream> 12#include <string> 13#include <vector> 14 15#include "core/fpdfapi/page/cpdf_page.h" 16#include "core/fpdfapi/parser/cfdf_document.h" 17#include "core/fpdfapi/parser/cpdf_array.h" 18#include "core/fpdfapi/parser/cpdf_document.h" 19#include "core/fpdfapi/parser/cpdf_stream.h" 20#include "core/fpdfdoc/cpdf_actionfields.h" 21#include "core/fpdfdoc/cpdf_interform.h" 22#include "core/fxge/cfx_graphstatedata.h" 23#include "core/fxge/cfx_pathdata.h" 24#include "fpdfsdk/cba_annotiterator.h" 25#include "fpdfsdk/cpdfsdk_annot.h" 26#include "fpdfsdk/cpdfsdk_formfillenvironment.h" 27#include "fpdfsdk/cpdfsdk_pageview.h" 28#include "fpdfsdk/cpdfsdk_widget.h" 29#include "fpdfsdk/formfiller/cffl_formfiller.h" 30#include "fpdfsdk/fsdk_actionhandler.h" 31#include "fpdfsdk/fsdk_define.h" 32#include "fpdfsdk/ipdfsdk_annothandler.h" 33#include "fxjs/ijs_event_context.h" 34#include "fxjs/ijs_runtime.h" 35#include "third_party/base/stl_util.h" 36 37#ifdef PDF_ENABLE_XFA 38#include "fpdfsdk/cpdfsdk_xfawidget.h" 39#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h" 40#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h" 41#include "xfa/fxfa/cxfa_eventparam.h" 42#include "xfa/fxfa/cxfa_ffdocview.h" 43#include "xfa/fxfa/cxfa_ffwidget.h" 44#include "xfa/fxfa/cxfa_ffwidgethandler.h" 45#endif // PDF_ENABLE_XFA 46 47namespace { 48 49bool IsFormFieldTypeComboOrText(FormFieldType fieldType) { 50 switch (fieldType) { 51 case FormFieldType::kComboBox: 52 case FormFieldType::kTextField: 53 return true; 54 default: 55 return false; 56 } 57} 58 59#ifdef PDF_ENABLE_XFA 60bool IsFormFieldTypeXFA(FormFieldType fieldType) { 61 switch (fieldType) { 62 case FormFieldType::kXFA: 63 case FormFieldType::kXFA_CheckBox: 64 case FormFieldType::kXFA_ComboBox: 65 case FormFieldType::kXFA_ImageField: 66 case FormFieldType::kXFA_ListBox: 67 case FormFieldType::kXFA_PushButton: 68 case FormFieldType::kXFA_Signature: 69 case FormFieldType::kXFA_TextField: 70 return true; 71 default: 72 return false; 73 } 74} 75#endif // PDF_ENABLE_XFA 76 77} // namespace 78 79CPDFSDK_InterForm::CPDFSDK_InterForm(CPDFSDK_FormFillEnvironment* pFormFillEnv) 80 : m_pFormFillEnv(pFormFillEnv), 81 m_pInterForm( 82 pdfium::MakeUnique<CPDF_InterForm>(m_pFormFillEnv->GetPDFDocument())), 83#ifdef PDF_ENABLE_XFA 84 m_bXfaCalculate(true), 85 m_bXfaValidationsEnabled(true), 86#endif // PDF_ENABLE_XFA 87 m_bCalculate(true), 88 m_bBusy(false), 89 m_HighlightAlpha(0) { 90 m_pInterForm->SetFormNotify(this); 91 RemoveAllHighLights(); 92} 93 94CPDFSDK_InterForm::~CPDFSDK_InterForm() { 95 m_Map.clear(); 96#ifdef PDF_ENABLE_XFA 97 m_XFAMap.clear(); 98#endif // PDF_ENABLE_XFA 99} 100 101bool CPDFSDK_InterForm::HighlightWidgets() { 102 return false; 103} 104 105CPDFSDK_Widget* CPDFSDK_InterForm::GetSibling(CPDFSDK_Widget* pWidget, 106 bool bNext) const { 107 auto pIterator = pdfium::MakeUnique<CBA_AnnotIterator>( 108 pWidget->GetPageView(), CPDF_Annot::Subtype::WIDGET); 109 110 if (bNext) 111 return static_cast<CPDFSDK_Widget*>(pIterator->GetNextAnnot(pWidget)); 112 113 return static_cast<CPDFSDK_Widget*>(pIterator->GetPrevAnnot(pWidget)); 114} 115 116CPDFSDK_Widget* CPDFSDK_InterForm::GetWidget(CPDF_FormControl* pControl) const { 117 if (!pControl || !m_pInterForm) 118 return nullptr; 119 120 CPDFSDK_Widget* pWidget = nullptr; 121 const auto it = m_Map.find(pControl); 122 if (it != m_Map.end()) 123 pWidget = it->second; 124 if (pWidget) 125 return pWidget; 126 127 CPDF_Dictionary* pControlDict = pControl->GetWidget(); 128 CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument(); 129 CPDFSDK_PageView* pPage = nullptr; 130 131 if (CPDF_Dictionary* pPageDict = pControlDict->GetDictFor("P")) { 132 int nPageIndex = pDocument->GetPageIndex(pPageDict->GetObjNum()); 133 if (nPageIndex >= 0) 134 pPage = m_pFormFillEnv->GetPageView(nPageIndex); 135 } 136 137 if (!pPage) { 138 int nPageIndex = GetPageIndexByAnnotDict(pDocument, pControlDict); 139 if (nPageIndex >= 0) 140 pPage = m_pFormFillEnv->GetPageView(nPageIndex); 141 } 142 143 if (!pPage) 144 return nullptr; 145 146 return static_cast<CPDFSDK_Widget*>(pPage->GetAnnotByDict(pControlDict)); 147} 148 149void CPDFSDK_InterForm::GetWidgets( 150 const WideString& sFieldName, 151 std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const { 152 for (int i = 0, sz = m_pInterForm->CountFields(sFieldName); i < sz; ++i) { 153 CPDF_FormField* pFormField = m_pInterForm->GetField(i, sFieldName); 154 ASSERT(pFormField); 155 GetWidgets(pFormField, widgets); 156 } 157} 158 159void CPDFSDK_InterForm::GetWidgets( 160 CPDF_FormField* pField, 161 std::vector<CPDFSDK_Annot::ObservedPtr>* widgets) const { 162 for (int i = 0, sz = pField->CountControls(); i < sz; ++i) { 163 CPDF_FormControl* pFormCtrl = pField->GetControl(i); 164 ASSERT(pFormCtrl); 165 CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl); 166 if (pWidget) 167 widgets->emplace_back(pWidget); 168 } 169} 170 171int CPDFSDK_InterForm::GetPageIndexByAnnotDict( 172 CPDF_Document* pDocument, 173 CPDF_Dictionary* pAnnotDict) const { 174 ASSERT(pAnnotDict); 175 176 for (int i = 0, sz = pDocument->GetPageCount(); i < sz; i++) { 177 if (CPDF_Dictionary* pPageDict = pDocument->GetPage(i)) { 178 if (CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots")) { 179 for (int j = 0, jsz = pAnnots->GetCount(); j < jsz; j++) { 180 CPDF_Object* pDict = pAnnots->GetDirectObjectAt(j); 181 if (pAnnotDict == pDict) 182 return i; 183 } 184 } 185 } 186 } 187 188 return -1; 189} 190 191void CPDFSDK_InterForm::AddMap(CPDF_FormControl* pControl, 192 CPDFSDK_Widget* pWidget) { 193 m_Map[pControl] = pWidget; 194} 195 196void CPDFSDK_InterForm::RemoveMap(CPDF_FormControl* pControl) { 197 m_Map.erase(pControl); 198} 199 200void CPDFSDK_InterForm::EnableCalculate(bool bEnabled) { 201 m_bCalculate = bEnabled; 202} 203 204bool CPDFSDK_InterForm::IsCalculateEnabled() const { 205 return m_bCalculate; 206} 207 208#ifdef PDF_ENABLE_XFA 209void CPDFSDK_InterForm::AddXFAMap(CXFA_FFWidget* hWidget, 210 CPDFSDK_XFAWidget* pWidget) { 211 ASSERT(hWidget); 212 m_XFAMap[hWidget] = pWidget; 213} 214 215void CPDFSDK_InterForm::RemoveXFAMap(CXFA_FFWidget* hWidget) { 216 ASSERT(hWidget); 217 m_XFAMap.erase(hWidget); 218} 219 220CPDFSDK_XFAWidget* CPDFSDK_InterForm::GetXFAWidget(CXFA_FFWidget* hWidget) { 221 ASSERT(hWidget); 222 auto it = m_XFAMap.find(hWidget); 223 return it != m_XFAMap.end() ? it->second : nullptr; 224} 225 226void CPDFSDK_InterForm::XfaEnableCalculate(bool bEnabled) { 227 m_bXfaCalculate = bEnabled; 228} 229bool CPDFSDK_InterForm::IsXfaCalculateEnabled() const { 230 return m_bXfaCalculate; 231} 232 233bool CPDFSDK_InterForm::IsXfaValidationsEnabled() { 234 return m_bXfaValidationsEnabled; 235} 236void CPDFSDK_InterForm::XfaSetValidationsEnabled(bool bEnabled) { 237 m_bXfaValidationsEnabled = bEnabled; 238} 239 240void CPDFSDK_InterForm::SynchronizeField(CPDF_FormField* pFormField, 241 bool bSynchronizeElse) { 242 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { 243 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); 244 if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) 245 pWidget->Synchronize(bSynchronizeElse); 246 } 247} 248#endif // PDF_ENABLE_XFA 249 250void CPDFSDK_InterForm::OnCalculate(CPDF_FormField* pFormField) { 251 if (!m_pFormFillEnv->IsJSInitiated()) 252 return; 253 254 if (m_bBusy) 255 return; 256 257 m_bBusy = true; 258 259 if (!IsCalculateEnabled()) { 260 m_bBusy = false; 261 return; 262 } 263 264 IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime(); 265 int nSize = m_pInterForm->CountFieldsInCalculationOrder(); 266 for (int i = 0; i < nSize; i++) { 267 CPDF_FormField* pField = m_pInterForm->GetFieldInCalculationOrder(i); 268 if (!pField) 269 continue; 270 271 FormFieldType fieldType = pField->GetFieldType(); 272 if (!IsFormFieldTypeComboOrText(fieldType)) 273 continue; 274 275 CPDF_AAction aAction = pField->GetAdditionalAction(); 276 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Calculate)) 277 continue; 278 279 CPDF_Action action = aAction.GetAction(CPDF_AAction::Calculate); 280 if (!action.GetDict()) 281 continue; 282 283 WideString csJS = action.GetJavaScript(); 284 if (csJS.IsEmpty()) 285 continue; 286 287 IJS_EventContext* pContext = pRuntime->NewEventContext(); 288 WideString sOldValue = pField->GetValue(); 289 WideString sValue = sOldValue; 290 bool bRC = true; 291 pContext->OnField_Calculate(pFormField, pField, sValue, bRC); 292 293 WideString sInfo; 294 bool bRet = pContext->RunScript(csJS, &sInfo); 295 pRuntime->ReleaseEventContext(pContext); 296 if (bRet && bRC && sValue.Compare(sOldValue) != 0) 297 pField->SetValue(sValue, true); 298 } 299 m_bBusy = false; 300} 301 302WideString CPDFSDK_InterForm::OnFormat(CPDF_FormField* pFormField, 303 bool& bFormatted) { 304 WideString sValue = pFormField->GetValue(); 305 if (!m_pFormFillEnv->IsJSInitiated()) { 306 bFormatted = false; 307 return sValue; 308 } 309 310 IJS_Runtime* pRuntime = m_pFormFillEnv->GetJSRuntime(); 311 if (pFormField->GetFieldType() == FormFieldType::kComboBox && 312 pFormField->CountSelectedItems() > 0) { 313 int index = pFormField->GetSelectedIndex(0); 314 if (index >= 0) 315 sValue = pFormField->GetOptionLabel(index); 316 } 317 318 bFormatted = false; 319 320 CPDF_AAction aAction = pFormField->GetAdditionalAction(); 321 if (aAction.GetDict() && aAction.ActionExist(CPDF_AAction::Format)) { 322 CPDF_Action action = aAction.GetAction(CPDF_AAction::Format); 323 if (action.GetDict()) { 324 WideString script = action.GetJavaScript(); 325 if (!script.IsEmpty()) { 326 WideString Value = sValue; 327 328 IJS_EventContext* pContext = pRuntime->NewEventContext(); 329 pContext->OnField_Format(pFormField, Value, true); 330 WideString sInfo; 331 bool bRet = pContext->RunScript(script, &sInfo); 332 pRuntime->ReleaseEventContext(pContext); 333 if (bRet) { 334 sValue = Value; 335 bFormatted = true; 336 } 337 } 338 } 339 } 340 return sValue; 341} 342 343void CPDFSDK_InterForm::ResetFieldAppearance(CPDF_FormField* pFormField, 344 const WideString* sValue, 345 bool bValueChanged) { 346 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { 347 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); 348 ASSERT(pFormCtrl); 349 if (CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl)) 350 pWidget->ResetAppearance(sValue, bValueChanged); 351 } 352} 353 354void CPDFSDK_InterForm::UpdateField(CPDF_FormField* pFormField) { 355 auto* formfiller = m_pFormFillEnv->GetInteractiveFormFiller(); 356 for (int i = 0, sz = pFormField->CountControls(); i < sz; i++) { 357 CPDF_FormControl* pFormCtrl = pFormField->GetControl(i); 358 ASSERT(pFormCtrl); 359 360 CPDFSDK_Widget* pWidget = GetWidget(pFormCtrl); 361 if (!pWidget) 362 continue; 363 364 UnderlyingPageType* pPage = pWidget->GetUnderlyingPage(); 365 FX_RECT rect = formfiller->GetViewBBox( 366 m_pFormFillEnv->GetPageView(pPage, false), pWidget); 367 m_pFormFillEnv->Invalidate(pPage, rect); 368 } 369} 370 371bool CPDFSDK_InterForm::OnKeyStrokeCommit(CPDF_FormField* pFormField, 372 const WideString& csValue) { 373 CPDF_AAction aAction = pFormField->GetAdditionalAction(); 374 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::KeyStroke)) 375 return true; 376 377 CPDF_Action action = aAction.GetAction(CPDF_AAction::KeyStroke); 378 if (!action.GetDict()) 379 return true; 380 381 CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler(); 382 PDFSDK_FieldAction fa; 383 fa.bModifier = false; 384 fa.bShift = false; 385 fa.sValue = csValue; 386 pActionHandler->DoAction_FieldJavaScript( 387 action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa); 388 return fa.bRC; 389} 390 391bool CPDFSDK_InterForm::OnValidate(CPDF_FormField* pFormField, 392 const WideString& csValue) { 393 CPDF_AAction aAction = pFormField->GetAdditionalAction(); 394 if (!aAction.GetDict() || !aAction.ActionExist(CPDF_AAction::Validate)) 395 return true; 396 397 CPDF_Action action = aAction.GetAction(CPDF_AAction::Validate); 398 if (!action.GetDict()) 399 return true; 400 401 CPDFSDK_ActionHandler* pActionHandler = m_pFormFillEnv->GetActionHandler(); 402 PDFSDK_FieldAction fa; 403 fa.bModifier = false; 404 fa.bShift = false; 405 fa.sValue = csValue; 406 pActionHandler->DoAction_FieldJavaScript( 407 action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa); 408 return fa.bRC; 409} 410 411bool CPDFSDK_InterForm::DoAction_Hide(const CPDF_Action& action) { 412 ASSERT(action.GetDict()); 413 414 CPDF_ActionFields af(&action); 415 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields(); 416 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects); 417 418 bool bHide = action.GetHideStatus(); 419 bool bChanged = false; 420 421 for (CPDF_FormField* pField : fields) { 422 for (int i = 0, sz = pField->CountControls(); i < sz; ++i) { 423 CPDF_FormControl* pControl = pField->GetControl(i); 424 ASSERT(pControl); 425 426 if (CPDFSDK_Widget* pWidget = GetWidget(pControl)) { 427 uint32_t nFlags = pWidget->GetFlags(); 428 nFlags &= ~ANNOTFLAG_INVISIBLE; 429 nFlags &= ~ANNOTFLAG_NOVIEW; 430 if (bHide) 431 nFlags |= ANNOTFLAG_HIDDEN; 432 else 433 nFlags &= ~ANNOTFLAG_HIDDEN; 434 pWidget->SetFlags(nFlags); 435 pWidget->GetPageView()->UpdateView(pWidget); 436 bChanged = true; 437 } 438 } 439 } 440 441 return bChanged; 442} 443 444bool CPDFSDK_InterForm::DoAction_SubmitForm(const CPDF_Action& action) { 445 WideString sDestination = action.GetFilePath(); 446 if (sDestination.IsEmpty()) 447 return false; 448 449 CPDF_Dictionary* pActionDict = action.GetDict(); 450 if (pActionDict->KeyExist("Fields")) { 451 CPDF_ActionFields af(&action); 452 uint32_t dwFlags = action.GetFlags(); 453 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields(); 454 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects); 455 if (!fields.empty()) { 456 bool bIncludeOrExclude = !(dwFlags & 0x01); 457 if (!m_pInterForm->CheckRequiredFields(&fields, bIncludeOrExclude)) 458 return false; 459 460 return SubmitFields(sDestination, fields, bIncludeOrExclude, false); 461 } 462 } 463 if (!m_pInterForm->CheckRequiredFields(nullptr, true)) 464 return false; 465 466 return SubmitForm(sDestination, false); 467} 468 469bool CPDFSDK_InterForm::SubmitFields(const WideString& csDestination, 470 const std::vector<CPDF_FormField*>& fields, 471 bool bIncludeOrExclude, 472 bool bUrlEncoded) { 473 ByteString textBuf = ExportFieldsToFDFTextBuf(fields, bIncludeOrExclude); 474 475 size_t nBufSize = textBuf.GetLength(); 476 if (nBufSize == 0) 477 return false; 478 479 uint8_t* pLocalBuffer = FX_Alloc(uint8_t, nBufSize); 480 memcpy(pLocalBuffer, textBuf.c_str(), nBufSize); 481 uint8_t* pBuffer = pLocalBuffer; 482 483 if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) { 484 FX_Free(pLocalBuffer); 485 return false; 486 } 487 488 m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, csDestination.c_str()); 489 490 if (pBuffer != pLocalBuffer) 491 FX_Free(pBuffer); 492 493 FX_Free(pLocalBuffer); 494 495 return true; 496} 497 498bool CPDFSDK_InterForm::FDFToURLEncodedData(uint8_t*& pBuf, size_t& nBufSize) { 499 std::unique_ptr<CFDF_Document> pFDF = 500 CFDF_Document::ParseMemory(pBuf, nBufSize); 501 if (!pFDF) 502 return true; 503 504 CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDictFor("FDF"); 505 if (!pMainDict) 506 return false; 507 508 CPDF_Array* pFields = pMainDict->GetArrayFor("Fields"); 509 if (!pFields) 510 return false; 511 512 std::ostringstream fdfEncodedData; 513 for (uint32_t i = 0; i < pFields->GetCount(); i++) { 514 CPDF_Dictionary* pField = pFields->GetDictAt(i); 515 if (!pField) 516 continue; 517 WideString name; 518 name = pField->GetUnicodeTextFor("T"); 519 ByteString name_b = ByteString::FromUnicode(name); 520 ByteString csBValue = pField->GetStringFor("V"); 521 WideString csWValue = PDF_DecodeText(csBValue); 522 ByteString csValue_b = ByteString::FromUnicode(csWValue); 523 524 fdfEncodedData << name_b.GetBuffer(name_b.GetLength()); 525 name_b.ReleaseBuffer(name_b.GetStringLength()); 526 fdfEncodedData << "="; 527 fdfEncodedData << csValue_b.GetBuffer(csValue_b.GetLength()); 528 csValue_b.ReleaseBuffer(csValue_b.GetStringLength()); 529 if (i != pFields->GetCount() - 1) 530 fdfEncodedData << "&"; 531 } 532 533 nBufSize = fdfEncodedData.tellp(); 534 if (nBufSize == 0) 535 return false; 536 537 pBuf = FX_Alloc(uint8_t, nBufSize); 538 memcpy(pBuf, fdfEncodedData.str().c_str(), nBufSize); 539 return true; 540} 541 542ByteString CPDFSDK_InterForm::ExportFieldsToFDFTextBuf( 543 const std::vector<CPDF_FormField*>& fields, 544 bool bIncludeOrExclude) { 545 std::unique_ptr<CFDF_Document> pFDF = m_pInterForm->ExportToFDF( 546 m_pFormFillEnv->JS_docGetFilePath(), fields, bIncludeOrExclude, false); 547 548 return pFDF ? pFDF->WriteToString() : ByteString(); 549} 550 551bool CPDFSDK_InterForm::SubmitForm(const WideString& sDestination, 552 bool bUrlEncoded) { 553 if (sDestination.IsEmpty()) 554 return false; 555 556 if (!m_pFormFillEnv || !m_pInterForm) 557 return false; 558 559 std::unique_ptr<CFDF_Document> pFDFDoc = 560 m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false); 561 if (!pFDFDoc) 562 return false; 563 564 ByteString fdfBuffer = pFDFDoc->WriteToString(); 565 566 if (fdfBuffer.IsEmpty()) 567 return false; 568 569 uint8_t* pLocalBuffer = FX_Alloc(uint8_t, fdfBuffer.GetLength()); 570 memcpy(pLocalBuffer, fdfBuffer.c_str(), fdfBuffer.GetLength()); 571 uint8_t* pBuffer = pLocalBuffer; 572 573 size_t nBufSize = fdfBuffer.GetLength(); 574 if (bUrlEncoded && !FDFToURLEncodedData(pBuffer, nBufSize)) { 575 FX_Free(pLocalBuffer); 576 return false; 577 } 578 579 m_pFormFillEnv->JS_docSubmitForm(pBuffer, nBufSize, sDestination.c_str()); 580 581 if (pBuffer != pLocalBuffer) 582 FX_Free(pBuffer); 583 584 FX_Free(pLocalBuffer); 585 586 return true; 587} 588 589ByteString CPDFSDK_InterForm::ExportFormToFDFTextBuf() { 590 std::unique_ptr<CFDF_Document> pFDF = 591 m_pInterForm->ExportToFDF(m_pFormFillEnv->JS_docGetFilePath(), false); 592 593 return pFDF ? pFDF->WriteToString() : ByteString(); 594} 595 596bool CPDFSDK_InterForm::DoAction_ResetForm(const CPDF_Action& action) { 597 ASSERT(action.GetDict()); 598 599 CPDF_Dictionary* pActionDict = action.GetDict(); 600 if (!pActionDict->KeyExist("Fields")) 601 return m_pInterForm->ResetForm(true); 602 603 CPDF_ActionFields af(&action); 604 uint32_t dwFlags = action.GetFlags(); 605 606 std::vector<CPDF_Object*> fieldObjects = af.GetAllFields(); 607 std::vector<CPDF_FormField*> fields = GetFieldFromObjects(fieldObjects); 608 return m_pInterForm->ResetForm(fields, !(dwFlags & 0x01), true); 609} 610 611bool CPDFSDK_InterForm::DoAction_ImportData(const CPDF_Action& action) { 612 return false; 613} 614 615std::vector<CPDF_FormField*> CPDFSDK_InterForm::GetFieldFromObjects( 616 const std::vector<CPDF_Object*>& objects) const { 617 std::vector<CPDF_FormField*> fields; 618 for (CPDF_Object* pObject : objects) { 619 if (pObject && pObject->IsString()) { 620 WideString csName = pObject->GetUnicodeText(); 621 CPDF_FormField* pField = m_pInterForm->GetField(0, csName); 622 if (pField) 623 fields.push_back(pField); 624 } 625 } 626 return fields; 627} 628 629int CPDFSDK_InterForm::BeforeValueChange(CPDF_FormField* pField, 630 const WideString& csValue) { 631 FormFieldType fieldType = pField->GetFieldType(); 632 if (!IsFormFieldTypeComboOrText(fieldType)) 633 return 0; 634 635 if (!OnKeyStrokeCommit(pField, csValue)) 636 return -1; 637 638 if (!OnValidate(pField, csValue)) 639 return -1; 640 641 return 1; 642} 643 644void CPDFSDK_InterForm::AfterValueChange(CPDF_FormField* pField) { 645#ifdef PDF_ENABLE_XFA 646 SynchronizeField(pField, false); 647#endif // PDF_ENABLE_XFA 648 FormFieldType fieldType = pField->GetFieldType(); 649 if (IsFormFieldTypeComboOrText(fieldType)) { 650 OnCalculate(pField); 651 bool bFormatted = false; 652 WideString sValue = OnFormat(pField, bFormatted); 653 ResetFieldAppearance(pField, bFormatted ? &sValue : nullptr, true); 654 UpdateField(pField); 655 } 656} 657 658int CPDFSDK_InterForm::BeforeSelectionChange(CPDF_FormField* pField, 659 const WideString& csValue) { 660 if (pField->GetFieldType() != FormFieldType::kListBox) 661 return 0; 662 663 if (!OnKeyStrokeCommit(pField, csValue)) 664 return -1; 665 666 if (!OnValidate(pField, csValue)) 667 return -1; 668 669 return 1; 670} 671 672void CPDFSDK_InterForm::AfterSelectionChange(CPDF_FormField* pField) { 673 if (pField->GetFieldType() != FormFieldType::kListBox) 674 return; 675 676 OnCalculate(pField); 677 ResetFieldAppearance(pField, nullptr, true); 678 UpdateField(pField); 679} 680 681void CPDFSDK_InterForm::AfterCheckedStatusChange(CPDF_FormField* pField) { 682 FormFieldType fieldType = pField->GetFieldType(); 683 if (fieldType != FormFieldType::kCheckBox && 684 fieldType != FormFieldType::kRadioButton) 685 return; 686 687 OnCalculate(pField); 688 UpdateField(pField); 689} 690 691int CPDFSDK_InterForm::BeforeFormReset(CPDF_InterForm* pForm) { 692 return 0; 693} 694 695void CPDFSDK_InterForm::AfterFormReset(CPDF_InterForm* pForm) { 696 OnCalculate(nullptr); 697} 698 699int CPDFSDK_InterForm::BeforeFormImportData(CPDF_InterForm* pForm) { 700 return 0; 701} 702 703void CPDFSDK_InterForm::AfterFormImportData(CPDF_InterForm* pForm) { 704 OnCalculate(nullptr); 705} 706 707bool CPDFSDK_InterForm::IsNeedHighLight(FormFieldType fieldType) { 708 if (fieldType == FormFieldType::kUnknown) 709 return false; 710 711#ifdef PDF_ENABLE_XFA 712 // For the XFA fields, we need to return if the specific field type has 713 // highlight enabled or if the general XFA field type has it enabled. 714 if (IsFormFieldTypeXFA(fieldType)) { 715 if (!m_NeedsHighlight[static_cast<size_t>(fieldType)]) 716 return m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)]; 717 } 718#endif // PDF_ENABLE_XFA 719 return m_NeedsHighlight[static_cast<size_t>(fieldType)]; 720} 721 722void CPDFSDK_InterForm::RemoveAllHighLights() { 723 std::fill(m_HighlightColor, m_HighlightColor + kFormFieldTypeCount, 724 FXSYS_RGB(255, 255, 255)); 725 std::fill(m_NeedsHighlight, m_NeedsHighlight + kFormFieldTypeCount, false); 726} 727 728void CPDFSDK_InterForm::SetHighlightColor(FX_COLORREF clr, 729 FormFieldType fieldType) { 730 if (fieldType == FormFieldType::kUnknown) 731 return; 732 733 m_HighlightColor[static_cast<size_t>(fieldType)] = clr; 734 m_NeedsHighlight[static_cast<size_t>(fieldType)] = true; 735} 736 737void CPDFSDK_InterForm::SetAllHighlightColors(FX_COLORREF clr) { 738 for (auto type : kFormFieldTypes) { 739 m_HighlightColor[static_cast<size_t>(type)] = clr; 740 m_NeedsHighlight[static_cast<size_t>(type)] = true; 741 } 742} 743 744FX_COLORREF CPDFSDK_InterForm::GetHighlightColor(FormFieldType fieldType) { 745 if (fieldType == FormFieldType::kUnknown) 746 return FXSYS_RGB(255, 255, 255); 747 748#ifdef PDF_ENABLE_XFA 749 // For the XFA fields, we need to return the specific field type highlight 750 // colour or the general XFA field type colour if present. 751 if (IsFormFieldTypeXFA(fieldType)) { 752 if (!m_NeedsHighlight[static_cast<size_t>(fieldType)] && 753 m_NeedsHighlight[static_cast<size_t>(FormFieldType::kXFA)]) { 754 return m_HighlightColor[static_cast<size_t>(FormFieldType::kXFA)]; 755 } 756 } 757#endif // PDF_ENABLE_XFA 758 return m_HighlightColor[static_cast<size_t>(fieldType)]; 759} 760