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