Home | History | Annotate | Download | only in fpdfdoc
      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