Do some IWYU cleanups.
[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, FX_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 FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE;
284 FX_BOOL CPDF_InterForm::UpdatingAPEnabled()
285 {
286     return m_bUpdateAP;
287 }
288 void CPDF_InterForm::EnableUpdateAP(FX_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     FX_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     } else {
358         LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam;
359         memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
360         pData->bFind = TRUE;
361         return 0;
362     }
363 }
364 static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf)
365 {
366     PDF_FONTDATA fd;
367     memset(&fd, 0, sizeof(PDF_FONTDATA));
368     HDC hDC = ::GetDC(NULL);
369     EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, 0);
370     ::ReleaseDC(NULL, hDC);
371     if (fd.bFind) {
372         memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
373     }
374     return fd.bFind;
375 }
376 static FX_BOOL RetrieveSpecificFont(uint8_t charSet, uint8_t pitchAndFamily, LPCSTR pcsFontName, LOGFONTA& lf)
377 {
378     memset(&lf, 0, sizeof(LOGFONTA));
379     lf.lfCharSet = charSet;
380     lf.lfPitchAndFamily = pitchAndFamily;
381     if (pcsFontName != NULL) {
382         strcpy(lf.lfFaceName, pcsFontName);
383     }
384     return RetrieveSpecificFont(lf);
385 }
386 static FX_BOOL RetrieveStockFont(int iFontObject, uint8_t charSet, LOGFONTA& lf)
387 {
388     HFONT hFont = (HFONT)::GetStockObject(iFontObject);
389     if (hFont != NULL) {
390         memset(&lf, 0, sizeof(LOGFONTA));
391         int iRet = ::GetObject(hFont, sizeof(LOGFONTA), &lf);
392         if (iRet > 0 && (lf.lfCharSet == charSet || charSet == 255)) {
393             return RetrieveSpecificFont(lf);
394         }
395     }
396     return FALSE;
397 }
398 #endif
399 CPDF_Font* CPDF_InterForm::AddSystemDefaultFont(const CPDF_Document* pDocument)
400 {
401     if (pDocument == NULL) {
402         return NULL;
403     }
404     CPDF_Font* pFont = NULL;
405 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
406     LOGFONTA lf;
407     FX_BOOL bRet;
408     bRet = RetrieveStockFont(DEFAULT_GUI_FONT, 255, lf);
409     if (!bRet) {
410         bRet = RetrieveStockFont(SYSTEM_FONT, 255, lf);
411     }
412     if (bRet) {
413         pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
414     }
415 #endif
416     return pFont;
417 }
418 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_ByteString csFontName, uint8_t iCharSet)
419 {
420     if (pDocument == NULL || csFontName.IsEmpty()) {
421         return NULL;
422     }
423 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
424     if (iCharSet == 1) {
425         iCharSet = GetNativeCharSet();
426     }
427     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());
428     if (hFont != NULL) {
429         LOGFONTA lf;
430         memset(&lf, 0, sizeof(LOGFONTA));
431         ::GetObjectA(hFont, sizeof(LOGFONTA), &lf);
432         ::DeleteObject(hFont);
433         if (strlen(lf.lfFaceName) > 0) {
434             return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
435         }
436     }
437 #endif
438     return NULL;
439 }
440 CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_WideString csFontName, uint8_t iCharSet)
441 {
442     if (pDocument == NULL || csFontName.IsEmpty()) {
443         return NULL;
444     }
445 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
446     if (iCharSet == 1) {
447         iCharSet = GetNativeCharSet();
448     }
449     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());
450     if (hFont != NULL) {
451         LOGFONTA lf;
452         memset(&lf, 0, sizeof(LOGFONTA));
453         ::GetObject(hFont, sizeof(LOGFONTA), &lf);
454         ::DeleteObject(hFont);
455         if (strlen(lf.lfFaceName) > 0) {
456             return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
457         }
458     }
459 #endif
460     return NULL;
461 }
462 CPDF_Font* CPDF_InterForm::AddStandardFont(const CPDF_Document* pDocument, CFX_ByteString csFontName)
463 {
464     if (pDocument == NULL || csFontName.IsEmpty()) {
465         return NULL;
466     }
467     CPDF_Font* pFont = NULL;
468     if (csFontName == "ZapfDingbats") {
469         pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, NULL);
470     } else {
471         CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
472         pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, &encoding);
473     }
474     return pFont;
475 }
476 CFX_ByteString CPDF_InterForm::GetNativeFont(uint8_t charSet, void* pLogFont)
477 {
478     CFX_ByteString csFontName;
479 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
480     LOGFONTA lf;
481     FX_BOOL bRet;
482     if (charSet == ANSI_CHARSET) {
483         csFontName = "Helvetica";
484         return csFontName;
485     }
486     bRet = FALSE;
487     if (charSet == SHIFTJIS_CHARSET) {
488         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MS Mincho", lf);
489     } else if (charSet == GB2312_CHARSET) {
490         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", lf);
491     } else if (charSet == CHINESEBIG5_CHARSET) {
492         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", lf);
493     }
494     if (!bRet) {
495         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Arial Unicode MS", lf);
496     }
497     if (!bRet) {
498         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Microsoft Sans Serif", lf);
499     }
500     if (!bRet) {
501         bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, NULL, lf);
502     }
503     if (bRet) {
504         if (pLogFont != NULL) {
505             memcpy(pLogFont, &lf, sizeof(LOGFONTA));
506         }
507         csFontName = lf.lfFaceName;
508         return csFontName;
509     }
510 #endif
511     return csFontName;
512 }
513 CFX_ByteString CPDF_InterForm::GetNativeFont(void* pLogFont)
514 {
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 {
524 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
525     uint8_t charSet = ANSI_CHARSET;
526     UINT iCodePage = ::GetACP();
527     switch (iCodePage) {
528         case 932:
529             charSet = SHIFTJIS_CHARSET;
530             break;
531         case 936:
532             charSet = GB2312_CHARSET;
533             break;
534         case 950:
535             charSet = CHINESEBIG5_CHARSET;
536             break;
537         case 1252:
538             charSet = ANSI_CHARSET;
539             break;
540         case 874:
541             charSet = THAI_CHARSET;
542             break;
543         case 949:
544             charSet = HANGUL_CHARSET;
545             break;
546         case 1200:
547             charSet = ANSI_CHARSET;
548             break;
549         case 1250:
550             charSet = EASTEUROPE_CHARSET;
551             break;
552         case 1251:
553             charSet = RUSSIAN_CHARSET;
554             break;
555         case 1253:
556             charSet = GREEK_CHARSET;
557             break;
558         case 1254:
559             charSet = TURKISH_CHARSET;
560             break;
561         case 1255:
562             charSet = HEBREW_CHARSET;
563             break;
564         case 1256:
565             charSet = ARABIC_CHARSET;
566             break;
567         case 1257:
568             charSet = BALTIC_CHARSET;
569             break;
570         case 1258:
571             charSet = VIETNAMESE_CHARSET;
572             break;
573         case 1361:
574             charSet = JOHAB_CHARSET;
575             break;
576     }
577     return charSet;
578 #else
579     return 0;
580 #endif
581 }
582 CPDF_Font* CPDF_InterForm::AddNativeFont(uint8_t charSet, const CPDF_Document* pDocument)
583 {
584     if (pDocument == NULL) {
585         return NULL;
586     }
587     CPDF_Font* pFont = NULL;
588 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
589     LOGFONTA lf;
590     CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
591     if (!csFontName.IsEmpty()) {
592         if (csFontName == "Helvetica") {
593             pFont = AddStandardFont(pDocument, csFontName);
594         } else {
595             pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
596         }
597     }
598 #endif
599     return pFont;
600 }
601 CPDF_Font* CPDF_InterForm::AddNativeFont(const CPDF_Document* pDocument)
602 {
603     if (pDocument == NULL) {
604         return NULL;
605     }
606     CPDF_Font* pFont = NULL;
607     uint8_t charSet = GetNativeCharSet();
608     pFont = AddNativeFont(charSet, pDocument);
609     return pFont;
610 }
611 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType, const CPDF_FormField* pExcludedField, const CPDF_FormControl* pExcludedControl)
612 {
613     if (csNewFieldName.IsEmpty()) {
614         return FALSE;
615     }
616     int iPos = 0;
617     int iLength = csNewFieldName.GetLength();
618     CFX_WideString csSub;
619     while (TRUE) {
620         while (iPos < iLength && (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
621             iPos ++;
622         }
623         if (iPos < iLength && !csSub.IsEmpty()) {
624             csSub += L'.';
625         }
626         while (iPos < iLength && csNewFieldName[iPos] != L'.') {
627             csSub += csNewFieldName[iPos ++];
628         }
629         for (int i = csSub.GetLength() - 1; i > -1; i --) {
630             if (csSub[i] == L' ' || csSub[i] == L'.') {
631                 csSub.SetAt(i, L'\0');
632             } else {
633                 break;
634             }
635         }
636         FX_DWORD dwCount = m_pFieldTree->m_Root.CountFields();
637         for (FX_DWORD m = 0; m < dwCount; m ++) {
638             CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m);
639             if (pField == NULL) {
640                 continue;
641             }
642             if (pField == pExcludedField) {
643                 if (pExcludedControl != NULL) {
644                     if (pField->CountControls() < 2) {
645                         continue;
646                     }
647                 } else {
648                     continue;
649                 }
650             }
651             CFX_WideString csFullName = pField->GetFullName();
652             int iRet = CompareFieldName(csSub, csFullName);
653             if (iRet == 1) {
654                 if (pField->GetFieldType() != iType) {
655                     return FALSE;
656                 }
657             } else if (iRet == 2 && csSub == csNewFieldName) {
658                 if (csFullName[iPos] == L'.') {
659                     return FALSE;
660                 }
661             } else if (iRet == 3 && csSub == csNewFieldName) {
662                 if (csNewFieldName[csFullName.GetLength()] == L'.') {
663                     return FALSE;
664                 }
665             }
666         }
667         if (iPos >= iLength) {
668             break;
669         }
670     }
671     if (csSub.IsEmpty()) {
672         return FALSE;
673     }
674     csNewFieldName = csSub;
675     return TRUE;
676 }
677 FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType)
678 {
679     return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
680 }
681 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField, CFX_WideString& csNewFieldName)
682 {
683     if (pField == NULL || csNewFieldName.IsEmpty()) {
684         return FALSE;
685     }
686     return ValidateFieldName(csNewFieldName, ((CPDF_FormField*)pField)->GetFieldType(), pField, NULL);
687 }
688 FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl, CFX_WideString& csNewFieldName)
689 {
690     if (pControl == NULL || csNewFieldName.IsEmpty()) {
691         return FALSE;
692     }
693     CPDF_FormField* pField = ((CPDF_FormControl*)pControl)->GetField();
694     return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, pControl);
695 }
696 int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1, const CFX_ByteString& name2)
697 {
698     const FX_CHAR* ptr1 = name1;
699     const FX_CHAR* ptr2 = name2;
700     if (name1.GetLength() != name2.GetLength()) {
701         int i = 0;
702         while (ptr1[i] == ptr2[i]) {
703             i ++;
704         }
705         if (i == name1.GetLength()) {
706             return 2;
707         }
708         if (i == name2.GetLength()) {
709             return 3;
710         }
711         return 0;
712     } else {
713         return name1 == name2 ? 1 : 0;
714     }
715 }
716 int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2)
717 {
718     const FX_WCHAR* ptr1 = name1.c_str();
719     const FX_WCHAR* ptr2 = name2.c_str();
720     if (name1.GetLength() != name2.GetLength()) {
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     } else {
733         return name1 == name2 ? 1 : 0;
734     }
735 }
736 FX_DWORD CPDF_InterForm::CountFields(const CFX_WideString &csFieldName)
737 {
738     if (csFieldName.IsEmpty()) {
739         return (FX_DWORD)m_pFieldTree->m_Root.CountFields();
740     }
741     CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
742     if (pNode == NULL) {
743         return 0;
744     }
745     return pNode->CountFields();
746 }
747 CPDF_FormField* CPDF_InterForm::GetField(FX_DWORD index, const CFX_WideString &csFieldName)
748 {
749     if (csFieldName == L"") {
750         return m_pFieldTree->m_Root.GetField(index);
751     }
752     CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
753     if (pNode == NULL) {
754         return NULL;
755     }
756     return pNode->GetField(index);
757 }
758 void CPDF_InterForm::GetAllFieldNames(CFX_WideStringArray& allFieldNames)
759 {
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 {
772     if (pField == NULL) {
773         return FALSE;
774     }
775     int nCount = m_pFieldTree->m_Root.CountFields();
776     for (int i = 0; i < nCount; i++) {
777         CPDF_FormField *pFormField = m_pFieldTree->m_Root.GetField(i);
778         if (pField == pFormField) {
779             return TRUE;
780         }
781     }
782     return FALSE;
783 }
784 CPDF_FormField* CPDF_InterForm::GetFieldByDict(CPDF_Dictionary* pFieldDict) const
785 {
786     if (pFieldDict == NULL) {
787         return NULL;
788     }
789     CFX_WideString csWName = GetFullName(pFieldDict);
790     return m_pFieldTree->GetField(csWName);
791 }
792 FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName)
793 {
794     if (csFieldName.IsEmpty()) {
795         return (FX_DWORD)m_ControlMap.GetCount();
796     }
797     CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
798     if (pField == NULL) {
799         return 0;
800     }
801     return pField->m_ControlList.GetSize();
802 }
803 CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index, CFX_WideString csFieldName)
804 {
805     CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
806     if (pField == NULL) {
807         return NULL;
808     }
809     if (index < (FX_DWORD)pField->m_ControlList.GetSize()) {
810         return (CPDF_FormControl *)pField->m_ControlList.GetAt(index);
811     }
812     return NULL;
813 }
814 FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl)
815 {
816     if (pControl == NULL) {
817         return FALSE;
818     }
819     FX_POSITION pos = m_ControlMap.GetStartPosition();
820     while (pos) {
821         CPDF_Dictionary* pWidgetDict = NULL;
822         void* pFormControl = NULL;
823         m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, pFormControl);
824         if (pControl == pFormControl) {
825             return TRUE;
826         }
827     }
828     return FALSE;
829 }
830 int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const
831 {
832     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
833     if (pAnnotList == NULL) {
834         return 0;
835     }
836     int count = 0;
837     for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
838         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
839         if (pAnnot == NULL) {
840             continue;
841         }
842         CPDF_FormControl* pControl;
843         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
844             continue;
845         }
846         count ++;
847     }
848     return count;
849 }
850 CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage, int index) const
851 {
852     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
853     if (pAnnotList == NULL) {
854         return NULL;
855     }
856     int count = 0;
857     for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
858         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
859         if (pAnnot == NULL) {
860             continue;
861         }
862         CPDF_FormControl* pControl;
863         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
864             continue;
865         }
866         if (index == count) {
867             return pControl;
868         }
869         count ++;
870     }
871     return NULL;
872 }
873 CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y) const
874 {
875     CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
876     if (pAnnotList == NULL) {
877         return NULL;
878     }
879     for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i --) {
880         CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1);
881         if (pAnnot == NULL) {
882             continue;
883         }
884         CPDF_FormControl* pControl;
885         if (!m_ControlMap.Lookup(pAnnot, (void*&)pControl)) {
886             continue;
887         }
888         CFX_FloatRect rect = pControl->GetRect();
889         if (rect.Contains(pdf_x, pdf_y)) {
890             return pControl;
891         }
892     }
893     return NULL;
894 }
895 CPDF_FormControl* CPDF_InterForm::GetControlByDict(CPDF_Dictionary* pWidgetDict) const
896 {
897     CPDF_FormControl* pControl = NULL;
898     m_ControlMap.Lookup(pWidgetDict, (void*&)pControl);
899     return pControl;
900 }
901 FX_DWORD CPDF_InterForm::CountInternalFields(const CFX_WideString& csFieldName) const
902 {
903     if (m_pFormDict == NULL) {
904         return 0;
905     }
906     CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
907     if (pArray == NULL) {
908         return 0;
909     }
910     if (csFieldName.IsEmpty()) {
911         return pArray->GetCount();
912     } else {
913         int iLength = csFieldName.GetLength();
914         int iPos = 0;
915         CPDF_Dictionary* pDict = NULL;
916         while (pArray != NULL) {
917             CFX_WideString csSub;
918             if (iPos < iLength && csFieldName[iPos] == L'.') {
919                 iPos ++;
920             }
921             while (iPos < iLength && csFieldName[iPos] != L'.') {
922                 csSub += csFieldName[iPos ++];
923             }
924             int iCount = pArray->GetCount();
925             FX_BOOL bFind = FALSE;
926             for (int i = 0; i < iCount; i ++) {
927                 pDict = pArray->GetDict(i);
928                 if (pDict == NULL) {
929                     continue;
930                 }
931                 CFX_WideString csT = pDict->GetUnicodeText("T");
932                 if (csT == csSub) {
933                     bFind = TRUE;
934                     break;
935                 }
936             }
937             if (!bFind) {
938                 return 0;
939             }
940             if (iPos >= iLength) {
941                 break;
942             }
943             pArray = pDict->GetArray("Kids");
944         }
945         if (pDict == NULL) {
946             return 0;
947         } else {
948             pArray = pDict->GetArray("Kids");
949             if (pArray == NULL) {
950                 return 1;
951             } else {
952                 return pArray->GetCount();
953             }
954         }
955     }
956 }
957 CPDF_Dictionary* CPDF_InterForm::GetInternalField(FX_DWORD index, const CFX_WideString& csFieldName) const
958 {
959     if (m_pFormDict == NULL) {
960         return NULL;
961     }
962     CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
963     if (pArray == NULL) {
964         return 0;
965     }
966     if (csFieldName.IsEmpty()) {
967         return pArray->GetDict(index);
968     } else {
969         int iLength = csFieldName.GetLength();
970         int iPos = 0;
971         CPDF_Dictionary* pDict = NULL;
972         while (pArray != NULL) {
973             CFX_WideString csSub;
974             if (iPos < iLength && csFieldName[iPos] == L'.') {
975                 iPos ++;
976             }
977             while (iPos < iLength && csFieldName[iPos] != L'.') {
978                 csSub += csFieldName[iPos ++];
979             }
980             int iCount = pArray->GetCount();
981             FX_BOOL bFind = FALSE;
982             for (int i = 0; i < iCount; i ++) {
983                 pDict = pArray->GetDict(i);
984                 if (pDict == NULL) {
985                     continue;
986                 }
987                 CFX_WideString csT = pDict->GetUnicodeText("T");
988                 if (csT == csSub) {
989                     bFind = TRUE;
990                     break;
991                 }
992             }
993             if (!bFind) {
994                 return NULL;
995             }
996             if (iPos >= iLength) {
997                 break;
998             }
999             pArray = pDict->GetArray("Kids");
1000         }
1001         if (pDict == NULL) {
1002             return NULL;
1003         } else {
1004             pArray = pDict->GetArray("Kids");
1005             if (pArray == NULL) {
1006                 return pDict;
1007             } else {
1008                 return pArray->GetDict(index);
1009             }
1010         }
1011     }
1012 }
1013 FX_BOOL CPDF_InterForm::NeedConstructAP()
1014 {
1015     if (m_pFormDict == NULL) {
1016         return FALSE;
1017     }
1018     return m_pFormDict->GetBoolean("NeedAppearances");
1019 }
1020 void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP)
1021 {
1022     if (m_pFormDict == NULL) {
1023         InitInterFormDict(m_pFormDict, m_pDocument);
1024     }
1025     m_pFormDict->SetAtBoolean("NeedAppearances", bNeedAP);
1026     m_bGenerateAP = bNeedAP;
1027 }
1028 int CPDF_InterForm::CountFieldsInCalculationOrder()
1029 {
1030     if (m_pFormDict == NULL) {
1031         return 0;
1032     }
1033     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1034     if (pArray == NULL) {
1035         return 0;
1036     }
1037     return pArray->GetCount();
1038 }
1039 CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index)
1040 {
1041     if (m_pFormDict == NULL || index < 0) {
1042         return NULL;
1043     }
1044     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1045     if (pArray == NULL) {
1046         return NULL;
1047     }
1048     CPDF_Object* pElement = pArray->GetElementValue(index);
1049     if (pElement != NULL && pElement->GetType() == PDFOBJ_DICTIONARY) {
1050         return GetFieldByDict((CPDF_Dictionary*)pElement);
1051     }
1052     return NULL;
1053 }
1054 int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField)
1055 {
1056     if (m_pFormDict == NULL || pField == NULL) {
1057         return -1;
1058     }
1059     CPDF_Array* pArray = m_pFormDict->GetArray("CO");
1060     if (pArray == NULL) {
1061         return -1;
1062     }
1063     for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
1064         CPDF_Object* pElement = pArray->GetElementValue(i);
1065         if (pElement == pField->m_pDict) {
1066             return i;
1067         }
1068     }
1069     return -1;
1070 }
1071 FX_DWORD CPDF_InterForm::CountFormFonts()
1072 {
1073     return CountInterFormFonts(m_pFormDict);
1074 }
1075 CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index, CFX_ByteString& csNameTag)
1076 {
1077     return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
1078 }
1079 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag)
1080 {
1081     return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1082 }
1083 CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, CFX_ByteString& csNameTag)
1084 {
1085     return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
1086 }
1087 CPDF_Font* CPDF_InterForm::GetNativeFormFont(uint8_t charSet, CFX_ByteString& csNameTag)
1088 {
1089     return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1090 }
1091 CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag)
1092 {
1093     return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1094 }
1095 FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1096 {
1097     return FindInterFormFont(m_pFormDict, pFont, csNameTag);
1098 }
1099 FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag)
1100 {
1101     return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont, csNameTag);
1102 }
1103 void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
1104 {
1105     AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
1106     m_bUpdated = TRUE;
1107 }
1108 CPDF_Font* CPDF_InterForm::AddNativeFormFont(uint8_t charSet, CFX_ByteString& csNameTag)
1109 {
1110     m_bUpdated = TRUE;
1111     return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
1112 }
1113 CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag)
1114 {
1115     m_bUpdated = TRUE;
1116     return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
1117 }
1118 void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont)
1119 {
1120     m_bUpdated = TRUE;
1121     RemoveInterFormFont(m_pFormDict, pFont);
1122 }
1123 void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag)
1124 {
1125     m_bUpdated = TRUE;
1126     RemoveInterFormFont(m_pFormDict, csNameTag);
1127 }
1128 CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance()
1129 {
1130     CFX_ByteString csDA;
1131     if (m_pFormDict == NULL) {
1132         return csDA;
1133     }
1134     csDA = m_pFormDict->GetString("DA");
1135     return csDA;
1136 }
1137 CPDF_Font* CPDF_InterForm::GetDefaultFormFont()
1138 {
1139     return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
1140 }
1141 int CPDF_InterForm::GetFormAlignment()
1142 {
1143     if (m_pFormDict == NULL) {
1144         return 0;
1145     }
1146     return m_pFormDict->GetInteger("Q", 0);
1147 }
1148 FX_BOOL CPDF_InterForm::ResetForm(const CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bNotify)
1149 {
1150     if (bNotify && m_pFormNotify != NULL) {
1151         int iRet = m_pFormNotify->BeforeFormReset(this);
1152         if (iRet < 0) {
1153             return FALSE;
1154         }
1155     }
1156     int nCount = m_pFieldTree->m_Root.CountFields();
1157     for (int i = 0; i < nCount; i++) {
1158         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1159         if (pField == NULL) {
1160             continue;
1161         }
1162         FX_BOOL bFind = FALSE;
1163         int iCount = fields.GetSize();
1164         for (int i = 0; i < iCount; i ++) {
1165             if (pField == (CPDF_FormField*)fields[i]) {
1166                 bFind = TRUE;
1167                 break;
1168             }
1169         }
1170         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1171             pField->ResetField(bNotify);
1172         }
1173     }
1174     if (bNotify && m_pFormNotify != NULL) {
1175         m_pFormNotify->AfterFormReset(this);
1176     }
1177     return TRUE;
1178 }
1179 FX_BOOL CPDF_InterForm::ResetForm(FX_BOOL bNotify)
1180 {
1181     if (bNotify && m_pFormNotify != NULL) {
1182         int iRet = m_pFormNotify->BeforeFormReset(this);
1183         if (iRet < 0) {
1184             return FALSE;
1185         }
1186     }
1187     int nCount = m_pFieldTree->m_Root.CountFields();
1188     for (int i = 0; i < nCount; i++) {
1189         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1190         if (pField == NULL) {
1191             continue;
1192         }
1193         pField->ResetField(bNotify);
1194     }
1195     if (bNotify && m_pFormNotify != NULL) {
1196         m_pFormNotify->AfterFormReset(this);
1197     }
1198     return TRUE;
1199 }
1200 void CPDF_InterForm::ReloadForm()
1201 {
1202     FX_POSITION pos = m_ControlMap.GetStartPosition();
1203     while (pos) {
1204         CPDF_Dictionary* pWidgetDict;
1205         CPDF_FormControl* pControl;
1206         m_ControlMap.GetNextAssoc(pos, (void*&)pWidgetDict, (void*&)pControl);
1207         delete pControl;
1208     }
1209     m_ControlMap.RemoveAll();
1210     int nCount = m_pFieldTree->m_Root.CountFields();
1211     for (int k = 0; k < nCount; k ++) {
1212         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k);
1213         delete pField;
1214     }
1215     m_pFieldTree->RemoveAll();
1216     if (m_pFormDict == NULL) {
1217         return;
1218     }
1219     CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
1220     if (pFields == NULL) {
1221         return;
1222     }
1223     int iCount = pFields->GetCount();
1224     for (int i = 0; i < iCount; i ++) {
1225         LoadField(pFields->GetDict(i));
1226     }
1227 }
1228 void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel)
1229 {
1230     if (nLevel > nMaxRecursion) {
1231         return;
1232     }
1233     if (pFieldDict == NULL) {
1234         return;
1235     }
1236     FX_DWORD dwParentObjNum = pFieldDict->GetObjNum();
1237     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1238     if (!pKids) {
1239         AddTerminalField(pFieldDict);
1240         return;
1241     }
1242     CPDF_Dictionary* pFirstKid = pKids->GetDict(0);
1243     if (pFirstKid == NULL) {
1244         return;
1245     }
1246     if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
1247         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1248             CPDF_Dictionary * pChildDict = pKids->GetDict(i);
1249             if (pChildDict) {
1250                 if (pChildDict->GetObjNum() != dwParentObjNum) {
1251                     LoadField(pChildDict, nLevel + 1);
1252                 }
1253             }
1254         }
1255     } else {
1256         AddTerminalField(pFieldDict);
1257     }
1258 }
1259 FX_BOOL CPDF_InterForm::HasXFAForm() const
1260 {
1261     return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
1262 }
1263 void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage)
1264 {
1265     ASSERT(pPage != NULL);
1266     CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
1267     if (pPageDict == NULL) {
1268         return;
1269     }
1270     CPDF_Array* pAnnots = pPageDict->GetArray(FX_BSTRC("Annots"));
1271     if (pAnnots == NULL) {
1272         return;
1273     }
1274     int iAnnotCount = pAnnots->GetCount();
1275     for (int i = 0; i < iAnnotCount; i++) {
1276         CPDF_Dictionary* pAnnot = pAnnots->GetDict(i);
1277         if (pAnnot != NULL && pAnnot->GetString(FX_BSTRC("Subtype")) == "Widget") {
1278             LoadField(pAnnot);
1279         }
1280     }
1281 }
1282 CPDF_FormField* CPDF_InterForm::AddTerminalField(const CPDF_Dictionary* pFieldDict)
1283 {
1284     if (!pFieldDict->KeyExist(FX_BSTRC("T"))) {
1285         return NULL;
1286     }
1287     CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFieldDict;
1288     CFX_WideString csWName = GetFullName(pDict);
1289     if (csWName.IsEmpty()) {
1290         return NULL;
1291     }
1292     CPDF_FormField* pField = NULL;
1293     pField = m_pFieldTree->GetField(csWName);
1294     if (pField == NULL) {
1295         CPDF_Dictionary *pParent = (CPDF_Dictionary*)pFieldDict;
1296         if (!pFieldDict->KeyExist(FX_BSTRC("T")) &&
1297             pFieldDict->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget")) {
1298             pParent = pFieldDict->GetDict(FX_BSTRC("Parent"));
1299             if (!pParent) {
1300                 pParent = (CPDF_Dictionary*)pFieldDict;
1301             }
1302         }
1303         if (pParent && pParent != pFieldDict && !pParent->KeyExist(FX_BSTRC("FT"))) {
1304             if (pFieldDict->KeyExist(FX_BSTRC("FT"))) {
1305                 CPDF_Object *pFTValue = pFieldDict->GetElementValue(FX_BSTRC("FT"));
1306                 if (pFTValue) {
1307                     pParent->SetAt(FX_BSTRC("FT"), pFTValue->Clone());
1308                 }
1309             }
1310             if (pFieldDict->KeyExist(FX_BSTRC("Ff"))) {
1311                 CPDF_Object *pFfValue = pFieldDict->GetElementValue(FX_BSTRC("Ff"));
1312                 if (pFfValue) {
1313                     pParent->SetAt(FX_BSTRC("Ff"), pFfValue->Clone());
1314                 }
1315             }
1316         }
1317         pField = new CPDF_FormField(this, pParent);
1318         CPDF_Object* pTObj = pDict->GetElement("T");
1319         if (pTObj && pTObj->GetType() == PDFOBJ_REFERENCE) {
1320             CPDF_Object* pClone = pTObj->Clone(TRUE);
1321             if (pClone) {
1322                 pDict->SetAt("T", pClone);
1323             } else {
1324                 pDict->SetAtName("T", "");
1325             }
1326         }
1327         m_pFieldTree->SetField(csWName, pField);
1328     }
1329     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1330     if (pKids == NULL) {
1331         if (pFieldDict->GetString("Subtype") == "Widget") {
1332             AddControl(pField, pFieldDict);
1333         }
1334     } else {
1335         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1336             CPDF_Dictionary* pKid = pKids->GetDict(i);
1337             if (pKid == NULL) {
1338                 continue;
1339             }
1340             if (pKid->GetString("Subtype") != "Widget") {
1341                 continue;
1342             }
1343             AddControl(pField, pKid);
1344         }
1345     }
1346     return pField;
1347 }
1348 CPDF_FormControl* CPDF_InterForm::AddControl(const CPDF_FormField* pField, const CPDF_Dictionary* pWidgetDict)
1349 {
1350     void *rValue = NULL;
1351     if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) {
1352         return (CPDF_FormControl*)rValue;
1353     }
1354     CPDF_FormControl* pControl = new CPDF_FormControl((CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict);
1355     m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl);
1356     ((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
1357     return pControl;
1358 }
1359 CPDF_FormField* CPDF_InterForm::CheckRequiredFields(const CFX_PtrArray *fields, FX_BOOL bIncludeOrExclude) const
1360 {
1361     int nCount = m_pFieldTree->m_Root.CountFields();
1362     for (int i = 0; i < nCount; i++) {
1363         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1364         if (pField == NULL) {
1365             continue;
1366         }
1367         int32_t iType = pField->GetType();
1368         if (iType == CPDF_FormField::PushButton || iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
1369             continue;
1370         }
1371         FX_DWORD dwFlags = pField->GetFieldFlags();
1372         if (dwFlags & 0x04) {
1373             continue;
1374         }
1375         FX_BOOL bFind = TRUE;
1376         if (fields != NULL) {
1377             bFind = fields->Find(pField, 0) >= 0;
1378         }
1379         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1380             CPDF_Dictionary *pFieldDict = pField->m_pDict;
1381             if ((dwFlags & 0x02) != 0 && pFieldDict->GetString("V").IsEmpty()) {
1382                 return pField;
1383             }
1384         }
1385     }
1386     return NULL;
1387 }
1388 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, FX_BOOL bSimpleFileSpec) const
1389 {
1390     CFX_PtrArray fields;
1391     int nCount = m_pFieldTree->m_Root.CountFields();
1392     for (int i = 0; i < nCount; i ++) {
1393         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1394         fields.Add(pField);
1395     }
1396     return ExportToFDF(pdf_path, fields, TRUE, bSimpleFileSpec);
1397 }
1398 CFX_WideString FILESPEC_EncodeFileName(const CFX_WideStringC& filepath);
1399 CFDF_Document* CPDF_InterForm::ExportToFDF(const CFX_WideStringC& pdf_path, CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bSimpleFileSpec) const
1400 {
1401     CFDF_Document* pDoc = CFDF_Document::CreateNewDoc();
1402     if (pDoc == NULL) {
1403         return NULL;
1404     }
1405     CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDict("FDF");
1406     if (!pdf_path.IsEmpty()) {
1407         if (bSimpleFileSpec) {
1408             CFX_WideString wsFilePath = FILESPEC_EncodeFileName(pdf_path);
1409             pMainDict->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(wsFilePath));
1410             pMainDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsFilePath));
1411         } else {
1412             CPDF_FileSpec filespec;
1413             filespec.SetFileName(pdf_path);
1414             pMainDict->SetAt("F", (CPDF_Object*)filespec);
1415         }
1416     }
1417     CPDF_Array* pFields = CPDF_Array::Create();
1418     if (pFields == NULL) {
1419         return NULL;
1420     }
1421     pMainDict->SetAt("Fields", pFields);
1422     int nCount = m_pFieldTree->m_Root.CountFields();
1423     for (int i = 0; i < nCount; i ++) {
1424         CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
1425         if (pField == NULL || pField->GetType() == CPDF_FormField::PushButton) {
1426             continue;
1427         }
1428         FX_DWORD dwFlags = pField->GetFieldFlags();
1429         if (dwFlags & 0x04) {
1430             continue;
1431         }
1432         FX_BOOL bFind = fields.Find(pField, 0) >= 0;
1433         if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
1434             if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetString("V").IsEmpty()) {
1435                 continue;
1436             }
1437             CFX_WideString fullname = GetFullName(pField->GetFieldDict());
1438             CPDF_Dictionary* pFieldDict = CPDF_Dictionary::Create();
1439             if (pFieldDict == NULL) {
1440                 return NULL;
1441             }
1442             CPDF_String* pString = CPDF_String::Create(fullname);
1443             if (pString == NULL) {
1444                 pFieldDict->Release();
1445                 return NULL;
1446             }
1447             pFieldDict->SetAt("T", pString);
1448             if (pField->GetType() == CPDF_FormField::CheckBox || pField->GetType() == CPDF_FormField::RadioButton) {
1449                 CFX_WideString csExport = pField->GetCheckValue(FALSE);
1450                 CFX_ByteString csBExport = PDF_EncodeText(csExport);
1451                 CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
1452                 if (pOpt == NULL) {
1453                     pFieldDict->SetAtName("V", csBExport);
1454                 } else {
1455                     pFieldDict->SetAtString("V", csBExport);
1456                 }
1457             } else {
1458                 CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
1459                 if (pV != NULL) {
1460                     pFieldDict->SetAt("V", pV->Clone(TRUE));
1461                 }
1462             }
1463             pFields->Add(pFieldDict);
1464         }
1465     }
1466     return pDoc;
1467 }
1468 const struct _SupportFieldEncoding {
1469     const FX_CHAR* m_name;
1470     int32_t m_codePage;
1471 } g_fieldEncoding[] = {
1472     { "BigFive", 950 },
1473     { "GBK", 936 },
1474     { "Shift-JIS", 932 },
1475     { "UHC", 949 },
1476 };
1477 static void FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary *pFieldDict, CFX_WideString &csValue, CFX_ByteString &bsEncoding)
1478 {
1479     ASSERT(pFieldDict != NULL);
1480     CFX_ByteString csBValue = pFieldDict->GetString("V");
1481     int32_t iCount = sizeof(g_fieldEncoding) / sizeof(g_fieldEncoding[0]);
1482     int32_t i = 0;
1483     for (; i < iCount; ++i)
1484         if (bsEncoding == g_fieldEncoding[i].m_name) {
1485             break;
1486         }
1487     if (i < iCount) {
1488         CFX_CharMap *pCharMap = CFX_CharMap::GetDefaultMapper(g_fieldEncoding[i].m_codePage);
1489         FXSYS_assert(pCharMap != NULL);
1490         csValue.ConvertFrom(csBValue, pCharMap);
1491         return;
1492     }
1493     CFX_ByteString csTemp = csBValue.Left(2);
1494     if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") {
1495         csValue = PDF_DecodeText(csBValue);
1496     } else {
1497         csValue = CFX_WideString::FromLocal(csBValue);
1498     }
1499 }
1500 void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, const CFX_WideString& parent_name, FX_BOOL bNotify, int nLevel)
1501 {
1502     CFX_WideString name;
1503     if (!parent_name.IsEmpty()) {
1504         name = parent_name + L".";
1505     }
1506     name += pFieldDict->GetUnicodeText("T");
1507     CPDF_Array* pKids = pFieldDict->GetArray("Kids");
1508     if (pKids) {
1509         for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
1510             CPDF_Dictionary* pKid = pKids->GetDict(i);
1511             if (pKid == NULL) {
1512                 continue;
1513             }
1514             if (nLevel <= nMaxRecursion) {
1515                 FDF_ImportField(pKid, name, bNotify, nLevel + 1);
1516             }
1517         }
1518         return;
1519     }
1520     if (!pFieldDict->KeyExist("V")) {
1521         return;
1522     }
1523     CPDF_FormField* pField = m_pFieldTree->GetField(name);
1524     if (pField == NULL) {
1525         return;
1526     }
1527     CFX_WideString csWValue;
1528     FPDFDOC_FDF_GetFieldValue(pFieldDict, csWValue, m_bsEncoding);
1529     int iType = pField->GetFieldType();
1530     if (bNotify && m_pFormNotify != NULL) {
1531         int iRet = 0;
1532         if (iType == FIELDTYPE_LISTBOX) {
1533             iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue);
1534         } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1535             iRet = m_pFormNotify->BeforeValueChange(pField, csWValue);
1536         }
1537         if (iRet < 0) {
1538             return;
1539         }
1540     }
1541     CFX_ByteArray statusArray;
1542     if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1543         SaveCheckedFieldStatus(pField, statusArray);
1544     }
1545     pField->SetValue(csWValue);
1546     CPDF_FormField::Type eType = pField->GetType();
1547     if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && pFieldDict->KeyExist("Opt")) {
1548         pField->m_pDict->SetAt("Opt", pFieldDict->GetElementValue("Opt")->Clone(TRUE));
1549     }
1550     if (bNotify && m_pFormNotify != NULL) {
1551         if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
1552             m_pFormNotify->AfterCheckedStatusChange(pField, statusArray);
1553         } else if (iType == FIELDTYPE_LISTBOX) {
1554             m_pFormNotify->AfterSelectionChange(pField);
1555         } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
1556             m_pFormNotify->AfterValueChange(pField);
1557         }
1558     }
1559     if (CPDF_InterForm::m_bUpdateAP) {
1560         pField->UpdateAP(NULL);
1561     }
1562 }
1563 FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, FX_BOOL bNotify)
1564 {
1565     if (pFDF == NULL) {
1566         return FALSE;
1567     }
1568     CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
1569     if (pMainDict == NULL) {
1570         return FALSE;
1571     }
1572     CPDF_Array* pFields = pMainDict->GetArray("Fields");
1573     if (pFields == NULL) {
1574         return FALSE;
1575     }
1576     m_bsEncoding = pMainDict->GetString(FX_BSTRC("Encoding"));
1577     if (bNotify && m_pFormNotify != NULL) {
1578         int iRet = m_pFormNotify->BeforeFormImportData(this);
1579         if (iRet < 0) {
1580             return FALSE;
1581         }
1582     }
1583     for (FX_DWORD i = 0; i < pFields->GetCount(); i ++) {
1584         CPDF_Dictionary* pField = pFields->GetDict(i);
1585         if (pField == NULL) {
1586             continue;
1587         }
1588         FDF_ImportField(pField, L"", bNotify);
1589     }
1590     if (bNotify && m_pFormNotify != NULL) {
1591         m_pFormNotify->AfterFormImportData(this);
1592     }
1593     return TRUE;
1594 }
1595 void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify)
1596 {
1597     m_pFormNotify = (CPDF_FormNotify*)pNotify;
1598 }
1599 int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext)
1600 {
1601     if (iCurPage < 0) {
1602         return -1;
1603     }
1604     int iPageCount = m_pDocument->GetPageCount();
1605     if (iCurPage >= iPageCount) {
1606         return -1;
1607     }
1608     int iNewPage = iCurPage;
1609     do {
1610         iNewPage += bNext ? 1 : -1;
1611         if (iNewPage >= iPageCount) {
1612             iNewPage = 0;
1613         }
1614         if (iNewPage < 0) {
1615             iNewPage = iPageCount - 1;
1616         }
1617         if (iNewPage == iCurPage) {
1618             break;
1619         }
1620         CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage);
1621         if (pPageDict == NULL) {
1622             continue;
1623         }
1624         CPDF_Array* pAnnots = pPageDict->GetArray("Annots");
1625         if (pAnnots == NULL) {
1626             continue;
1627         }
1628         FX_DWORD dwCount = pAnnots->GetCount();
1629         for (FX_DWORD i = 0; i < dwCount; i ++) {
1630             CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i);
1631             if (pAnnotDict == NULL) {
1632                 continue;
1633             }
1634             CPDF_FormControl* pControl = NULL;
1635             if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) {
1636                 return iNewPage;
1637             }
1638         }
1639     } while (TRUE);
1640     return -1;
1641 }