clang-format all pdfium code.
[pdfium.git] / core / src / fpdfdoc / doc_form.cpp
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 "../../include/fpdfdoc/fpdf_doc.h"
8 #include "doc_utils.h"
9
10 const int nMaxRecursion = 32;
11
12 class _CFieldNameExtractor {
13  public:
14   _CFieldNameExtractor(const CFX_WideString& full_name) {
15     m_pStart = full_name.c_str();
16     m_pEnd = m_pStart + full_name.GetLength();
17     m_pCur = m_pStart;
18   }
19   void GetNext(const FX_WCHAR*& pSubName, FX_STRSIZE& size) {
20     pSubName = m_pCur;
21     while (m_pCur < m_pEnd && m_pCur[0] != L'.') {
22       m_pCur++;
23     }
24     size = (FX_STRSIZE)(m_pCur - pSubName);
25     if (m_pCur < m_pEnd && m_pCur[0] == L'.') {
26       m_pCur++;
27     }
28   }
29
30  protected:
31   const FX_WCHAR* m_pStart;
32   const FX_WCHAR* m_pEnd;
33   const FX_WCHAR* m_pCur;
34 };
35 class CFieldTree {
36  public:
37   struct _Node {
38     _Node* parent;
39     CFX_PtrArray children;
40     CFX_WideString short_name;
41     CPDF_FormField* field_ptr;
42     int CountFields(int nLevel = 0) {
43       if (nLevel > nMaxRecursion) {
44         return 0;
45       }
46       if (field_ptr) {
47         return 1;
48       }
49       int count = 0;
50       for (int i = 0; i < children.GetSize(); i++) {
51         count += ((_Node*)children.GetAt(i))->CountFields(nLevel + 1);
52       }
53       return count;
54     }
55     CPDF_FormField* GetField(int* fields_to_go) {
56       if (field_ptr) {
57         if (*fields_to_go == 0) {
58           return field_ptr;
59         }
60         --*fields_to_go;
61         return NULL;
62       }
63       for (int i = 0; i < children.GetSize(); i++) {
64         _Node* pNode = (_Node*)children.GetAt(i);
65         CPDF_FormField* pField = pNode->GetField(fields_to_go);
66         if (pField) {
67           return pField;
68         }
69       }
70       return NULL;
71     }
72     CPDF_FormField* GetField(int index) {
73       int fields_to_go = index;
74       return GetField(&fields_to_go);
75     }
76   };
77   CFieldTree();
78   ~CFieldTree();
79   void SetField(const CFX_WideString& full_name, CPDF_FormField* field_ptr);
80   CPDF_FormField* GetField(const CFX_WideString& full_name);
81   CPDF_FormField* RemoveField(const CFX_WideString& full_name);
82   void RemoveAll();
83   _Node* FindNode(const CFX_WideString& full_name);
84   _Node* AddChild(_Node* pParent,
85                   const CFX_WideString& short_name,
86                   CPDF_FormField* field_ptr);
87   void RemoveNode(_Node* pNode, int nLevel = 0);
88   _Node* _Lookup(_Node* pParent, const CFX_WideString& short_name);
89   _Node m_Root;
90 };
91 CFieldTree::CFieldTree() {
92   m_Root.parent = NULL;
93   m_Root.field_ptr = NULL;
94 }
95 CFieldTree::~CFieldTree() {
96   RemoveAll();
97 }
98 CFieldTree::_Node* CFieldTree::AddChild(_Node* pParent,
99                                         const CFX_WideString& short_name,
100                                         CPDF_FormField* field_ptr) {
101   if (pParent == NULL) {
102     return NULL;
103   }
104   _Node* pNode = new _Node;
105   pNode->parent = pParent;
106   pNode->short_name = short_name;
107   pNode->field_ptr = field_ptr;
108   pParent->children.Add(pNode);
109   return pNode;
110 }
111 void CFieldTree::RemoveNode(_Node* pNode, int nLevel) {
112   if (pNode == NULL) {
113     return;
114   }
115   if (nLevel > nMaxRecursion) {
116     delete pNode;
117     return;
118   }
119   CFX_PtrArray& ptr_array = pNode->children;
120   for (int i = 0; i < ptr_array.GetSize(); i++) {
121     _Node* pChild = (_Node*)ptr_array[i];
122     RemoveNode(pChild, nLevel + 1);
123   }
124   delete pNode;
125 }
126 CFieldTree::_Node* CFieldTree::_Lookup(_Node* pParent,
127                                        const CFX_WideString& short_name) {
128   if (pParent == NULL) {
129     return NULL;
130   }
131   CFX_PtrArray& ptr_array = pParent->children;
132   for (int i = 0; i < ptr_array.GetSize(); i++) {
133     _Node* pNode = (_Node*)ptr_array[i];
134     if (pNode->short_name.GetLength() == short_name.GetLength() &&
135         FXSYS_memcmp(pNode->short_name.c_str(), short_name.c_str(),
136                      short_name.GetLength() * sizeof(FX_WCHAR)) == 0) {
137       return pNode;
138     }
139   }
140   return NULL;
141 }
142 void CFieldTree::RemoveAll() {
143   CFX_PtrArray& ptr_array = m_Root.children;
144   for (int i = 0; i < ptr_array.GetSize(); i++) {
145     _Node* pNode = (_Node*)ptr_array[i];
146     RemoveNode(pNode);
147   }
148 }
149 void CFieldTree::SetField(const CFX_WideString& full_name,
150                           CPDF_FormField* field_ptr) {
151   if (full_name == L"") {
152     return;
153   }
154   _CFieldNameExtractor name_extractor(full_name);
155   const FX_WCHAR* pName;
156   FX_STRSIZE nLength;
157   name_extractor.GetNext(pName, nLength);
158   _Node *pNode = &m_Root, *pLast = NULL;
159   while (nLength > 0) {
160     pLast = pNode;
161     CFX_WideString name = CFX_WideString(pName, nLength);
162     pNode = _Lookup(pLast, name);
163     if (pNode == NULL) {
164       pNode = AddChild(pLast, name, NULL);
165     }
166     name_extractor.GetNext(pName, nLength);
167   }
168   if (pNode != &m_Root) {
169     pNode->field_ptr = field_ptr;
170   }
171 }
172 CPDF_FormField* CFieldTree::GetField(const CFX_WideString& full_name) {
173   if (full_name == L"") {
174     return NULL;
175   }
176   _CFieldNameExtractor name_extractor(full_name);
177   const FX_WCHAR* pName;
178   FX_STRSIZE nLength;
179   name_extractor.GetNext(pName, nLength);
180   _Node *pNode = &m_Root, *pLast = NULL;
181   while (nLength > 0 && pNode) {
182     pLast = pNode;
183     CFX_WideString name = CFX_WideString(pName, nLength);
184     pNode = _Lookup(pLast, name);
185     name_extractor.GetNext(pName, nLength);
186   }
187   return pNode ? pNode->field_ptr : NULL;
188 }
189 CPDF_FormField* CFieldTree::RemoveField(const CFX_WideString& full_name) {
190   if (full_name == L"") {
191     return NULL;
192   }
193   _CFieldNameExtractor name_extractor(full_name);
194   const FX_WCHAR* pName;
195   FX_STRSIZE nLength;
196   name_extractor.GetNext(pName, nLength);
197   _Node *pNode = &m_Root, *pLast = NULL;
198   while (nLength > 0 && pNode) {
199     pLast = pNode;
200     CFX_WideString name = CFX_WideString(pName, nLength);
201     pNode = _Lookup(pLast, name);
202     name_extractor.GetNext(pName, nLength);
203   }
204   if (pNode && pNode != &m_Root) {
205     CFX_PtrArray& ptr_array = pLast->children;
206     for (int i = 0; i < ptr_array.GetSize(); i++) {
207       if (pNode == (_Node*)ptr_array[i]) {
208         ptr_array.RemoveAt(i);
209         break;
210       }
211     }
212     CPDF_FormField* pField = pNode->field_ptr;
213     RemoveNode(pNode);
214     return pField;
215   }
216   return NULL;
217 }
218 CFieldTree::_Node* CFieldTree::FindNode(const CFX_WideString& full_name) {
219   if (full_name == L"") {
220     return NULL;
221   }
222   _CFieldNameExtractor name_extractor(full_name);
223   const FX_WCHAR* pName;
224   FX_STRSIZE nLength;
225   name_extractor.GetNext(pName, nLength);
226   _Node *pNode = &m_Root, *pLast = NULL;
227   while (nLength > 0 && pNode) {
228     pLast = pNode;
229     CFX_WideString name = CFX_WideString(pName, nLength);
230     pNode = _Lookup(pLast, name);
231     name_extractor.GetNext(pName, nLength);
232   }
233   return pNode;
234 }
235 CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument, FX_BOOL bGenerateAP)
236     : CFX_PrivateData() {
237   m_pDocument = pDocument;
238   m_bGenerateAP = bGenerateAP;
239   m_pFormNotify = NULL;
240   m_bUpdated = FALSE;
241   m_pFieldTree = new CFieldTree;
242   CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
243   m_pFormDict = pRoot->GetDict("AcroForm");
244   if (m_pFormDict == NULL) {
245     return;
246   }
247   CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
248   if (pFields == NULL) {
249     return;
250   }
251   int count = pFields->GetCount();
252   for (int i = 0; i < count; i++) {
253     LoadField(pFields->GetDict(i));
254   }
255 }
256 CPDF_InterForm::~CPDF_InterForm() {
257   FX_POSITION pos = m_ControlMap.GetStartPosition();
258   while (pos) {
259     void* key;
260     void* value;
261     m_ControlMap.GetNextAssoc(pos, key, value);
262     delete (CPDF_FormControl*)value;
263   }
264   if (m_pFieldTree != NULL) {
265     int nCount = m_pFieldTree->m_Root.CountFields();
266     for (int i = 0; i < nCount; i++) {
267       CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
268       delete pField;
269     }
270     delete m_pFieldTree;
271   }
272 }
273 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE;
274 FX_BOOL CPDF_InterForm::UpdatingAPEnabled() {
275   return m_bUpdateAP;
276 }
277 void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP) {
278   m_bUpdateAP = bUpdateAP;
279 }
280 CFX_ByteString CPDF_InterForm::GenerateNewResourceName(
281     const CPDF_Dictionary* pResDict,
282     const FX_CHAR* csType,
283     int iMinLen,
284     const FX_CHAR* csPrefix) {
285   CFX_ByteString csStr = csPrefix;
286   CFX_ByteString csBType = csType;
287   if (csStr.IsEmpty()) {
288     if (csBType == "ExtGState") {
289       csStr = "GS";
290     } else if (csBType == "ColorSpace") {
291       csStr = "CS";
292     } else if (csBType == "Font") {
293       csStr = "ZiTi";
294     } else {
295       csStr = "Res";
296     }
297   }
298   CFX_ByteString csTmp = csStr;
299   int iCount = csStr.GetLength();
300   int m = 0;
301   if (iMinLen > 0) {
302     csTmp = "";
303     while (m < iMinLen && m < iCount) {
304       csTmp += csStr[m++];
305     }
306     while (m < iMinLen) {
307       csTmp += '0' + m % 10;
308       m++;
309     }
310   } else {
311     m = iCount;
312   }
313   if (pResDict == NULL) {
314     return csTmp;
315   }
316   CPDF_Dictionary* pDict = pResDict->GetDict(csType);
317   if (pDict == NULL) {
318     return csTmp;
319   }
320   int num = 0;
321   CFX_ByteString bsNum;
322   while (TRUE) {
323     if (!pDict->KeyExist(csTmp + bsNum)) {
324       return csTmp + bsNum;
325     }
326     if (m < iCount) {
327       csTmp += csStr[m++];
328     } else {
329       bsNum.Format("%d", num++);
330     }
331     m++;
332   }
333   return csTmp;
334 }
335 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
336 typedef struct _PDF_FONTDATA {
337   FX_BOOL bFind;
338   LOGFONTA lf;
339 } PDF_FONTDATA, FAR* LPDF_FONTDATA;
340 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXA* lpelfe,
341                                       NEWTEXTMETRICEX* lpntme,
342                                       DWORD FontType,
343                                       LPARAM lParam) {
344   if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@') != NULL) {
345     return 1;
346   }
347   LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam;
348   memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
349   pData->bFind = TRUE;
350   return 0;
351 }
352 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf) {
353   PDF_FONTDATA fd;
354   memset(&fd, 0, sizeof(PDF_FONTDATA));
355   HDC hDC = ::GetDC(NULL);
356   EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd,
357                       0);
358   ::ReleaseDC(NULL, hDC);
359   if (fd.bFind) {
360     memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
361   }
362   return fd.bFind;
363 }
364 static FX_BOOL RetrieveSpecificFont(uint8_t charSet,
365                                     uint8_t pitchAndFamily,
366                                     LPCSTR pcsFontName,
367                                     LOGFONTA& lf) {
368   memset(&lf, 0, sizeof(LOGFONTA));
369   lf.lfCharSet = charSet;
370   lf.lfPitchAndFamily = pitchAndFamily;
371   if (pcsFontName != NULL) {
372     strcpy(lf.lfFaceName, pcsFontName);
373   }
374   return RetrieveSpecificFont(lf);
375 }
376 static FX_BOOL RetrieveStockFont(int iFontObject,
377                                  uint8_t charSet,
378                                  LOGFONTA& lf) {
379   HFONT hFont = (HFONT)::GetStockObject(iFontObject);
380   if (hFont != NULL) {
381     memset(&lf, 0, sizeof(LOGFONTA));
382     int iRet = ::GetObject(hFont, sizeof(LOGFONTA), &lf);
383     if (iRet > 0 && (lf.lfCharSet == charSet || charSet == 255)) {
384       return RetrieveSpecificFont(lf);
385     }
386   }
387   return FALSE;
388 }
389 #endif
390 CPDF_Font* CPDF_InterForm::AddSystemDefaultFont(
391     const CPDF_Document* pDocument) {
392   if (pDocument == NULL) {
393     return NULL;
394   }
395   CPDF_Font* pFont = NULL;
396 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
397   LOGFONTA lf;
398   FX_BOOL bRet;
399   bRet = RetrieveStockFont(DEFAULT_GUI_FONT, 255, lf);
400   if (!bRet) {
401     bRet = RetrieveStockFont(SYSTEM_FONT, 255, lf);
402   }
403   if (bRet) {
404     pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
405   }
406 #endif
407   return pFont;
408 }
409 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument,
410                                          CFX_ByteString csFontName,
411                                          uint8_t iCharSet) {
412   if (pDocument == NULL || csFontName.IsEmpty()) {
413     return NULL;
414   }
415 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
416   if (iCharSet == 1) {
417     iCharSet = GetNativeCharSet();
418   }
419   HFONT hFont = ::CreateFontA(
420       0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
421       DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, csFontName.c_str());
422   if (hFont != NULL) {
423     LOGFONTA lf;
424     memset(&lf, 0, sizeof(LOGFONTA));
425     ::GetObjectA(hFont, sizeof(LOGFONTA), &lf);
426     ::DeleteObject(hFont);
427     if (strlen(lf.lfFaceName) > 0) {
428       return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
429     }
430   }
431 #endif
432   return NULL;
433 }
434 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument,
435                                          CFX_WideString csFontName,
436                                          uint8_t iCharSet) {
437   if (pDocument == NULL || csFontName.IsEmpty()) {
438     return NULL;
439   }
440 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
441   if (iCharSet == 1) {
442     iCharSet = GetNativeCharSet();
443   }
444   HFONT hFont = ::CreateFontW(
445       0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
446       DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, csFontName.c_str());
447   if (hFont != NULL) {
448     LOGFONTA lf;
449     memset(&lf, 0, sizeof(LOGFONTA));
450     ::GetObject(hFont, sizeof(LOGFONTA), &lf);
451     ::DeleteObject(hFont);
452     if (strlen(lf.lfFaceName) > 0) {
453       return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
454     }
455   }
456 #endif
457   return NULL;
458 }
459 CPDF_Font* CPDF_InterForm::AddStandardFont(const CPDF_Document* pDocument,
460                                            CFX_ByteString csFontName) {
461   if (pDocument == NULL || csFontName.IsEmpty()) {
462     return NULL;
463   }
464   CPDF_Font* pFont = NULL;
465   if (csFontName == "ZapfDingbats") {
466     pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, NULL);
467   } else {
468     CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
469     pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, &encoding);
470   }
471   return pFont;
472 }
473 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont) {
474   CFX_ByteString csFontName;
475 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
476   LOGFONTA lf;
477   FX_BOOL bRet;
478   if (charSet == ANSI_CHARSET) {
479     csFontName = "Helvetica";
480     return csFontName;
481   }
482   bRet = FALSE;
483   if (charSet == SHIFTJIS_CHARSET) {
484     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
485                                 "MS Mincho", lf);
486   } else if (charSet == GB2312_CHARSET) {
487     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun",
488                                 lf);
489   } else if (charSet == CHINESEBIG5_CHARSET) {
490     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU",
491                                 lf);
492   }
493   if (!bRet) {
494     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
495                                 "Arial Unicode MS", lf);
496   }
497   if (!bRet) {
498     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE,
499                                 "Microsoft Sans Serif", lf);
500   }
501   if (!bRet) {
502     bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, NULL, lf);
503   }
504   if (bRet) {
505     if (pLogFont != NULL) {
506       memcpy(pLogFont, &lf, sizeof(LOGFONTA));
507     }
508     csFontName = lf.lfFaceName;
509     return csFontName;
510   }
511 #endif
512   return csFontName;
513 }
514 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont) {
515 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
516   uint8_t charSet = GetNativeCharSet();
517   return GetNativeFont(charSet, pLogFont);
518 #else
519   return CFX_ByteString();
520 #endif
521 }
522 uint8_t CPDF_InterForm::GetNativeCharSet() {
523 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
524   uint8_t charSet = ANSI_CHARSET;
525   UINT iCodePage = ::GetACP();
526   switch (iCodePage) {
527     case 932:
528       charSet = SHIFTJIS_CHARSET;
529       break;
530     case 936:
531       charSet = GB2312_CHARSET;
532       break;
533     case 950:
534       charSet = CHINESEBIG5_CHARSET;
535       break;
536     case 1252:
537       charSet = ANSI_CHARSET;
538       break;
539     case 874:
540       charSet = THAI_CHARSET;
541       break;
542     case 949:
543       charSet = HANGUL_CHARSET;
544       break;
545     case 1200:
546       charSet = ANSI_CHARSET;
547       break;
548     case 1250:
549       charSet = EASTEUROPE_CHARSET;
550       break;
551     case 1251:
552       charSet = RUSSIAN_CHARSET;
553       break;
554     case 1253:
555       charSet = GREEK_CHARSET;
556       break;
557     case 1254:
558       charSet = TURKISH_CHARSET;
559       break;
560     case 1255:
561       charSet = HEBREW_CHARSET;
562       break;
563     case 1256:
564       charSet = ARABIC_CHARSET;
565       break;
566     case 1257:
567       charSet = BALTIC_CHARSET;
568       break;
569     case 1258:
570       charSet = VIETNAMESE_CHARSET;
571       break;
572     case 1361:
573       charSet = JOHAB_CHARSET;
574       break;
575   }
576   return charSet;
577 #else
578   return 0;
579 #endif
580 }
581 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet,
582                                          const CPDF_Document* pDocument) {
583   if (pDocument == NULL) {
584     return NULL;
585   }
586   CPDF_Font* pFont = NULL;
587 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
588   LOGFONTA lf;
589   CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
590   if (!csFontName.IsEmpty()) {
591     if (csFontName == "Helvetica") {
592       pFont = AddStandardFont(pDocument, csFontName);
593     } else {
594       pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
595     }
596   }
597 #endif
598   return pFont;
599 }
600 CPDF_Font* CPDF_InterForm::AddNativeFont(const CPDF_Document* pDocument) {
601   if (pDocument == NULL) {
602     return NULL;
603   }
604   CPDF_Font* pFont = NULL;
605   uint8_t charSet = GetNativeCharSet();
606   pFont = AddNativeFont(charSet, pDocument);
607   return pFont;
608 }
609 FX_BOOL CPDF_InterForm::ValidateFieldName(
610     CFX_WideString& csNewFieldName,
611     int iType,
612     const CPDF_FormField* pExcludedField,
613     const CPDF_FormControl* pExcludedControl) {
614   if (csNewFieldName.IsEmpty()) {
615     return FALSE;
616   }
617   int iPos = 0;
618   int iLength = csNewFieldName.GetLength();
619   CFX_WideString csSub;
620   while (TRUE) {
621     while (iPos < iLength &&
622            (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
623       iPos++;
624     }
625     if (iPos < iLength && !csSub.IsEmpty()) {
626       csSub += L'.';
627     }
628     while (iPos < iLength && csNewFieldName[iPos] != L'.') {
629       csSub += csNewFieldName[iPos++];
630     }
631     for (int i = csSub.GetLength() - 1; i > -1; i--) {
632       if (csSub[i] == L' ' || csSub[i] == L'.') {
633         csSub.SetAt(i, L'\0');
634       } else {
635         break;
636       }
637     }
638     FX_DWORD dwCount = m_pFieldTree->m_Root.CountFields();
639     for (FX_DWORD m = 0; m < dwCount; m++) {
640       CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m);
641       if (pField == NULL) {
642         continue;
643       }
644       if (pField == pExcludedField) {
645         if (pExcludedControl != NULL) {
646           if (pField->CountControls() < 2) {
647             continue;
648           }
649         } else {
650           continue;
651         }
652       }
653       CFX_WideString csFullName = pField->GetFullName();
654       int iRet = CompareFieldName(csSub, csFullName);
655       if (iRet == 1) {
656         if (pField->GetFieldType() != iType) {
657           return FALSE;
658         }
659       } else if (iRet == 2 && csSub == csNewFieldName) {
660         if (csFullName[iPos] == L'.') {
661           return FALSE;
662         }
663       } else if (iRet == 3 && csSub == csNewFieldName) {
664         if (csNewFieldName[csFullName.GetLength()] == L'.') {
665           return FALSE;
666         }
667       }
668     }
669     if (iPos >= iLength) {
670       break;
671     }
672   }
673   if (csSub.IsEmpty()) {
674     return FALSE;
675   }
676   csNewFieldName = csSub;
677   return TRUE;
678 }
679 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName,
680                                           int iType) {
681   return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
682 }
683 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField,
684                                           CFX_WideString& csNewFieldName) {
685   if (pField == NULL || csNewFieldName.IsEmpty()) {
686     return FALSE;
687   }
688   return ValidateFieldName(
689       csNewFieldName, ((CPDF_FormField*)pField)->GetFieldType(), pField, NULL);
690 }
691 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl,
692                                           CFX_WideString& csNewFieldName) {
693   if (pControl == NULL || csNewFieldName.IsEmpty()) {
694     return FALSE;
695   }
696   CPDF_FormField* pField = ((CPDF_FormControl*)pControl)->GetField();
697   return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField,
698                            pControl);
699 }
700 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1,
701                                      const CFX_ByteString& name2) {
702   const FX_CHAR* ptr1 = name1;
703   const FX_CHAR* ptr2 = name2;
704   if (name1.GetLength() == name2.GetLength()) {
705     return name1 == name2 ? 1 : 0;
706   }
707   int i = 0;
708   while (ptr1[i] == ptr2[i]) {
709     i++;
710   }
711   if (i == name1.GetLength()) {
712     return 2;
713   }
714   if (i == name2.GetLength()) {
715     return 3;
716   }
717   return 0;
718 }
719 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1,
720                                      const CFX_WideString& name2) {
721   const FX_WCHAR* ptr1 = name1.c_str();
722   const FX_WCHAR* ptr2 = name2.c_str();
723   if (name1.GetLength() == name2.GetLength()) {
724     return name1 == name2 ? 1 : 0;
725   }
726   int i = 0;
727   while (ptr1[i] == ptr2[i]) {
728     i++;
729   }
730   if (i == name1.GetLength()) {
731     return 2;
732   }
733   if (i == name2.GetLength()) {
734     return 3;
735   }
736   return 0;
737 }
738 FX_DWORD CPDF_InterForm::CountFields(const CFX_WideString& csFieldName) {
739   if (csFieldName.IsEmpty()) {
740     return (FX_DWORD)m_pFieldTree->m_Root.CountFields();
741   }
742   CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName);
743   if (pNode == NULL) {
744     return 0;
745   }
746   return pNode->CountFields();
747 }
748 CPDF_FormField* CPDF_InterForm::GetField(FX_DWORD index,
749                                          const CFX_WideString& csFieldName) {
750   if (csFieldName == L"") {
751     return m_pFieldTree->m_Root.GetField(index);
752   }
753   CFieldTree::_Node* pNode = m_pFieldTree->FindNode(csFieldName);
754   if (pNode == NULL) {
755     return NULL;
756   }
757   return pNode->GetField(index);
758 }
759 void CPDF_InterForm::GetAllFieldNames(CFX_WideStringArray& allFieldNames) {
760   allFieldNames.RemoveAll();
761   int nCount = m_pFieldTree->m_Root.CountFields();
762   for (int i = 0; i < nCount; i++) {
763     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
764     if (pField) {
765       CFX_WideString full_name = GetFullName(pField->GetFieldDict());
766       allFieldNames.Add(full_name);
767     }
768   }
769 }
770 FX_BOOL CPDF_InterForm::IsValidFormField(const void* pField) {
771   if (pField == NULL) {
772     return FALSE;
773   }
774   int nCount = m_pFieldTree->m_Root.CountFields();
775   for (int i = 0; i < nCount; i++) {
776     CPDF_FormField* pFormField = m_pFieldTree->m_Root.GetField(i);
777     if (pField == pFormField) {
778       return TRUE;
779     }
780   }
781   return FALSE;
782 }
783 CPDF_FormField* CPDF_InterForm::GetFieldByDict(
784     CPDF_Dictionary* pFieldDict) const {
785   if (pFieldDict == NULL) {
786     return NULL;
787   }
788   CFX_WideString csWName = GetFullName(pFieldDict);
789   return m_pFieldTree->GetField(csWName);
790 }
791 FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName) {
792   if (csFieldName.IsEmpty()) {
793     return (FX_DWORD)m_ControlMap.GetCount();
794   }
795   CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName);
796   if (pField == NULL) {
797     return 0;
798   }
799   return pField->m_ControlList.GetSize();
800 }
801 CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index,
802                                              CFX_WideString csFieldName) {
803   CPDF_FormField* pField = m_pFieldTree->GetField(csFieldName);
804   if (pField == NULL) {
805     return NULL;
806   }
807   if (index < (FX_DWORD)pField->m_ControlList.GetSize()) {
808     return (CPDF_FormControl*)pField->m_ControlList.GetAt(index);
809   }
810   return NULL;
811 }
812 FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl) {
813   if (pControl == NULL) {
814     return FALSE;
815   }
816   FX_POSITION pos = m_ControlMap.GetStartPosition();
817   while (pos) {
818     CPDF_Dictionary* pWidgetDict = NULL;
819     void* pFormControl = NULL;
820     m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, pFormControl);
821     if (pControl == pFormControl) {
822       return TRUE;
823     }
824   }
825   return FALSE;
826 }
827 int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const {
828   CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
829   if (pAnnotList == NULL) {
830     return 0;
831   }
832   int count = 0;
833   for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) {
834     CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
835     if (pAnnot == NULL) {
836       continue;
837     }
838     CPDF_FormControl* pControl;
839     if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
840       continue;
841     }
842     count++;
843   }
844   return count;
845 }
846 CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage,
847                                                  int index) const {
848   CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
849   if (pAnnotList == NULL) {
850     return NULL;
851   }
852   int count = 0;
853   for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i++) {
854     CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
855     if (pAnnot == NULL) {
856       continue;
857     }
858     CPDF_FormControl* pControl;
859     if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
860       continue;
861     }
862     if (index == count) {
863       return pControl;
864     }
865     count++;
866   }
867   return NULL;
868 }
869 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage,
870                                                     FX_FLOAT pdf_x,
871                                                     FX_FLOAT pdf_y) const {
872   CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
873   if (pAnnotList == NULL) {
874     return NULL;
875   }
876   for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i--) {
877     CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1);
878     if (pAnnot == NULL) {
879       continue;
880     }
881     CPDF_FormControl* pControl;
882     if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
883       continue;
884     }
885     CFX_FloatRect rect = pControl->GetRect();
886     if (rect.Contains(pdf_x, pdf_y)) {
887       return pControl;
888     }
889   }
890   return NULL;
891 }
892 CPDF_FormControl* CPDF_InterForm::GetControlByDict(
893     CPDF_Dictionary* pWidgetDict) const {
894   CPDF_FormControl* pControl = NULL;
895   m_ControlMap.Lookup(pWidgetDict, (void*&)pControl);
896   return pControl;
897 }
898 FX_DWORD CPDF_InterForm::CountInternalFields(
899     const CFX_WideString& csFieldName) const {
900   if (!m_pFormDict) {
901     return 0;
902   }
903   CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
904   if (!pArray) {
905     return 0;
906   }
907   if (csFieldName.IsEmpty()) {
908     return pArray->GetCount();
909   }
910   int iLength = csFieldName.GetLength();
911   int iPos = 0;
912   CPDF_Dictionary* pDict = NULL;
913   while (pArray != NULL) {
914     CFX_WideString csSub;
915     if (iPos < iLength && csFieldName[iPos] == L'.') {
916       iPos++;
917     }
918     while (iPos < iLength && csFieldName[iPos] != L'.') {
919       csSub += csFieldName[iPos++];
920     }
921     int iCount = pArray->GetCount();
922     FX_BOOL bFind = FALSE;
923     for (int i = 0; i < iCount; i++) {
924       pDict = pArray->GetDict(i);
925       if (pDict == NULL) {
926         continue;
927       }
928       CFX_WideString csT = pDict->GetUnicodeText("T");
929       if (csT == csSub) {
930         bFind = TRUE;
931         break;
932       }
933     }
934     if (!bFind) {
935       return 0;
936     }
937     if (iPos >= iLength) {
938       break;
939     }
940     pArray = pDict->GetArray("Kids");
941   }
942   if (!pDict) {
943     return 0;
944   }
945   pArray = pDict->GetArray("Kids");
946   return pArray ? pArray->GetCount() : 1;
947 }
948
949 CPDF_Dictionary* CPDF_InterForm::GetInternalField(
950     FX_DWORD index,
951     const CFX_WideString& csFieldName) const {
952   if (!m_pFormDict) {
953     return nullptr;
954   }
955   CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
956   if (!pArray) {
957     return nullptr;
958   }
959   if (csFieldName.IsEmpty()) {
960     return pArray->GetDict(index);
961   }
962   int iLength = csFieldName.GetLength();
963   int iPos = 0;
964   CPDF_Dictionary* pDict = NULL;
965   while (pArray != NULL) {
966     CFX_WideString csSub;
967     if (iPos < iLength && csFieldName[iPos] == L'.') {
968       iPos++;
969     }
970     while (iPos < iLength && csFieldName[iPos] != L'.') {
971       csSub += csFieldName[iPos++];
972     }
973     int iCount = pArray->GetCount();
974     FX_BOOL bFind = FALSE;
975     for (int i = 0; i < iCount; i++) {
976       pDict = pArray->GetDict(i);
977       if (pDict == NULL) {
978         continue;
979       }
980       CFX_WideString csT = pDict->GetUnicodeText("T");
981       if (csT == csSub) {
982         bFind = TRUE;
983         break;
984       }
985     }
986     if (!bFind) {
987       return NULL;
988     }
989     if (iPos >= iLength) {
990       break;
991     }
992     pArray = pDict->GetArray("Kids");
993   }
994   if (!pDict) {
995     return nullptr;
996   }
997   pArray = pDict->GetArray("Kids");
998   return pArray ? pArray->GetDict(index) : pDict;
999 }
1000 FX_BOOL CPDF_InterForm::NeedConstructAP() {
1001   if (m_pFormDict == NULL) {
1002     return FALSE;
1003   }
1004   return m_pFormDict->GetBoolean("NeedAppearances");
1005 }
1006 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP) {
1007   if (m_pFormDict == NULL) {
1008     InitInterFormDict(m_pFormDict, m_pDocument);
1009   }
1010   m_pFormDict->SetAtBoolean("NeedAppearances", bNeedAP);
1011   m_bGenerateAP = bNeedAP;
1012 }
1013 int CPDF_InterForm::CountFieldsInCalculationOrder() {
1014   if (m_pFormDict == NULL) {
1015     return 0;
1016   }
1017   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1018   if (pArray == NULL) {
1019     return 0;
1020   }
1021   return pArray->GetCount();
1022 }
1023 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index) {
1024   if (m_pFormDict == NULL || index < 0) {
1025     return NULL;
1026   }
1027   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1028   if (pArray == NULL) {
1029     return NULL;
1030   }
1031   CPDF_Object* pElement = pArray->GetElementValue(index);
1032   if (pElement != NULL && pElement->GetType() == PDFOBJ_DICTIONARY) {
1033     return GetFieldByDict((CPDF_Dictionary*)pElement);
1034   }
1035   return NULL;
1036 }
1037 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField) {
1038   if (m_pFormDict == NULL || pField == NULL) {
1039     return -1;
1040   }
1041   CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1042   if (pArray == NULL) {
1043     return -1;
1044   }
1045   for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
1046     CPDF_Object* pElement = pArray->GetElementValue(i);
1047     if (pElement == pField->m_pDict) {
1048       return i;
1049     }
1050   }
1051   return -1;
1052 }
1053 FX_DWORD CPDF_InterForm::CountFormFonts() {
1054   return CountInterFormFonts(m_pFormDict);
1055 }
1056 CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index,
1057                                        CFX_ByteString& csNameTag) {
1058   return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
1059 }
1060 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag) {
1061   return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1062 }
1063 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName,
1064                                        CFX_ByteString& csNameTag) {
1065   return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
1066 }
1067 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet,
1068                                              CFX_ByteString& csNameTag) {
1069   return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1070 }
1071 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag) {
1072   return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1073 }
1074 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont,
1075                                      CFX_ByteString& csNameTag) {
1076   return FindInterFormFont(m_pFormDict, pFont, csNameTag);
1077 }
1078 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName,
1079                                      CPDF_Font*& pFont,
1080                                      CFX_ByteString& csNameTag) {
1081   return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont,
1082                            csNameTag);
1083 }
1084 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont,
1085                                  CFX_ByteString& csNameTag) {
1086   AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
1087   m_bUpdated = TRUE;
1088 }
1089 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet,
1090                                              CFX_ByteString& csNameTag) {
1091   m_bUpdated = TRUE;
1092   return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1093 }
1094 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag) {
1095   m_bUpdated = TRUE;
1096   return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1097 }
1098 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont) {
1099   m_bUpdated = TRUE;
1100   RemoveInterFormFont(m_pFormDict, pFont);
1101 }
1102 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag) {
1103   m_bUpdated = TRUE;
1104   RemoveInterFormFont(m_pFormDict, csNameTag);
1105 }
1106 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance() {
1107   CFX_ByteString csDA;
1108   if (m_pFormDict == NULL) {
1109     return csDA;
1110   }
1111   csDA = m_pFormDict->GetString("DA");
1112   return csDA;
1113 }
1114 CPDF_Font* CPDF_InterForm::GetDefaultFormFont() {
1115   return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
1116 }
1117 int CPDF_InterForm::GetFormAlignment() {
1118   if (m_pFormDict == NULL) {
1119     return 0;
1120   }
1121   return m_pFormDict->GetInteger("Q", 0);
1122 }
1123 FX_BOOL CPDF_InterForm::ResetForm(const CFX_PtrArray& fields,
1124                                   FX_BOOL bIncludeOrExclude,
1125                                   FX_BOOL bNotify) {
1126   if (bNotify && m_pFormNotify != NULL) {
1127     int iRet = m_pFormNotify->BeforeFormReset(this);
1128     if (iRet < 0) {
1129       return FALSE;
1130     }
1131   }
1132   int nCount = m_pFieldTree->m_Root.CountFields();
1133   for (int i = 0; i < nCount; i++) {
1134     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1135     if (pField == NULL) {
1136       continue;
1137     }
1138     FX_BOOL bFind = FALSE;
1139     int iCount = fields.GetSize();
1140     for (int i = 0; i < iCount; i++) {
1141       if (pField == (CPDF_FormField*)fields[i]) {
1142         bFind = TRUE;
1143         break;
1144       }
1145     }
1146     if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1147       pField->ResetField(bNotify);
1148     }
1149   }
1150   if (bNotify && m_pFormNotify != NULL) {
1151     m_pFormNotify->AfterFormReset(this);
1152   }
1153   return TRUE;
1154 }
1155 FX_BOOL CPDF_InterForm::ResetForm(FX_BOOL bNotify) {
1156   if (bNotify && m_pFormNotify != NULL) {
1157     int iRet = m_pFormNotify->BeforeFormReset(this);
1158     if (iRet < 0) {
1159       return FALSE;
1160     }
1161   }
1162   int nCount = m_pFieldTree->m_Root.CountFields();
1163   for (int i = 0; i < nCount; i++) {
1164     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1165     if (pField == NULL) {
1166       continue;
1167     }
1168     pField->ResetField(bNotify);
1169   }
1170   if (bNotify && m_pFormNotify != NULL) {
1171     m_pFormNotify->AfterFormReset(this);
1172   }
1173   return TRUE;
1174 }
1175 void CPDF_InterForm::ReloadForm() {
1176   FX_POSITION pos = m_ControlMap.GetStartPosition();
1177   while (pos) {
1178     CPDF_Dictionary* pWidgetDict;
1179     CPDF_FormControl* pControl;
1180     m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, (void*&)pControl);
1181     delete pControl;
1182   }
1183   m_ControlMap.RemoveAll();
1184   int nCount = m_pFieldTree->m_Root.CountFields();
1185   for (int k = 0; k < nCount; k++) {
1186     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k);
1187     delete pField;
1188   }
1189   m_pFieldTree->RemoveAll();
1190   if (m_pFormDict == NULL) {
1191     return;
1192   }
1193   CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
1194   if (pFields == NULL) {
1195     return;
1196   }
1197   int iCount = pFields->GetCount();
1198   for (int i = 0; i < iCount; i++) {
1199     LoadField(pFields->GetDict(i));
1200   }
1201 }
1202 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel) {
1203   if (nLevel > nMaxRecursion) {
1204     return;
1205   }
1206   if (pFieldDict == NULL) {
1207     return;
1208   }
1209   FX_DWORD dwParentObjNum = pFieldDict->GetObjNum();
1210   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1211   if (!pKids) {
1212     AddTerminalField(pFieldDict);
1213     return;
1214   }
1215   CPDF_Dictionary* pFirstKid = pKids->GetDict(0);
1216   if (pFirstKid == NULL) {
1217     return;
1218   }
1219   if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
1220     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
1221       CPDF_Dictionary* pChildDict = pKids->GetDict(i);
1222       if (pChildDict) {
1223         if (pChildDict->GetObjNum() != dwParentObjNum) {
1224           LoadField(pChildDict, nLevel + 1);
1225         }
1226       }
1227     }
1228   } else {
1229     AddTerminalField(pFieldDict);
1230   }
1231 }
1232 FX_BOOL CPDF_InterForm::HasXFAForm() const {
1233   return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
1234 }
1235 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage) {
1236   ASSERT(pPage != NULL);
1237   CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
1238   if (pPageDict == NULL) {
1239     return;
1240   }
1241   CPDF_Array* pAnnots = pPageDict->GetArray(FX_BSTRC("Annots"));
1242   if (pAnnots == NULL) {
1243     return;
1244   }
1245   int iAnnotCount = pAnnots->GetCount();
1246   for (int i = 0; i < iAnnotCount; i++) {
1247     CPDF_Dictionary* pAnnot = pAnnots->GetDict(i);
1248     if (pAnnot != NULL && pAnnot->GetString(FX_BSTRC("Subtype")) == "Widget") {
1249       LoadField(pAnnot);
1250     }
1251   }
1252 }
1253 CPDF_FormField* CPDF_InterForm::AddTerminalField(
1254     const CPDF_Dictionary* pFieldDict) {
1255   if (!pFieldDict->KeyExist(FX_BSTRC("T"))) {
1256     return NULL;
1257   }
1258   CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFieldDict;
1259   CFX_WideString csWName = GetFullName(pDict);
1260   if (csWName.IsEmpty()) {
1261     return NULL;
1262   }
1263   CPDF_FormField* pField = NULL;
1264   pField = m_pFieldTree->GetField(csWName);
1265   if (pField == NULL) {
1266     CPDF_Dictionary* pParent = (CPDF_Dictionary*)pFieldDict;
1267     if (!pFieldDict->KeyExist(FX_BSTRC("T")) &&
1268         pFieldDict->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget")) {
1269       pParent = pFieldDict->GetDict(FX_BSTRC("Parent"));
1270       if (!pParent) {
1271         pParent = (CPDF_Dictionary*)pFieldDict;
1272       }
1273     }
1274     if (pParent && pParent != pFieldDict &&
1275         !pParent->KeyExist(FX_BSTRC("FT"))) {
1276       if (pFieldDict->KeyExist(FX_BSTRC("FT"))) {
1277         CPDF_Object* pFTValue = pFieldDict->GetElementValue(FX_BSTRC("FT"));
1278         if (pFTValue) {
1279           pParent->SetAt(FX_BSTRC("FT"), pFTValue->Clone());
1280         }
1281       }
1282       if (pFieldDict->KeyExist(FX_BSTRC("Ff"))) {
1283         CPDF_Object* pFfValue = pFieldDict->GetElementValue(FX_BSTRC("Ff"));
1284         if (pFfValue) {
1285           pParent->SetAt(FX_BSTRC("Ff"), pFfValue->Clone());
1286         }
1287       }
1288     }
1289     pField = new CPDF_FormField(this, pParent);
1290     CPDF_Object* pTObj = pDict->GetElement("T");
1291     if (pTObj && pTObj->GetType() == PDFOBJ_REFERENCE) {
1292       CPDF_Object* pClone = pTObj->Clone(TRUE);
1293       if (pClone) {
1294         pDict->SetAt("T", pClone);
1295       } else {
1296         pDict->SetAtName("T", "");
1297       }
1298     }
1299     m_pFieldTree->SetField(csWName, pField);
1300   }
1301   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1302   if (pKids == NULL) {
1303     if (pFieldDict->GetString("Subtype") == "Widget") {
1304       AddControl(pField, pFieldDict);
1305     }
1306   } else {
1307     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
1308       CPDF_Dictionary* pKid = pKids->GetDict(i);
1309       if (pKid == NULL) {
1310         continue;
1311       }
1312       if (pKid->GetString("Subtype") != "Widget") {
1313         continue;
1314       }
1315       AddControl(pField, pKid);
1316     }
1317   }
1318   return pField;
1319 }
1320 CPDF_FormControl* CPDF_InterForm::AddControl(
1321     const CPDF_FormField* pField,
1322     const CPDF_Dictionary* pWidgetDict) {
1323   void* rValue = NULL;
1324   if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) {
1325     return (CPDF_FormControl*)rValue;
1326   }
1327   CPDF_FormControl* pControl = new CPDF_FormControl(
1328       (CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict);
1329   m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl);
1330   ((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
1331   return pControl;
1332 }
1333 CPDF_FormField* CPDF_InterForm::CheckRequiredFields(
1334     const CFX_PtrArray* fields,
1335     FX_BOOL bIncludeOrExclude) const {
1336   int nCount = m_pFieldTree->m_Root.CountFields();
1337   for (int i = 0; i < nCount; i++) {
1338     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1339     if (pField == NULL) {
1340       continue;
1341     }
1342     int32_t iType = pField->GetType();
1343     if (iType == CPDF_FormField::PushButton ||
1344         iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
1345       continue;
1346     }
1347     FX_DWORD dwFlags = pField->GetFieldFlags();
1348     if (dwFlags & 0x04) {
1349       continue;
1350     }
1351     FX_BOOL bFind = TRUE;
1352     if (fields != NULL) {
1353       bFind = fields->Find(pField, 0) >= 0;
1354     }
1355     if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1356       CPDF_Dictionary* pFieldDict = pField->m_pDict;
1357       if ((dwFlags & 0x02) != 0 && pFieldDict->GetString("V").IsEmpty()) {
1358         return pField;
1359       }
1360     }
1361   }
1362   return NULL;
1363 }
1364 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path,
1365                                            FX_BOOL bSimpleFileSpec) const {
1366   CFX_PtrArray fields;
1367   int nCount = m_pFieldTree->m_Root.CountFields();
1368   for (int i = 0; i < nCount; i++) {
1369     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1370     fields.Add(pField);
1371   }
1372   return ExportToFDF(pdf_path, fields, TRUE, bSimpleFileSpec);
1373 }
1374 CFX_WideString FILESPEC_EncodeFileName(const CFX_WideStringC& filepath);
1375 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path,
1376                                            CFX_PtrArray& fields,
1377                                            FX_BOOL bIncludeOrExclude,
1378                                            FX_BOOL bSimpleFileSpec) const {
1379   CFDF_Document* pDoc = CFDF_Document::CreateNewDoc();
1380   if (pDoc == NULL) {
1381     return NULL;
1382   }
1383   CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDict("FDF");
1384   if (!pdf_path.IsEmpty()) {
1385     if (bSimpleFileSpec) {
1386       CFX_WideString wsFilePath = FILESPEC_EncodeFileName(pdf_path);
1387       pMainDict->SetAtString(FX_BSTRC("F"),
1388                              CFX_ByteString::FromUnicode(wsFilePath));
1389       pMainDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsFilePath));
1390     } else {
1391       CPDF_FileSpec filespec;
1392       filespec.SetFileName(pdf_path);
1393       pMainDict->SetAt("F", (CPDF_Object*)filespec);
1394     }
1395   }
1396   CPDF_Array* pFields = CPDF_Array::Create();
1397   if (pFields == NULL) {
1398     return NULL;
1399   }
1400   pMainDict->SetAt("Fields", pFields);
1401   int nCount = m_pFieldTree->m_Root.CountFields();
1402   for (int i = 0; i < nCount; i++) {
1403     CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1404     if (pField == NULL || pField->GetType() == CPDF_FormField::PushButton) {
1405       continue;
1406     }
1407     FX_DWORD dwFlags = pField->GetFieldFlags();
1408     if (dwFlags & 0x04) {
1409       continue;
1410     }
1411     FX_BOOL bFind = fields.Find(pField, 0) >= 0;
1412     if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1413       if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetString("V").IsEmpty()) {
1414         continue;
1415       }
1416       CFX_WideString fullname = GetFullName(pField->GetFieldDict());
1417       CPDF_Dictionary* pFieldDict = CPDF_Dictionary::Create();
1418       if (pFieldDict == NULL) {
1419         return NULL;
1420       }
1421       CPDF_String* pString = CPDF_String::Create(fullname);
1422       if (pString == NULL) {
1423         pFieldDict->Release();
1424         return NULL;
1425       }
1426       pFieldDict->SetAt("T", pString);
1427       if (pField->GetType() == CPDF_FormField::CheckBox ||
1428           pField->GetType() == CPDF_FormField::RadioButton) {
1429         CFX_WideString csExport = pField->GetCheckValue(FALSE);
1430         CFX_ByteString csBExport = PDF_EncodeText(csExport);
1431         CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
1432         if (pOpt == NULL) {
1433           pFieldDict->SetAtName("V", csBExport);
1434         } else {
1435           pFieldDict->SetAtString("V", csBExport);
1436         }
1437       } else {
1438         CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
1439         if (pV != NULL) {
1440           pFieldDict->SetAt("V", pV->Clone(TRUE));
1441         }
1442       }
1443       pFields->Add(pFieldDict);
1444     }
1445   }
1446   return pDoc;
1447 }
1448 const struct _SupportFieldEncoding {
1449   const FX_CHAR* m_name;
1450   int32_t m_codePage;
1451 } g_fieldEncoding[] = {
1452     {"BigFive", 950},
1453     {"GBK", 936},
1454     {"Shift-JIS", 932},
1455     {"UHC", 949},
1456 };
1457 static void FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary* pFieldDict,
1458                                       CFX_WideString& csValue,
1459                                       CFX_ByteString& bsEncoding) {
1460   ASSERT(pFieldDict != NULL);
1461   CFX_ByteString csBValue = pFieldDict->GetString("V");
1462   int32_t iCount = sizeof(g_fieldEncoding) / sizeof(g_fieldEncoding[0]);
1463   int32_t i = 0;
1464   for (; i < iCount; ++i)
1465     if (bsEncoding == g_fieldEncoding[i].m_name) {
1466       break;
1467     }
1468   if (i < iCount) {
1469     CFX_CharMap* pCharMap =
1470         CFX_CharMap::GetDefaultMapper(g_fieldEncoding[i].m_codePage);
1471     FXSYS_assert(pCharMap != NULL);
1472     csValue.ConvertFrom(csBValue, pCharMap);
1473     return;
1474   }
1475   CFX_ByteString csTemp = csBValue.Left(2);
1476   if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") {
1477     csValue = PDF_DecodeText(csBValue);
1478   } else {
1479     csValue = CFX_WideString::FromLocal(csBValue);
1480   }
1481 }
1482 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict,
1483                                      const CFX_WideString& parent_name,
1484                                      FX_BOOL bNotify,
1485                                      int nLevel) {
1486   CFX_WideString name;
1487   if (!parent_name.IsEmpty()) {
1488     name = parent_name + L".";
1489   }
1490   name += pFieldDict->GetUnicodeText("T");
1491   CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1492   if (pKids) {
1493     for (FX_DWORD i = 0; i < pKids->GetCount(); i++) {
1494       CPDF_Dictionary* pKid = pKids->GetDict(i);
1495       if (pKid == NULL) {
1496         continue;
1497       }
1498       if (nLevel <= nMaxRecursion) {
1499         FDF_ImportField(pKid, name, bNotify, nLevel + 1);
1500       }
1501     }
1502     return;
1503   }
1504   if (!pFieldDict->KeyExist("V")) {
1505     return;
1506   }
1507   CPDF_FormField* pField = m_pFieldTree->GetField(name);
1508   if (pField == NULL) {
1509     return;
1510   }
1511   CFX_WideString csWValue;
1512   FPDFDOC_FDF_GetFieldValue(pFieldDict, csWValue, m_bsEncoding);
1513   int iType = pField->GetFieldType();
1514   if (bNotify && m_pFormNotify != NULL) {
1515     int iRet = 0;
1516     if (iType == FIELDTYPE_LISTBOX) {
1517       iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue);
1518     } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1519       iRet = m_pFormNotify->BeforeValueChange(pField, csWValue);
1520     }
1521     if (iRet < 0) {
1522       return;
1523     }
1524   }
1525   CFX_ByteArray statusArray;
1526   if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1527     SaveCheckedFieldStatus(pField, statusArray);
1528   }
1529   pField->SetValue(csWValue);
1530   CPDF_FormField::Type eType = pField->GetType();
1531   if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) &&
1532       pFieldDict->KeyExist("Opt")) {
1533     pField->m_pDict->SetAt("Opt",
1534                            pFieldDict->GetElementValue("Opt")->Clone(TRUE));
1535   }
1536   if (bNotify && m_pFormNotify != NULL) {
1537     if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1538       m_pFormNotify->AfterCheckedStatusChange(pField, statusArray);
1539     } else if (iType == FIELDTYPE_LISTBOX) {
1540       m_pFormNotify->AfterSelectionChange(pField);
1541     } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1542       m_pFormNotify->AfterValueChange(pField);
1543     }
1544   }
1545   if (CPDF_InterForm::m_bUpdateAP) {
1546     pField->UpdateAP(NULL);
1547   }
1548 }
1549 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF,
1550                                       FX_BOOL bNotify) {
1551   if (pFDF == NULL) {
1552     return FALSE;
1553   }
1554   CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
1555   if (pMainDict == NULL) {
1556     return FALSE;
1557   }
1558   CPDF_Array* pFields = pMainDict->GetArray("Fields");
1559   if (pFields == NULL) {
1560     return FALSE;
1561   }
1562   m_bsEncoding = pMainDict->GetString(FX_BSTRC("Encoding"));
1563   if (bNotify && m_pFormNotify != NULL) {
1564     int iRet = m_pFormNotify->BeforeFormImportData(this);
1565     if (iRet < 0) {
1566       return FALSE;
1567     }
1568   }
1569   for (FX_DWORD i = 0; i < pFields->GetCount(); i++) {
1570     CPDF_Dictionary* pField = pFields->GetDict(i);
1571     if (pField == NULL) {
1572       continue;
1573     }
1574     FDF_ImportField(pField, L"", bNotify);
1575   }
1576   if (bNotify && m_pFormNotify != NULL) {
1577     m_pFormNotify->AfterFormImportData(this);
1578   }
1579   return TRUE;
1580 }
1581 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify) {
1582   m_pFormNotify = (CPDF_FormNotify*)pNotify;
1583 }
1584 int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext) {
1585   if (iCurPage < 0) {
1586     return -1;
1587   }
1588   int iPageCount = m_pDocument->GetPageCount();
1589   if (iCurPage >= iPageCount) {
1590     return -1;
1591   }
1592   int iNewPage = iCurPage;
1593   do {
1594     iNewPage += bNext ? 1 : -1;
1595     if (iNewPage >= iPageCount) {
1596       iNewPage = 0;
1597     }
1598     if (iNewPage < 0) {
1599       iNewPage = iPageCount - 1;
1600     }
1601     if (iNewPage == iCurPage) {
1602       break;
1603     }
1604     CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage);
1605     if (pPageDict == NULL) {
1606       continue;
1607     }
1608     CPDF_Array* pAnnots = pPageDict->GetArray("Annots");
1609     if (pAnnots == NULL) {
1610       continue;
1611     }
1612     FX_DWORD dwCount = pAnnots->GetCount();
1613     for (FX_DWORD i = 0; i < dwCount; i++) {
1614       CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i);
1615       if (pAnnotDict == NULL) {
1616         continue;
1617       }
1618       CPDF_FormControl* pControl = NULL;
1619       if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) {
1620         return iNewPage;
1621       }
1622     }
1623   } while (TRUE);
1624   return -1;
1625 }