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