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 "core/fpdfdoc/cpdf_interform.h" 8 9 #include <utility> 10 #include <vector> 11 12 #include "core/fpdfapi/font/cpdf_font.h" 13 #include "core/fpdfapi/font/cpdf_fontencoding.h" 14 #include "core/fpdfapi/page/cpdf_page.h" 15 #include "core/fpdfapi/parser/cfdf_document.h" 16 #include "core/fpdfapi/parser/cpdf_array.h" 17 #include "core/fpdfapi/parser/cpdf_document.h" 18 #include "core/fpdfapi/parser/cpdf_name.h" 19 #include "core/fpdfapi/parser/cpdf_reference.h" 20 #include "core/fpdfapi/parser/cpdf_string.h" 21 #include "core/fpdfdoc/cpdf_filespec.h" 22 #include "core/fpdfdoc/cpdf_formcontrol.h" 23 #include "core/fxge/cfx_substfont.h" 24 #include "core/fxge/fx_font.h" 25 #include "third_party/base/stl_util.h" 26 27 namespace { 28 29 const int nMaxRecursion = 32; 30 31 const struct SupportFieldEncoding { 32 const FX_CHAR* m_name; 33 uint16_t m_codePage; 34 } g_fieldEncoding[] = { 35 {"BigFive", 950}, 36 {"GBK", 936}, 37 {"Shift-JIS", 932}, 38 {"UHC", 949}, 39 }; 40 41 CFX_WideString GetFieldValue(const CPDF_Dictionary& pFieldDict, 42 const CFX_ByteString& bsEncoding) { 43 const CFX_ByteString csBValue = pFieldDict.GetStringFor("V"); 44 for (const auto& encoding : g_fieldEncoding) { 45 if (bsEncoding == encoding.m_name) 46 return CFX_WideString::FromCodePage(csBValue.AsStringC(), 47 encoding.m_codePage); 48 } 49 CFX_ByteString csTemp = csBValue.Left(2); 50 if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") 51 return PDF_DecodeText(csBValue); 52 return CFX_WideString::FromLocal(csBValue.AsStringC()); 53 } 54 55 void AddFont(CPDF_Dictionary*& pFormDict, 56 CPDF_Document* pDocument, 57 const CPDF_Font* pFont, 58 CFX_ByteString& csNameTag); 59 60 void InitDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument) { 61 if (!pDocument) 62 return; 63 64 if (!pFormDict) { 65 pFormDict = pDocument->NewIndirect<CPDF_Dictionary>(); 66 pDocument->GetRoot()->SetNewFor<CPDF_Reference>("AcroForm", pDocument, 67 pFormDict->GetObjNum()); 68 } 69 70 CFX_ByteString csDA; 71 if (!pFormDict->KeyExist("DR")) { 72 CFX_ByteString csBaseName; 73 CFX_ByteString csDefault; 74 uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); 75 CPDF_Font* pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica"); 76 if (pFont) { 77 AddFont(pFormDict, pDocument, pFont, csBaseName); 78 csDefault = csBaseName; 79 } 80 if (charSet != FXFONT_ANSI_CHARSET) { 81 CFX_ByteString csFontName = 82 CPDF_InterForm::GetNativeFont(charSet, nullptr); 83 if (!pFont || csFontName != "Helvetica") { 84 pFont = CPDF_InterForm::AddNativeFont(pDocument); 85 if (pFont) { 86 csBaseName = ""; 87 AddFont(pFormDict, pDocument, pFont, csBaseName); 88 csDefault = csBaseName; 89 } 90 } 91 } 92 if (pFont) 93 csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf"; 94 } 95 if (!csDA.IsEmpty()) 96 csDA += " "; 97 98 csDA += "0 g"; 99 if (!pFormDict->KeyExist("DA")) 100 pFormDict->SetNewFor<CPDF_String>("DA", csDA, false); 101 } 102 103 CPDF_Font* GetFont(CPDF_Dictionary* pFormDict, 104 CPDF_Document* pDocument, 105 CFX_ByteString csNameTag) { 106 CFX_ByteString csAlias = PDF_NameDecode(csNameTag); 107 if (!pFormDict || csAlias.IsEmpty()) 108 return nullptr; 109 110 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); 111 if (!pDR) 112 return nullptr; 113 114 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); 115 if (!pFonts) 116 return nullptr; 117 118 CPDF_Dictionary* pElement = pFonts->GetDictFor(csAlias); 119 if (!pElement) 120 return nullptr; 121 122 if (pElement->GetStringFor("Type") == "Font") 123 return pDocument->LoadFont(pElement); 124 return nullptr; 125 } 126 127 CPDF_Font* GetNativeFont(CPDF_Dictionary* pFormDict, 128 CPDF_Document* pDocument, 129 uint8_t charSet, 130 CFX_ByteString& csNameTag) { 131 if (!pFormDict) 132 return nullptr; 133 134 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); 135 if (!pDR) 136 return nullptr; 137 138 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); 139 if (!pFonts) 140 return nullptr; 141 142 for (const auto& it : *pFonts) { 143 const CFX_ByteString& csKey = it.first; 144 if (!it.second) 145 continue; 146 147 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); 148 if (!pElement) 149 continue; 150 if (pElement->GetStringFor("Type") != "Font") 151 continue; 152 CPDF_Font* pFind = pDocument->LoadFont(pElement); 153 if (!pFind) 154 continue; 155 156 CFX_SubstFont* pSubst = pFind->GetSubstFont(); 157 if (!pSubst) 158 continue; 159 160 if (pSubst->m_Charset == (int)charSet) { 161 csNameTag = csKey; 162 return pFind; 163 } 164 } 165 return nullptr; 166 } 167 168 bool FindFont(CPDF_Dictionary* pFormDict, 169 const CPDF_Font* pFont, 170 CFX_ByteString& csNameTag) { 171 if (!pFormDict || !pFont) 172 return false; 173 174 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); 175 if (!pDR) 176 return false; 177 178 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); 179 if (!pFonts) 180 return false; 181 182 for (const auto& it : *pFonts) { 183 const CFX_ByteString& csKey = it.first; 184 if (!it.second) 185 continue; 186 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); 187 if (!pElement) 188 continue; 189 if (pElement->GetStringFor("Type") != "Font") 190 continue; 191 if (pFont->GetFontDict() == pElement) { 192 csNameTag = csKey; 193 return true; 194 } 195 } 196 return false; 197 } 198 199 bool FindFont(CPDF_Dictionary* pFormDict, 200 CPDF_Document* pDocument, 201 CFX_ByteString csFontName, 202 CPDF_Font*& pFont, 203 CFX_ByteString& csNameTag) { 204 if (!pFormDict) 205 return false; 206 207 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); 208 if (!pDR) 209 return false; 210 211 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); 212 if (!pFonts) 213 return false; 214 if (csFontName.GetLength() > 0) 215 csFontName.Remove(' '); 216 217 for (const auto& it : *pFonts) { 218 const CFX_ByteString& csKey = it.first; 219 if (!it.second) 220 continue; 221 222 CPDF_Dictionary* pElement = ToDictionary(it.second->GetDirect()); 223 if (!pElement) 224 continue; 225 if (pElement->GetStringFor("Type") != "Font") 226 continue; 227 pFont = pDocument->LoadFont(pElement); 228 if (!pFont) 229 continue; 230 231 CFX_ByteString csBaseFont; 232 csBaseFont = pFont->GetBaseFont(); 233 csBaseFont.Remove(' '); 234 if (csBaseFont == csFontName) { 235 csNameTag = csKey; 236 return true; 237 } 238 } 239 return false; 240 } 241 242 void AddFont(CPDF_Dictionary*& pFormDict, 243 CPDF_Document* pDocument, 244 const CPDF_Font* pFont, 245 CFX_ByteString& csNameTag) { 246 if (!pFont) 247 return; 248 if (!pFormDict) 249 InitDict(pFormDict, pDocument); 250 251 CFX_ByteString csTag; 252 if (FindFont(pFormDict, pFont, csTag)) { 253 csNameTag = csTag; 254 return; 255 } 256 if (!pFormDict) 257 InitDict(pFormDict, pDocument); 258 259 CPDF_Dictionary* pDR = pFormDict->GetDictFor("DR"); 260 if (!pDR) 261 pDR = pFormDict->SetNewFor<CPDF_Dictionary>("DR"); 262 263 CPDF_Dictionary* pFonts = pDR->GetDictFor("Font"); 264 if (!pFonts) 265 pFonts = pDR->SetNewFor<CPDF_Dictionary>("Font"); 266 267 if (csNameTag.IsEmpty()) 268 csNameTag = pFont->GetBaseFont(); 269 270 csNameTag.Remove(' '); 271 csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, 272 csNameTag.c_str()); 273 pFonts->SetNewFor<CPDF_Reference>(csNameTag, pDocument, 274 pFont->GetFontDict()->GetObjNum()); 275 } 276 277 CPDF_Font* AddNativeFont(CPDF_Dictionary*& pFormDict, 278 CPDF_Document* pDocument, 279 uint8_t charSet, 280 CFX_ByteString& csNameTag) { 281 if (!pFormDict) 282 InitDict(pFormDict, pDocument); 283 284 CFX_ByteString csTemp; 285 CPDF_Font* pFont = GetNativeFont(pFormDict, pDocument, charSet, csTemp); 286 if (pFont) { 287 csNameTag = csTemp; 288 return pFont; 289 } 290 CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, nullptr); 291 if (!csFontName.IsEmpty() && 292 FindFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) { 293 return pFont; 294 } 295 pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument); 296 if (pFont) 297 AddFont(pFormDict, pDocument, pFont, csNameTag); 298 299 return pFont; 300 } 301 302 class CFieldNameExtractor { 303 public: 304 explicit CFieldNameExtractor(const CFX_WideString& full_name) 305 : m_FullName(full_name) { 306 m_pCur = m_FullName.c_str(); 307 m_pEnd = m_pCur + m_FullName.GetLength(); 308 } 309 310 void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) { 311 pSubName = m_pCur; 312 while (m_pCur < m_pEnd && m_pCur[0] != L'.') 313 m_pCur++; 314 315 size = (FX_STRSIZE)(m_pCur - pSubName); 316 if (m_pCur < m_pEnd && m_pCur[0] == L'.') 317 m_pCur++; 318 } 319 320 protected: 321 CFX_WideString m_FullName; 322 const FX_WCHAR* m_pCur; 323 const FX_WCHAR* m_pEnd; 324 }; 325 326 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 327 typedef struct { 328 bool bFind; 329 LOGFONTA lf; 330 } PDF_FONTDATA; 331 332 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe, 333 NEWTEXTMETRICEX* lpntme, 334 DWORD FontType, 335 LPARAM lParam) { 336 if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@')) 337 return 1; 338 339 PDF_FONTDATA* pData = (PDF_FONTDATA*)lParam; 340 memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA)); 341 pData->bFind = true; 342 return 0; 343 } 344 345 bool RetrieveSpecificFont(LOGFONTA& lf) { 346 PDF_FONTDATA fd; 347 memset(&fd, 0, sizeof(PDF_FONTDATA)); 348 HDC hDC = ::GetDC(nullptr); 349 EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, 350 0); 351 ::ReleaseDC(nullptr, hDC); 352 if (fd.bFind) 353 memcpy(&lf, &fd.lf, sizeof(LOGFONTA)); 354 355 return fd.bFind; 356 } 357 358 bool RetrieveSpecificFont(uint8_t charSet, 359 uint8_t pitchAndFamily, 360 LPCSTR pcsFontName, 361 LOGFONTA& lf) { 362 memset(&lf, 0, sizeof(LOGFONTA)); 363 lf.lfCharSet = charSet; 364 lf.lfPitchAndFamily = pitchAndFamily; 365 if (pcsFontName) { 366 // TODO(dsinclair): Should this be strncpy? 367 // NOLINTNEXTLINE(runtime/printf) 368 strcpy(lf.lfFaceName, pcsFontName); 369 } 370 return RetrieveSpecificFont(lf); 371 } 372 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 373 374 int CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2) { 375 const FX_WCHAR* ptr1 = name1.c_str(); 376 const FX_WCHAR* ptr2 = name2.c_str(); 377 if (name1.GetLength() == name2.GetLength()) 378 return name1 == name2 ? 1 : 0; 379 380 int i = 0; 381 while (ptr1[i] == ptr2[i]) 382 i++; 383 if (i == name1.GetLength()) 384 return 2; 385 if (i == name2.GetLength()) 386 return 3; 387 return 0; 388 } 389 390 } // namespace 391 392 class CFieldTree { 393 public: 394 class Node { 395 public: 396 Node() : m_pField(nullptr) {} 397 Node(const CFX_WideString& short_name, CPDF_FormField* pField) 398 : m_ShortName(short_name), m_pField(pField) {} 399 ~Node() {} 400 401 void AddChildNode(Node* pNode) { m_Children.push_back(pNode); } 402 403 size_t GetChildrenCount() const { return m_Children.size(); } 404 405 Node* GetChildAt(size_t i) { return m_Children[i]; } 406 const Node* GetChildAt(size_t i) const { return m_Children[i]; } 407 408 CPDF_FormField* GetFieldAtIndex(size_t index) { 409 size_t nFieldsToGo = index; 410 return GetFieldInternal(&nFieldsToGo); 411 } 412 413 size_t CountFields() const { return CountFieldsInternal(0); } 414 415 void SetField(CPDF_FormField* pField) { m_pField = pField; } 416 417 CPDF_FormField* GetField() { return m_pField; } 418 const CPDF_FormField* GetField() const { return m_pField; } 419 420 const CFX_WideString& GetShortName() const { return m_ShortName; } 421 422 private: 423 CPDF_FormField* GetFieldInternal(size_t* pFieldsToGo) { 424 if (m_pField) { 425 if (*pFieldsToGo == 0) 426 return m_pField; 427 428 --*pFieldsToGo; 429 } 430 for (size_t i = 0; i < GetChildrenCount(); ++i) { 431 CPDF_FormField* pField = GetChildAt(i)->GetFieldInternal(pFieldsToGo); 432 if (pField) 433 return pField; 434 } 435 return nullptr; 436 } 437 438 size_t CountFieldsInternal(int nLevel) const { 439 if (nLevel > nMaxRecursion) 440 return 0; 441 442 size_t count = 0; 443 if (m_pField) 444 ++count; 445 446 for (size_t i = 0; i < GetChildrenCount(); ++i) 447 count += GetChildAt(i)->CountFieldsInternal(nLevel + 1); 448 return count; 449 } 450 451 std::vector<Node*> m_Children; 452 CFX_WideString m_ShortName; 453 CPDF_FormField* m_pField; 454 }; 455 456 CFieldTree(); 457 ~CFieldTree(); 458 459 void SetField(const CFX_WideString& full_name, CPDF_FormField* pField); 460 CPDF_FormField* GetField(const CFX_WideString& full_name); 461 void RemoveAll(); 462 463 Node* FindNode(const CFX_WideString& full_name); 464 Node* AddChild(Node* pParent, 465 const CFX_WideString& short_name, 466 CPDF_FormField* pField); 467 void RemoveNode(Node* pNode, int nLevel = 0); 468 469 Node* Lookup(Node* pParent, const CFX_WideString& short_name); 470 471 Node m_Root; 472 }; 473 474 CFieldTree::CFieldTree() {} 475 476 CFieldTree::~CFieldTree() { 477 RemoveAll(); 478 } 479 480 CFieldTree::Node* CFieldTree::AddChild(Node* pParent, 481 const CFX_WideString& short_name, 482 CPDF_FormField* pField) { 483 if (!pParent) 484 return nullptr; 485 486 Node* pNode = new Node(short_name, pField); 487 pParent->AddChildNode(pNode); 488 return pNode; 489 } 490 491 void CFieldTree::RemoveNode(Node* pNode, int nLevel) { 492 if (!pNode) 493 return; 494 495 if (nLevel <= nMaxRecursion) { 496 for (size_t i = 0; i < pNode->GetChildrenCount(); ++i) 497 RemoveNode(pNode->GetChildAt(i), nLevel + 1); 498 } 499 delete pNode; 500 } 501 502 CFieldTree::Node* CFieldTree::Lookup(Node* pParent, 503 const CFX_WideString& short_name) { 504 if (!pParent) 505 return nullptr; 506 507 for (size_t i = 0; i < pParent->GetChildrenCount(); ++i) { 508 Node* pNode = pParent->GetChildAt(i); 509 if (pNode->GetShortName() == short_name) 510 return pNode; 511 } 512 return nullptr; 513 } 514 515 void CFieldTree::RemoveAll() { 516 for (size_t i = 0; i < m_Root.GetChildrenCount(); ++i) 517 RemoveNode(m_Root.GetChildAt(i)); 518 } 519 520 void CFieldTree::SetField(const CFX_WideString& full_name, 521 CPDF_FormField* pField) { 522 if (full_name.IsEmpty()) 523 return; 524 525 CFieldNameExtractor name_extractor(full_name); 526 const FX_WCHAR* pName; 527 FX_STRSIZE nLength; 528 name_extractor.GetNext(pName, nLength); 529 Node* pNode = &m_Root; 530 Node* pLast = nullptr; 531 while (nLength > 0) { 532 pLast = pNode; 533 CFX_WideString name = CFX_WideString(pName, nLength); 534 pNode = Lookup(pLast, name); 535 if (!pNode) 536 pNode = AddChild(pLast, name, nullptr); 537 538 name_extractor.GetNext(pName, nLength); 539 } 540 if (pNode != &m_Root) 541 pNode->SetField(pField); 542 } 543 544 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) { 545 if (full_name.IsEmpty()) 546 return nullptr; 547 548 CFieldNameExtractor name_extractor(full_name); 549 const FX_WCHAR* pName; 550 FX_STRSIZE nLength; 551 name_extractor.GetNext(pName, nLength); 552 Node* pNode = &m_Root; 553 Node* pLast = nullptr; 554 while (nLength > 0 && pNode) { 555 pLast = pNode; 556 CFX_WideString name = CFX_WideString(pName, nLength); 557 pNode = Lookup(pLast, name); 558 name_extractor.GetNext(pName, nLength); 559 } 560 return pNode ? pNode->GetField() : nullptr; 561 } 562 563 CFieldTree::Node* CFieldTree::FindNode(const CFX_WideString& full_name) { 564 if (full_name.IsEmpty()) 565 return nullptr; 566 567 CFieldNameExtractor name_extractor(full_name); 568 const FX_WCHAR* pName; 569 FX_STRSIZE nLength; 570 name_extractor.GetNext(pName, nLength); 571 Node* pNode = &m_Root; 572 Node* pLast = nullptr; 573 while (nLength > 0 && pNode) { 574 pLast = pNode; 575 CFX_WideString name = CFX_WideString(pName, nLength); 576 pNode = Lookup(pLast, name); 577 name_extractor.GetNext(pName, nLength); 578 } 579 return pNode; 580 } 581 582 CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, 583 CPDF_Document* pDocument, 584 CFX_ByteString& csNameTag) { 585 uint8_t charSet = CPDF_InterForm::GetNativeCharSet(); 586 return AddNativeFont(pFormDict, pDocument, charSet, csNameTag); 587 } 588 589 // static 590 uint8_t CPDF_InterForm::GetNativeCharSet() { 591 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 592 uint8_t charSet = FXFONT_ANSI_CHARSET; 593 UINT iCodePage = ::GetACP(); 594 switch (iCodePage) { 595 case 932: 596 charSet = FXFONT_SHIFTJIS_CHARSET; 597 break; 598 case 936: 599 charSet = FXFONT_GB2312_CHARSET; 600 break; 601 case 950: 602 charSet = FXFONT_CHINESEBIG5_CHARSET; 603 break; 604 case 1252: 605 charSet = FXFONT_ANSI_CHARSET; 606 break; 607 case 874: 608 charSet = FXFONT_THAI_CHARSET; 609 break; 610 case 949: 611 charSet = FXFONT_HANGUL_CHARSET; 612 break; 613 case 1200: 614 charSet = FXFONT_ANSI_CHARSET; 615 break; 616 case 1250: 617 charSet = FXFONT_EASTEUROPE_CHARSET; 618 break; 619 case 1251: 620 charSet = FXFONT_RUSSIAN_CHARSET; 621 break; 622 case 1253: 623 charSet = FXFONT_GREEK_CHARSET; 624 break; 625 case 1254: 626 charSet = FXFONT_TURKISH_CHARSET; 627 break; 628 case 1255: 629 charSet = FXFONT_HEBREW_CHARSET; 630 break; 631 case 1256: 632 charSet = FXFONT_ARABIC_CHARSET; 633 break; 634 case 1257: 635 charSet = FXFONT_BALTIC_CHARSET; 636 break; 637 case 1258: 638 charSet = FXFONT_VIETNAMESE_CHARSET; 639 break; 640 case 1361: 641 charSet = FXFONT_JOHAB_CHARSET; 642 break; 643 } 644 return charSet; 645 #else 646 return 0; 647 #endif 648 } 649 650 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument) 651 : m_pDocument(pDocument), 652 m_pFormDict(nullptr), 653 m_pFieldTree(new CFieldTree), 654 m_pFormNotify(nullptr) { 655 CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); 656 if (!pRoot) 657 return; 658 659 m_pFormDict = pRoot->GetDictFor("AcroForm"); 660 if (!m_pFormDict) 661 return; 662 663 CPDF_Array* pFields = m_pFormDict->GetArrayFor("Fields"); 664 if (!pFields) 665 return; 666 667 for (size_t i = 0; i < pFields->GetCount(); ++i) 668 LoadField(pFields->GetDictAt(i), 0); 669 } 670 671 CPDF_InterForm::~CPDF_InterForm() { 672 m_ControlMap.clear(); 673 size_t nCount = m_pFieldTree->m_Root.CountFields(); 674 for (size_t i = 0; i < nCount; ++i) 675 delete m_pFieldTree->m_Root.GetFieldAtIndex(i); 676 } 677 678 bool CPDF_InterForm::s_bUpdateAP = true; 679 680 bool CPDF_InterForm::IsUpdateAPEnabled() { 681 return s_bUpdateAP; 682 } 683 684 void CPDF_InterForm::SetUpdateAP(bool bUpdateAP) { 685 s_bUpdateAP = bUpdateAP; 686 } 687 688 CFX_ByteString CPDF_InterForm::GenerateNewResourceName( 689 const CPDF_Dictionary* pResDict, 690 const FX_CHAR* csType, 691 int iMinLen, 692 const FX_CHAR* csPrefix) { 693 CFX_ByteString csStr = csPrefix; 694 CFX_ByteString csBType = csType; 695 if (csStr.IsEmpty()) { 696 if (csBType == "ExtGState") 697 csStr = "GS"; 698 else if (csBType == "ColorSpace") 699 csStr = "CS"; 700 else if (csBType == "Font") 701 csStr = "ZiTi"; 702 else 703 csStr = "Res"; 704 } 705 CFX_ByteString csTmp = csStr; 706 int iCount = csStr.GetLength(); 707 int m = 0; 708 if (iMinLen > 0) { 709 csTmp = ""; 710 while (m < iMinLen && m < iCount) 711 csTmp += csStr[m++]; 712 while (m < iMinLen) { 713 csTmp += '0' + m % 10; 714 m++; 715 } 716 } else { 717 m = iCount; 718 } 719 if (!pResDict) 720 return csTmp; 721 722 CPDF_Dictionary* pDict = pResDict->GetDictFor(csType); 723 if (!pDict) 724 return csTmp; 725 726 int num = 0; 727 CFX_ByteString bsNum; 728 while (true) { 729 CFX_ByteString csKey = csTmp + bsNum; 730 if (!pDict->KeyExist(csKey)) 731 return csKey; 732 if (m < iCount) 733 csTmp += csStr[m++]; 734 else 735 bsNum.Format("%d", num++); 736 737 m++; 738 } 739 return csTmp; 740 } 741 742 CPDF_Font* CPDF_InterForm::AddStandardFont(CPDF_Document* pDocument, 743 CFX_ByteString csFontName) { 744 if (!pDocument || csFontName.IsEmpty()) 745 return nullptr; 746 747 if (csFontName == "ZapfDingbats") 748 return pDocument->AddStandardFont(csFontName.c_str(), nullptr); 749 750 CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI); 751 return pDocument->AddStandardFont(csFontName.c_str(), &encoding); 752 } 753 754 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) { 755 CFX_ByteString csFontName; 756 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 757 LOGFONTA lf = {}; 758 if (charSet == FXFONT_ANSI_CHARSET) { 759 csFontName = "Helvetica"; 760 return csFontName; 761 } 762 bool bRet = false; 763 if (charSet == FXFONT_SHIFTJIS_CHARSET) { 764 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, 765 "MS Mincho", lf); 766 } else if (charSet == FXFONT_GB2312_CHARSET) { 767 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", 768 lf); 769 } else if (charSet == FXFONT_CHINESEBIG5_CHARSET) { 770 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", 771 lf); 772 } 773 if (!bRet) { 774 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, 775 "Arial Unicode MS", lf); 776 } 777 if (!bRet) { 778 bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, 779 "Microsoft Sans Serif", lf); 780 } 781 if (!bRet) { 782 bRet = 783 RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, nullptr, lf); 784 } 785 if (bRet) { 786 if (pLogFont) 787 memcpy(pLogFont, &lf, sizeof(LOGFONTA)); 788 789 csFontName = lf.lfFaceName; 790 return csFontName; 791 } 792 #endif 793 return csFontName; 794 } 795 796 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, 797 CPDF_Document* pDocument) { 798 if (!pDocument) 799 return nullptr; 800 801 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 802 LOGFONTA lf; 803 CFX_ByteString csFontName = GetNativeFont(charSet, &lf); 804 if (!csFontName.IsEmpty()) { 805 if (csFontName == "Helvetica") 806 return AddStandardFont(pDocument, csFontName); 807 return pDocument->AddWindowsFont(&lf, false, true); 808 } 809 #endif 810 return nullptr; 811 } 812 813 CPDF_Font* CPDF_InterForm::AddNativeFont(CPDF_Document* pDocument) { 814 return pDocument ? AddNativeFont(GetNativeCharSet(), pDocument) : nullptr; 815 } 816 817 bool CPDF_InterForm::ValidateFieldName( 818 CFX_WideString& csNewFieldName, 819 int iType, 820 const CPDF_FormField* pExcludedField, 821 const CPDF_FormControl* pExcludedControl) const { 822 if (csNewFieldName.IsEmpty()) 823 return false; 824 825 int iPos = 0; 826 int iLength = csNewFieldName.GetLength(); 827 CFX_WideString csSub; 828 while (true) { 829 while (iPos < iLength && 830 (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) { 831 iPos++; 832 } 833 if (iPos < iLength && !csSub.IsEmpty()) 834 csSub += L'.'; 835 while (iPos < iLength && csNewFieldName[iPos] != L'.') 836 csSub += csNewFieldName[iPos++]; 837 for (int i = csSub.GetLength() - 1; i > -1; i--) { 838 if (csSub[i] != L' ' && csSub[i] != L'.') 839 break; 840 841 csSub.SetAt(i, L'\0'); 842 } 843 size_t dwCount = m_pFieldTree->m_Root.CountFields(); 844 for (size_t m = 0; m < dwCount; ++m) { 845 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(m); 846 if (!pField) 847 continue; 848 if (pField == pExcludedField) { 849 if (!pExcludedControl || pField->CountControls() < 2) 850 continue; 851 } 852 CFX_WideString csFullName = pField->GetFullName(); 853 int iRet = CompareFieldName(csSub, csFullName); 854 if (iRet == 1) { 855 if (pField->GetFieldType() != iType) 856 return false; 857 } else if (iRet == 2 && csSub == csNewFieldName) { 858 if (csFullName[iPos] == L'.') 859 return false; 860 } else if (iRet == 3 && csSub == csNewFieldName) { 861 if (csNewFieldName[csFullName.GetLength()] == L'.') 862 return false; 863 } 864 } 865 if (iPos >= iLength) 866 break; 867 } 868 if (csSub.IsEmpty()) 869 return false; 870 871 csNewFieldName = csSub; 872 return true; 873 } 874 875 size_t CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) const { 876 if (csFieldName.IsEmpty()) 877 return m_pFieldTree->m_Root.CountFields(); 878 879 CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName); 880 return pNode ? pNode->CountFields() : 0; 881 } 882 883 CPDF_FormField* CPDF_InterForm::GetField( 884 uint32_t index, 885 const CFX_WideString& csFieldName) const { 886 if (csFieldName.IsEmpty()) 887 return m_pFieldTree->m_Root.GetFieldAtIndex(index); 888 889 CFieldTree::Node* pNode = m_pFieldTree->FindNode(csFieldName); 890 return pNode ? pNode->GetFieldAtIndex(index) : nullptr; 891 } 892 893 CPDF_FormField* CPDF_InterForm::GetFieldByDict( 894 CPDF_Dictionary* pFieldDict) const { 895 if (!pFieldDict) 896 return nullptr; 897 898 CFX_WideString csWName = FPDF_GetFullName(pFieldDict); 899 return m_pFieldTree->GetField(csWName); 900 } 901 902 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, 903 const CFX_PointF& point, 904 905 int* z_order) const { 906 CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArrayFor("Annots"); 907 if (!pAnnotList) 908 return nullptr; 909 910 for (size_t i = pAnnotList->GetCount(); i > 0; --i) { 911 size_t annot_index = i - 1; 912 CPDF_Dictionary* pAnnot = pAnnotList->GetDictAt(annot_index); 913 if (!pAnnot) 914 continue; 915 916 const auto it = m_ControlMap.find(pAnnot); 917 if (it == m_ControlMap.end()) 918 continue; 919 920 CPDF_FormControl* pControl = it->second.get(); 921 if (!pControl->GetRect().Contains(point)) 922 continue; 923 924 if (z_order) 925 *z_order = static_cast<int>(annot_index); 926 return pControl; 927 } 928 return nullptr; 929 } 930 931 CPDF_FormControl* CPDF_InterForm::GetControlByDict( 932 const CPDF_Dictionary* pWidgetDict) const { 933 const auto it = m_ControlMap.find(pWidgetDict); 934 return it != m_ControlMap.end() ? it->second.get() : nullptr; 935 } 936 937 bool CPDF_InterForm::NeedConstructAP() const { 938 return m_pFormDict && m_pFormDict->GetBooleanFor("NeedAppearances"); 939 } 940 941 int CPDF_InterForm::CountFieldsInCalculationOrder() { 942 if (!m_pFormDict) 943 return 0; 944 945 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); 946 return pArray ? pArray->GetCount() : 0; 947 } 948 949 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) { 950 if (!m_pFormDict || index < 0) 951 return nullptr; 952 953 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); 954 if (!pArray) 955 return nullptr; 956 957 CPDF_Dictionary* pElement = ToDictionary(pArray->GetDirectObjectAt(index)); 958 return pElement ? GetFieldByDict(pElement) : nullptr; 959 } 960 961 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) { 962 if (!m_pFormDict || !pField) 963 return -1; 964 965 CPDF_Array* pArray = m_pFormDict->GetArrayFor("CO"); 966 if (!pArray) 967 return -1; 968 969 for (size_t i = 0; i < pArray->GetCount(); i++) { 970 CPDF_Object* pElement = pArray->GetDirectObjectAt(i); 971 if (pElement == pField->m_pDict) 972 return i; 973 } 974 return -1; 975 } 976 977 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) { 978 return GetFont(m_pFormDict, m_pDocument, csNameTag); 979 } 980 981 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() const { 982 if (!m_pFormDict) 983 return CPDF_DefaultAppearance(); 984 return CPDF_DefaultAppearance(m_pFormDict->GetStringFor("DA")); 985 } 986 987 int CPDF_InterForm::GetFormAlignment() const { 988 return m_pFormDict ? m_pFormDict->GetIntegerFor("Q", 0) : 0; 989 } 990 991 bool CPDF_InterForm::ResetForm(const std::vector<CPDF_FormField*>& fields, 992 bool bIncludeOrExclude, 993 bool bNotify) { 994 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) 995 return false; 996 997 size_t nCount = m_pFieldTree->m_Root.CountFields(); 998 for (size_t i = 0; i < nCount; ++i) { 999 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); 1000 if (!pField) 1001 continue; 1002 1003 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) 1004 pField->ResetField(bNotify); 1005 } 1006 if (bNotify && m_pFormNotify) 1007 m_pFormNotify->AfterFormReset(this); 1008 return true; 1009 } 1010 1011 bool CPDF_InterForm::ResetForm(bool bNotify) { 1012 if (bNotify && m_pFormNotify && m_pFormNotify->BeforeFormReset(this) < 0) 1013 return false; 1014 1015 size_t nCount = m_pFieldTree->m_Root.CountFields(); 1016 for (size_t i = 0; i < nCount; ++i) { 1017 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); 1018 if (!pField) 1019 continue; 1020 1021 pField->ResetField(bNotify); 1022 } 1023 if (bNotify && m_pFormNotify) 1024 m_pFormNotify->AfterFormReset(this); 1025 return true; 1026 } 1027 1028 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) { 1029 if (nLevel > nMaxRecursion) 1030 return; 1031 if (!pFieldDict) 1032 return; 1033 1034 uint32_t dwParentObjNum = pFieldDict->GetObjNum(); 1035 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); 1036 if (!pKids) { 1037 AddTerminalField(pFieldDict); 1038 return; 1039 } 1040 1041 CPDF_Dictionary* pFirstKid = pKids->GetDictAt(0); 1042 if (!pFirstKid) 1043 return; 1044 1045 if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) { 1046 for (size_t i = 0; i < pKids->GetCount(); i++) { 1047 CPDF_Dictionary* pChildDict = pKids->GetDictAt(i); 1048 if (pChildDict) { 1049 if (pChildDict->GetObjNum() != dwParentObjNum) 1050 LoadField(pChildDict, nLevel + 1); 1051 } 1052 } 1053 } else { 1054 AddTerminalField(pFieldDict); 1055 } 1056 } 1057 1058 bool CPDF_InterForm::HasXFAForm() const { 1059 return m_pFormDict && m_pFormDict->GetArrayFor("XFA"); 1060 } 1061 1062 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) { 1063 CPDF_Dictionary* pPageDict = pPage->m_pFormDict; 1064 if (!pPageDict) 1065 return; 1066 1067 CPDF_Array* pAnnots = pPageDict->GetArrayFor("Annots"); 1068 if (!pAnnots) 1069 return; 1070 1071 for (size_t i = 0; i < pAnnots->GetCount(); i++) { 1072 CPDF_Dictionary* pAnnot = pAnnots->GetDictAt(i); 1073 if (pAnnot && pAnnot->GetStringFor("Subtype") == "Widget") 1074 LoadField(pAnnot, 0); 1075 } 1076 } 1077 1078 CPDF_FormField* CPDF_InterForm::AddTerminalField(CPDF_Dictionary* pFieldDict) { 1079 if (!pFieldDict->KeyExist("FT")) { 1080 // Key "FT" is required for terminal fields, it is also inheritable. 1081 CPDF_Dictionary* pParentDict = pFieldDict->GetDictFor("Parent"); 1082 if (!pParentDict || !pParentDict->KeyExist("FT")) 1083 return nullptr; 1084 } 1085 1086 CPDF_Dictionary* pDict = pFieldDict; 1087 CFX_WideString csWName = FPDF_GetFullName(pFieldDict); 1088 if (csWName.IsEmpty()) 1089 return nullptr; 1090 1091 CPDF_FormField* pField = nullptr; 1092 pField = m_pFieldTree->GetField(csWName); 1093 if (!pField) { 1094 CPDF_Dictionary* pParent = pFieldDict; 1095 if (!pFieldDict->KeyExist("T") && 1096 pFieldDict->GetStringFor("Subtype") == "Widget") { 1097 pParent = pFieldDict->GetDictFor("Parent"); 1098 if (!pParent) 1099 pParent = pFieldDict; 1100 } 1101 1102 if (pParent && pParent != pFieldDict && !pParent->KeyExist("FT")) { 1103 if (pFieldDict->KeyExist("FT")) { 1104 CPDF_Object* pFTValue = pFieldDict->GetDirectObjectFor("FT"); 1105 if (pFTValue) 1106 pParent->SetFor("FT", pFTValue->Clone()); 1107 } 1108 1109 if (pFieldDict->KeyExist("Ff")) { 1110 CPDF_Object* pFfValue = pFieldDict->GetDirectObjectFor("Ff"); 1111 if (pFfValue) 1112 pParent->SetFor("Ff", pFfValue->Clone()); 1113 } 1114 } 1115 1116 pField = new CPDF_FormField(this, pParent); 1117 CPDF_Object* pTObj = pDict->GetObjectFor("T"); 1118 if (ToReference(pTObj)) { 1119 std::unique_ptr<CPDF_Object> pClone = pTObj->CloneDirectObject(); 1120 if (pClone) 1121 pDict->SetFor("T", std::move(pClone)); 1122 else 1123 pDict->SetNewFor<CPDF_Name>("T", ""); 1124 } 1125 m_pFieldTree->SetField(csWName, pField); 1126 } 1127 1128 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); 1129 if (pKids) { 1130 for (size_t i = 0; i < pKids->GetCount(); i++) { 1131 CPDF_Dictionary* pKid = pKids->GetDictAt(i); 1132 if (!pKid) 1133 continue; 1134 if (pKid->GetStringFor("Subtype") != "Widget") 1135 continue; 1136 1137 AddControl(pField, pKid); 1138 } 1139 } else { 1140 if (pFieldDict->GetStringFor("Subtype") == "Widget") 1141 AddControl(pField, pFieldDict); 1142 } 1143 return pField; 1144 } 1145 1146 CPDF_FormControl* CPDF_InterForm::AddControl(CPDF_FormField* pField, 1147 CPDF_Dictionary* pWidgetDict) { 1148 const auto it = m_ControlMap.find(pWidgetDict); 1149 if (it != m_ControlMap.end()) 1150 return it->second.get(); 1151 1152 auto pNew = pdfium::MakeUnique<CPDF_FormControl>(pField, pWidgetDict); 1153 CPDF_FormControl* pControl = pNew.get(); 1154 m_ControlMap[pWidgetDict] = std::move(pNew); 1155 pField->m_ControlList.push_back(pControl); 1156 return pControl; 1157 } 1158 1159 bool CPDF_InterForm::CheckRequiredFields( 1160 const std::vector<CPDF_FormField*>* fields, 1161 bool bIncludeOrExclude) const { 1162 size_t nCount = m_pFieldTree->m_Root.CountFields(); 1163 for (size_t i = 0; i < nCount; ++i) { 1164 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); 1165 if (!pField) 1166 continue; 1167 1168 int32_t iType = pField->GetType(); 1169 if (iType == CPDF_FormField::PushButton || 1170 iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) { 1171 continue; 1172 } 1173 uint32_t dwFlags = pField->GetFieldFlags(); 1174 // TODO(thestig): Look up these magic numbers and add constants for them. 1175 if (dwFlags & FORMFLAG_NOEXPORT) 1176 continue; 1177 1178 bool bFind = true; 1179 if (fields) 1180 bFind = pdfium::ContainsValue(*fields, pField); 1181 if (bIncludeOrExclude == bFind) { 1182 CPDF_Dictionary* pFieldDict = pField->m_pDict; 1183 if ((dwFlags & FORMFLAG_REQUIRED) != 0 && 1184 pFieldDict->GetStringFor("V").IsEmpty()) { 1185 return false; 1186 } 1187 } 1188 } 1189 return true; 1190 } 1191 1192 std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF( 1193 const CFX_WideStringC& pdf_path, 1194 bool bSimpleFileSpec) const { 1195 std::vector<CPDF_FormField*> fields; 1196 size_t nCount = m_pFieldTree->m_Root.CountFields(); 1197 for (size_t i = 0; i < nCount; ++i) 1198 fields.push_back(m_pFieldTree->m_Root.GetFieldAtIndex(i)); 1199 return ExportToFDF(pdf_path, fields, true, bSimpleFileSpec); 1200 } 1201 1202 std::unique_ptr<CFDF_Document> CPDF_InterForm::ExportToFDF( 1203 const CFX_WideStringC& pdf_path, 1204 const std::vector<CPDF_FormField*>& fields, 1205 bool bIncludeOrExclude, 1206 bool bSimpleFileSpec) const { 1207 std::unique_ptr<CFDF_Document> pDoc = CFDF_Document::CreateNewDoc(); 1208 if (!pDoc) 1209 return nullptr; 1210 1211 CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDictFor("FDF"); 1212 if (!pdf_path.IsEmpty()) { 1213 if (bSimpleFileSpec) { 1214 CFX_WideString wsFilePath = CPDF_FileSpec::EncodeFileName(pdf_path); 1215 pMainDict->SetNewFor<CPDF_String>( 1216 "F", CFX_ByteString::FromUnicode(wsFilePath), false); 1217 pMainDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsFilePath), 1218 false); 1219 } else { 1220 CPDF_FileSpec filespec(pDoc->GetByteStringPool()); 1221 filespec.SetFileName(pdf_path); 1222 pMainDict->SetFor("F", pdfium::WrapUnique(filespec.GetObj())); 1223 } 1224 } 1225 1226 CPDF_Array* pFields = pMainDict->SetNewFor<CPDF_Array>("Fields"); 1227 size_t nCount = m_pFieldTree->m_Root.CountFields(); 1228 for (size_t i = 0; i < nCount; ++i) { 1229 CPDF_FormField* pField = m_pFieldTree->m_Root.GetFieldAtIndex(i); 1230 if (!pField || pField->GetType() == CPDF_FormField::PushButton) 1231 continue; 1232 1233 uint32_t dwFlags = pField->GetFieldFlags(); 1234 if (dwFlags & 0x04) 1235 continue; 1236 1237 if (bIncludeOrExclude == pdfium::ContainsValue(fields, pField)) { 1238 if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetStringFor("V").IsEmpty()) 1239 continue; 1240 1241 CFX_WideString fullname = FPDF_GetFullName(pField->GetFieldDict()); 1242 auto pFieldDict = 1243 pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool()); 1244 pFieldDict->SetNewFor<CPDF_String>("T", fullname); 1245 if (pField->GetType() == CPDF_FormField::CheckBox || 1246 pField->GetType() == CPDF_FormField::RadioButton) { 1247 CFX_WideString csExport = pField->GetCheckValue(false); 1248 CFX_ByteString csBExport = PDF_EncodeText(csExport); 1249 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt"); 1250 if (pOpt) 1251 pFieldDict->SetNewFor<CPDF_String>("V", csBExport, false); 1252 else 1253 pFieldDict->SetNewFor<CPDF_Name>("V", csBExport); 1254 } else { 1255 CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V"); 1256 if (pV) 1257 pFieldDict->SetFor("V", pV->CloneDirectObject()); 1258 } 1259 pFields->Add(std::move(pFieldDict)); 1260 } 1261 } 1262 return pDoc; 1263 } 1264 1265 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, 1266 const CFX_WideString& parent_name, 1267 bool bNotify, 1268 int nLevel) { 1269 CFX_WideString name; 1270 if (!parent_name.IsEmpty()) 1271 name = parent_name + L"."; 1272 1273 name += pFieldDict->GetUnicodeTextFor("T"); 1274 CPDF_Array* pKids = pFieldDict->GetArrayFor("Kids"); 1275 if (pKids) { 1276 for (size_t i = 0; i < pKids->GetCount(); i++) { 1277 CPDF_Dictionary* pKid = pKids->GetDictAt(i); 1278 if (!pKid) 1279 continue; 1280 if (nLevel <= nMaxRecursion) 1281 FDF_ImportField(pKid, name, bNotify, nLevel + 1); 1282 } 1283 return; 1284 } 1285 if (!pFieldDict->KeyExist("V")) 1286 return; 1287 1288 CPDF_FormField* pField = m_pFieldTree->GetField(name); 1289 if (!pField) 1290 return; 1291 1292 CFX_WideString csWValue = GetFieldValue(*pFieldDict, m_bsEncoding); 1293 int iType = pField->GetFieldType(); 1294 if (bNotify && m_pFormNotify) { 1295 if (iType == FIELDTYPE_LISTBOX) { 1296 if (m_pFormNotify->BeforeSelectionChange(pField, csWValue) < 0) 1297 return; 1298 } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) { 1299 if (m_pFormNotify->BeforeValueChange(pField, csWValue) < 0) 1300 return; 1301 } 1302 } 1303 pField->SetValue(csWValue); 1304 CPDF_FormField::Type eType = pField->GetType(); 1305 if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && 1306 pFieldDict->KeyExist("Opt")) { 1307 pField->m_pDict->SetFor( 1308 "Opt", pFieldDict->GetDirectObjectFor("Opt")->CloneDirectObject()); 1309 } 1310 1311 if (bNotify && m_pFormNotify) { 1312 if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) 1313 m_pFormNotify->AfterCheckedStatusChange(pField); 1314 else if (iType == FIELDTYPE_LISTBOX) 1315 m_pFormNotify->AfterSelectionChange(pField); 1316 else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) 1317 m_pFormNotify->AfterValueChange(pField); 1318 } 1319 } 1320 1321 void CPDF_InterForm::SetFormNotify(IPDF_FormNotify* pNotify) { 1322 m_pFormNotify = pNotify; 1323 } 1324